emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/cider 5ad3f380df 4/4: Move helper functions to own file, f


From: ELPA Syncer
Subject: [nongnu] elpa/cider 5ad3f380df 4/4: Move helper functions to own file, fix test issue with client conn
Date: Thu, 8 Dec 2022 10:58:40 -0500 (EST)

branch: elpa/cider
commit 5ad3f380dfbf9126e9f5bed63926f7cf7e428f87
Author: ikappaki <ikappaki@users.noreply.github.com>
Commit: Bozhidar Batsov <bozhidar@batsov.dev>

    Move helper functions to own file, fix test issue with client conn
    
    Changes
    1. Created integration-test-utils.el to collect increasing number of
    integration helper functions.
    1. A `with-cider-test-sandbox` macro is introduced to restore cider
    state after test has finished.
    2. The `cider-itu-poll-until` helper function is introduced to replace
    `nrepl-tests-sleep-until`, this fn now throws if condition does not
    become true after the timeout has elapsed.
    3. There was an issue with the previous attempt to add a hook and
    return a value for the test to poll when he client is connected to
    the nREPL. The hook was naively attached to the temp buffer, which is
    not necessarily in scope when the hook is run. A new
    `cider-itu-nrepl-client-connected-ref-make!` replaces that fn, that
    now returns a global variable ref, and has to be called inside
    `with-cider-test-sandbox` so that the hook variable is restored after
    the test finishes.
    4. Introduced tests to test the new integration tests helper functions.
    5. All integration tests are updated to use the new functions mentioned 
above.
    6. Rename `connected?` to `is-connected` as per review comments.
    7. Restore `nrepl-client-tests.el` update which was overwritten with
    previous commit.
---
 test/integration/integration-test-utils.el | 114 +++++++++++++++++++
 test/integration/integration-tests.el      | 169 +++++++++++++----------------
 test/nrepl-client-tests.el                 |  13 ++-
 3 files changed, 195 insertions(+), 101 deletions(-)

diff --git a/test/integration/integration-test-utils.el 
b/test/integration/integration-test-utils.el
new file mode 100644
index 0000000000..a8cc7b081b
--- /dev/null
+++ b/test/integration/integration-test-utils.el
@@ -0,0 +1,114 @@
+;;; integration-test-utils.el  -*- lexical-binding: t; -*-
+
+;; Copyright © 2022 Ioannis Kappas
+
+;; This file is NOT part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see `http://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;; Helper utils for use by integration tests.
+;;
+;; All helper functions should begin with `cider-itu-`.
+
+;; This file is part of CIDER
+
+;;; Code:
+
+(require 'buttercup)
+(require 'cider)
+(require 'cl-lib)
+
+(defmacro with-cider-test-sandbox (&rest body)
+  "Run BODY inside sandbox, with key cider global vars restored on exit.
+
+Only the following variables are currently restored, please add more as the
+test coverage increases:
+
+`cider-connected-hook`."
+  (declare (indent 0))
+  ;; for dynamic vars, just use a binding under the same name.
+  `(let ((cider-connected-hook cider-connected-hook))
+     ,@body))
+
+;; https://emacs.stackexchange.com/a/55031
+(defmacro with-temp-dir (temp-dir &rest body)
+  "Create a temporary directory and bind it to TEMP-DIR while evaluating BODY.
+Remove the temp directory at the end of evaluation."
+  (declare (indent 1))
+  `(let ((,temp-dir (make-temp-file "" t)))
+    (unwind-protect
+      (progn
+        ,@body)
+      (condition-case err
+          (delete-directory ,temp-dir t)
+        (error
+         (message ":with-temp-dir-error :cannot-remove-temp-dir %S" err))))))
+
+(defmacro cider-itu-poll-until (condition timeout-secs)
+  "Poll every 0.2 secs until CONDITION becomes true or error out if 
TIMEOUT-SECS elapses."
+  (let* ((interval-secs 0.2)
+         (count (truncate (/ timeout-secs interval-secs))))
+    `(cl-loop repeat ,count
+              for condition = ,condition
+              if condition
+                return condition
+              else
+                do (sleep-for ,interval-secs)
+              finally (error ":cider-itu-poll-until-errored 
:timed-out-after-secs %d :waiting-for %S"
+                               ,timeout-secs (quote ,condition)))))
+
+(defun cider-itu-nrepl-client-connected-ref-make! ()
+  "Returns a gv ref to signal when the client is connected to the nREPL server.
+This is done by adding a hook to `cider-connected-hook' and must be run
+inside `with-cider-test-sandbox'.
+
+Use `gv-deref' to deref the value.
+
+The generalized variable can have the following values
+
+'!connected the client has not yet connected to the nREPL server.
+'connected  the client has connected to the nREPL server."
+  (let ((is-connected '!connected))
+    (add-hook 'cider-connected-hook
+              (lambda ()
+                (setq is-connected 'connected)))
+    (gv-ref is-connected)))
+
+(describe "in integration utils test"
+  (it "that cider-itu-poll-until works when sexpr eventually becomes true."
+    (let ((stack '(nil 123 456)))
+      (expect (cider-itu-poll-until (progn (message ":looping... %S" stack) 
(pop stack)) 1) :to-equal 123)
+      (expect stack :to-equal '(456)))
+    (expect (cider-itu-poll-until nil 1) :to-throw 'error))
+
+  (it "that sand box can restore CIDER global vars."
+    (let ((count (length cider-connected-hook)))
+      (with-cider-test-sandbox
+       (add-hook 'cider-connected-hook (lambda ()))
+       (expect (length cider-connected-hook) :to-be (1+ count)))
+      (expect (length cider-connected-hook) :to-be count)))
+
+  (it "that `cider-itu-nrepl-client-connected-ref-make!' return ref changes 
value when client is connected."
+    (with-cider-test-sandbox
+      (let ((is-connected* (cider-itu-nrepl-client-connected-ref-make!)))
+        (expect (gv-deref is-connected*) :to-equal '!connected)
+        (run-hooks 'cider-connected-hook)
+        (expect (gv-deref is-connected*) :to-equal 'connected)))))
+
+
+(provide 'integration-test-utils)
+
+;;; integration-test-utils.el ends here
diff --git a/test/integration/integration-tests.el 
b/test/integration/integration-tests.el
index 94a9fc40e0..2baa6e77fb 100644
--- a/test/integration/integration-tests.el
+++ b/test/integration/integration-tests.el
@@ -29,41 +29,18 @@
 (require 'cider)
 (require 'nrepl-dict)
 (require 'nrepl-tests-utils "test/utils/nrepl-tests-utils")
-
-;; https://emacs.stackexchange.com/a/55031
-(defmacro with-temp-dir (temp-dir &rest body)
-  "Create a temporary directory and bind it to TEMP-DIR while evaluating BODY.
-Remove the temp directory at the end of evaluation."
-  `(let ((,temp-dir (make-temp-file "" t)))
-    (unwind-protect
-      (progn
-        ,@body)
-      (condition-case err
-          (delete-directory ,temp-dir t)
-        (error
-         (message ":with-temp-dir-error :cannot-remove-temp-dir %S" err))))))
-
-(defun nrepl-client-connected?-ref-make! ()
-  "Return a reference to indicate when the client is connected to nREPL server.
-This is done by adding a hook to `cider-connected-hook` and is only active
-in the scope of the current buffer."
-  (let (connected?)
-    (add-hook 'cider-connected-hook
-              (lambda ()
-                (setq connected? t))
-              nil
-              ;; only set in the current buffer scope.
-              t)))
-
+(require 'integration-test-utils)
 
 (describe "jack in"
-  ;; See "bb" case for basic commentary
+  ;; See "babashka" case for commentary on the base template used by all other
+  ;; tests.
   ;;
   ;; It has been observed that some REPLs (Clojure cli, shadow) might take a
   ;; very long time to bring up/respond/shutdown, and thus sleep duration 
values
   ;; are set rather high.
 
   (it "to babashka"
+    (with-cider-test-sandbox
       (with-temp-dir temp-dir
         ;; set up a project directory in temp
         (let* ((project-dir temp-dir)
@@ -75,18 +52,20 @@ in the scope of the current buffer."
             (setq-local default-directory project-dir)
 
             (unwind-protect
-                ;; jack in and get repl buffer
-                (let* ((client-connected?* (nrepl-client-connected?-ref-make!))
+                (let* (;; Get a gv reference so as to poll if the client has
+                       ;; connected to the nREPL server.
+                       (client-is-connected* 
(cider-itu-nrepl-client-connected-ref-make!))
+
+                       ;; jack in and get repl buffer
                        (nrepl-proc (cider-jack-in-clj '()))
                        (nrepl-buf (process-buffer nrepl-proc)))
 
                   ;; wait until the client has successfully connected to the
                   ;; nREPL server.
-                  (nrepl-tests-sleep-until 5 client-connected?*)
-                  (expect client-connected?*)
+                  (cider-itu-poll-until (eq (gv-deref client-is-connected*) 
'connected) 5)
 
                   ;; give it some time to setup the clj REPL
-                  (nrepl-tests-sleep-until 5 (cider-repls 'clj nil))
+                  (cider-itu-poll-until (cider-repls 'clj nil) 5)
 
                   ;; send command to the REPL, and stdout/stderr to
                   ;; corresponding eval- variables.
@@ -107,7 +86,7 @@ in the scope of the current buffer."
                          (when out (push out eval-out)))) )
 
                     ;; wait for the response to come back.
-                    (nrepl-tests-sleep-until 5 eval-out)
+                    (cider-itu-poll-until eval-out 5)
 
                     ;; ensure there are no errors and response is as expected.
                     (expect eval-err :to-equal '())
@@ -117,15 +96,16 @@ in the scope of the current buffer."
                     (cider-quit repl-buffer)
 
                     ;; wait for the REPL to exit
-                    (nrepl-tests-sleep-until 5 (not (eq (process-status 
nrepl-proc) 'run)))
+                    (cider-itu-poll-until (not (eq (process-status nrepl-proc) 
'run)) 5)
                     (expect (member (process-status nrepl-proc) '(exit 
signal)))))
 
               ;; useful for debugging on errors
               (when-let ((nrepl-error-buffer (get-buffer "*nrepl-error*")))
                 (with-current-buffer nrepl-error-buffer
-                  (message ":*nrepl-error* %S" (substring-no-properties 
(buffer-string))))))))))
+                  (message ":*nrepl-error* %S" (substring-no-properties 
(buffer-string)))))))))))
 
   (it "to clojure tools cli"
+    (with-cider-test-sandbox
       (with-temp-dir temp-dir
         (let* ((project-dir temp-dir)
                (deps-edn (expand-file-name "deps.edn" project-dir)))
@@ -133,14 +113,12 @@ in the scope of the current buffer."
           (with-temp-buffer
             (setq-local default-directory project-dir)
             (unwind-protect
-                (let* ((client-connected?* (nrepl-client-connected?-ref-make!))
+                (let* ((client-is-connected* 
(cider-itu-nrepl-client-connected-ref-make!))
                        (nrepl-proc (cider-jack-in-clj `()))
                        (nrepl-buf (process-buffer nrepl-proc)))
-                  (nrepl-tests-sleep-until 5 client-connected?*)
-                  (expect client-connected?*)
-
                   ;; high duration since on windows it takes a long time to 
startup
-                  (nrepl-tests-sleep-until 90 (cider-repls 'clj nil))
+                  (cider-itu-poll-until (eq (gv-deref client-is-connected*) 
'connected) 90)
+                  (cider-itu-poll-until (cider-repls 'clj nil) 90)
                   (let ((repl-buffer (cider-current-repl))
                         (eval-err '())
                         (eval-out '()))
@@ -153,17 +131,18 @@ in the scope of the current buffer."
                            (out err)
                          (when err (push err eval-err))
                          (when out (push out eval-out)))) )
-                    (nrepl-tests-sleep-until 10 eval-out)
+                    (cider-itu-poll-until eval-out 10)
                     (expect eval-err :to-equal '())
                     (expect eval-out :to-equal '(":clojure? true"))
                     (cider-quit repl-buffer)
-                    (nrepl-tests-sleep-until 15 (not (eq (process-status 
nrepl-proc) 'run)))
+                    (cider-itu-poll-until (not (eq (process-status nrepl-proc) 
'run)) 15)
                     (expect (member (process-status nrepl-proc) '(exit 
signal)))))
               (when-let ((nrepl-error-buffer (get-buffer "*nrepl-error*")))
                 (with-current-buffer nrepl-error-buffer
-                  (message ":*nrepl-error* %S" (substring-no-properties 
(buffer-string))))))))))
+                  (message ":*nrepl-error* %S" (substring-no-properties 
(buffer-string)))))))))))
 
   (it "to leiningen"
+    (with-cider-test-sandbox
       (with-temp-dir temp-dir
         (let* ((project-dir temp-dir)
                (project-clj (expand-file-name "project.clj" project-dir)))
@@ -173,12 +152,11 @@ in the scope of the current buffer."
           (with-temp-buffer
             (setq-local default-directory project-dir)
             (unwind-protect
-                (let* ((client-connected?* (nrepl-client-connected?-ref-make!))
+                (let* ((client-is-connected* 
(cider-itu-nrepl-client-connected-ref-make!))
                        (nrepl-proc (cider-jack-in-clj `()))
                        (nrepl-buf (process-buffer nrepl-proc)))
-                  (nrepl-tests-sleep-until 5 client-connected?*)
-                  (expect client-connected?*)
-                  (nrepl-tests-sleep-until 90 (cider-repls 'clj nil))
+                  (cider-itu-poll-until (eq (gv-deref client-is-connected*) 
'connected) 90)
+                  (cider-itu-poll-until (cider-repls 'clj nil) 90)
                   (let ((repl-buffer (cider-current-repl))
                         (eval-err '())
                         (eval-out '()))
@@ -191,68 +169,67 @@ in the scope of the current buffer."
                            (out err)
                          (when err (push err eval-err))
                          (when out (push out eval-out)))) )
-                    (nrepl-tests-sleep-until 10 eval-out)
+                    (cider-itu-poll-until eval-out 10)
                     (expect eval-err :to-equal '())
                     (expect eval-out :to-equal '(":clojure? true"))
                     (cider-quit repl-buffer)
-                    (nrepl-tests-sleep-until 15 (not (eq (process-status 
nrepl-proc) 'run)))
+                    (cider-itu-poll-until (not (eq (process-status nrepl-proc) 
'run)) 15)
                     (expect (member (process-status nrepl-proc) '(exit 
signal)))
                     (sleep-for 0.5)))
               (when-let ((nrepl-error-buffer (get-buffer "*nrepl-error*")))
                 (with-current-buffer nrepl-error-buffer
                   (message ":*nrepl-error* %S"
-                           (substring-no-properties (buffer-string))))))))))
+                           (substring-no-properties (buffer-string)))))))))))
 
   (it "to shadow"
       ;; shadow asks user whether they want to open a browser, force to no
       (spy-on 'y-or-n-p)
 
-      (with-temp-dir temp-dir
-        (let* ((project-dir temp-dir)
-               (shadow-cljs-edn (expand-file-name "shadow-cljs.edn" 
project-dir))
-               (package-json    (expand-file-name "package.json"    
project-dir)))
-          (write-region "{}" nil shadow-cljs-edn)
-          (write-region "{\"dependencies\":{\"shadow-cljs\": \"^2.20.13\"}}" 
nil package-json)
-          (let ((default-directory project-dir))
-            (message ":npm-install...")
-            (shell-command "npm install")
-            (message ":npm-install :done"))
-          (let ((cider-preferred-build-tool 'shadow-cljs)
-                ;; request for a node repl, so that shadow forks one.
-                (cider-shadow-default-options ":node-repl"))
-            (with-temp-buffer
-              (setq-local default-directory project-dir)
-              (unwind-protect
-                  (let* ((client-connected?* 
(nrepl-client-connected?-ref-make!))
-                         (nrepl-proc (cider-jack-in-cljs '(:cljs-repl-type 
shadow)))
-                         (nrepl-buf (process-buffer nrepl-proc)))
-                    (nrepl-tests-sleep-until 5 client-connected?*)
-                    (expect client-connected?*)
-                    (nrepl-tests-sleep-until 120 (cider-repls 'cljs nil))
-                    (expect (cider-repls 'cljs nil) :not :to-be nil)
-                    (let ((repl-buffer (cider-current-repl))
-                          (eval-err '())
-                          (eval-out '()))
-                      (expect repl-buffer :not :to-be nil)
-                      (sleep-for 2)
-                      (cider-interactive-eval
-                       "(print :cljs? (some? *clojurescript-version*))"
-                       (lambda (return)
-                         (nrepl-dbind-response
-                             return
-                             (out err)
-                           (when err (push err eval-err))
-                           (when out (push out eval-out)))) )
-                      (nrepl-tests-sleep-until 10 eval-out)
-                      (expect eval-err :to-equal '())
-                      (expect eval-out :to-equal '(":cljs? true\n"))
-                      (cider-quit repl-buffer)
-                      (nrepl-tests-sleep-until 15 (not (eq (process-status 
nrepl-proc) 'run)))
-                      (expect (member (process-status nrepl-proc) '(exit 
signal)))))
-                (when-let ((nrepl-error-buffer (get-buffer "*nrepl-error*")))
-                  (with-current-buffer nrepl-error-buffer
-                    (message ":*nrepl-error* %S"
-                             (substring-no-properties 
(buffer-string))))))))))))
+      (with-cider-test-sandbox
+          (with-temp-dir temp-dir
+            (let* ((project-dir temp-dir)
+                   (shadow-cljs-edn (expand-file-name "shadow-cljs.edn" 
project-dir))
+                   (package-json    (expand-file-name "package.json"    
project-dir)))
+              (write-region "{}" nil shadow-cljs-edn)
+              (write-region "{\"dependencies\":{\"shadow-cljs\": 
\"^2.20.13\"}}" nil package-json)
+              (let ((default-directory project-dir))
+                (message ":npm-install...")
+                (shell-command "npm install")
+                (message ":npm-install :done"))
+              (let ((cider-preferred-build-tool 'shadow-cljs)
+                    ;; request for a node repl, so that shadow forks one.
+                    (cider-shadow-default-options ":node-repl"))
+                (with-temp-buffer
+                  (setq-local default-directory project-dir)
+                  (unwind-protect
+                      (let* ((client-is-connected* 
(cider-itu-nrepl-client-connected-ref-make!))
+                             (nrepl-proc (cider-jack-in-cljs '(:cljs-repl-type 
shadow)))
+                             (nrepl-buf (process-buffer nrepl-proc)))
+                        (cider-itu-poll-until (eq (gv-deref 
client-is-connected*) 'connected) 120)
+                        (cider-itu-poll-until (cider-repls 'cljs nil) 120)
+                        (let ((repl-buffer (cider-current-repl))
+                              (eval-err '())
+                              (eval-out '()))
+                          (expect repl-buffer :not :to-be nil)
+                          (sleep-for 2)
+                          (cider-interactive-eval
+                           "(print :cljs? (some? *clojurescript-version*))"
+                           (lambda (return)
+                             (nrepl-dbind-response
+                                 return
+                                 (out err)
+                               (when err (push err eval-err))
+                               (when out (push out eval-out)))) )
+                          (cider-itu-poll-until eval-out 10)
+                          (expect eval-err :to-equal '())
+                          (expect eval-out :to-equal '(":cljs? true\n"))
+                          (cider-quit repl-buffer)
+                          (cider-itu-poll-until (not (eq (process-status 
nrepl-proc) 'run)) 15)
+                          (expect (member (process-status nrepl-proc) '(exit 
signal)))))
+                    (when-let ((nrepl-error-buffer (get-buffer 
"*nrepl-error*")))
+                      (with-current-buffer nrepl-error-buffer
+                        (message ":*nrepl-error* %S"
+                                 (substring-no-properties 
(buffer-string)))))))))))))
 
 (provide 'integration-tests)
 
diff --git a/test/nrepl-client-tests.el b/test/nrepl-client-tests.el
index 4f57a24cc0..b8da9bcccc 100644
--- a/test/nrepl-client-tests.el
+++ b/test/nrepl-client-tests.el
@@ -159,7 +159,8 @@
         ;; server has reported its endpoint
         (nrepl-tests-sleep-until 2 server-endpoint)
         (expect server-endpoint :not :to-be nil)
-
+        (expect (plist-get (process-plist server-process) 
:cider--nrepl-server-ready)
+                :to-equal t)
         (condition-case error-details
             ;; start client process
             (let* ((client-buffer (get-buffer-create 
":nrepl-lifecycle/client"))
@@ -182,10 +183,12 @@
               (delete-process process-client)
 
               ;; server process has been signalled
-              (nrepl-tests-sleep-until 4 (eq (process-status server-process)
-                                             'signal))
-              (expect (process-status server-process)
-                      :to-equal 'signal))
+              (nrepl-tests-sleep-until 4 (member (process-status 
server-process)
+                                                 '(exit signal)))
+              (expect (let ((status (process-status server-process)))
+                        (if (eq system-type 'windows-nt)
+                            (eq status 'exit)
+                          (eq status 'signal)))))
           (error
            ;; there may be some useful information in the nrepl buffer on error
            (when-let ((nrepl-error-buffer (get-buffer "*nrepl-error*")))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]