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

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

[nongnu] elpa/cider a4b8ab1e0d 1/4: Introduce integration tests


From: ELPA Syncer
Subject: [nongnu] elpa/cider a4b8ab1e0d 1/4: Introduce integration tests
Date: Thu, 8 Dec 2022 10:58:39 -0500 (EST)

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

    Introduce integration tests
    
    1. Migrated macos regression tests to circle ci, but with a reduced set to 
only cover Emacs latest version.
    2. Replaced existing macos only testing github action to run the 
integration tests across macos, ubuntu and windows latest on Emacs 28, 27 and 
26. It was nearly impossible to do so on circleci across all platforms, thus a 
github action was chosen.
    3. Updated the `Eldev` project file to support integration test via a new 
`--test-type` command line option (the template was taken from the `Eldev` 
tool's project file itself).
    4. The cider server is given now a 0.5 sec opportunity to execute the 
`close` op before the server is killed.
    5. The hacking section in documentation has been updated to mention 
integration tests.
    6. The `nrepl--kill-process` has been updated to address the orphaned child 
process menace under MS-Windows, whereby the nREPL child processes were most 
likely to be left orphaned after the parent process was killed. The kill is now 
done by contracting the external `taskkill` windows program to do the job if 
available, and falls back to the previous logic otherwise.
    7. The `nrepl-server-sentinel` has been simplified to only report an error 
if the nREPL process couldn't bootstrap itself, or send an exit message 
otherwise. The old code only closed client connections on `hangup` (i.e. HUP 
signal), but the new logic will close clients on any fatal signal. Not sure why 
the old code only did this on HUP, but it seems sensible to me that any open 
client connection should close when the server has exited.
    8. Fixed an issue in `cider-tests.el` that a couple of buffer local 
shadow-cljs variables were set as global by mistake, thus affecting other tests 
(and in particular the integration tests).
    9. Updated nrepl-client-tests.el to test the new nrepl plist property to 
indicate that the nREPL server has been successfully brought up, and also test 
that the new process-status `exit` returned on MS-Windows with `taskkill` is 
set.
    10. Introduced integration tests covering jack-in for bb, clojure cli, lein 
and shadow.
---
 .circleci/config.yml                             |  20 ++
 .codespellrc                                     |   2 +
 .github/workflows/test.yml                       |  52 ++++-
 Eldev                                            |  36 +++-
 cider-connection.el                              |   2 +
 doc/modules/ROOT/pages/contributing/hacking.adoc |  15 +-
 nrepl-client.el                                  |  92 ++++++---
 test/cider-tests.el                              |  11 +-
 test/integration/integration-tests.el            | 231 +++++++++++++++++++++++
 test/nrepl-client-tests.el                       |  13 +-
 test/utils/nrepl-tests-utils.el                  |  16 ++
 11 files changed, 439 insertions(+), 51 deletions(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index ea36a7402e..3fbd3084fa 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -15,6 +15,18 @@ commands:
           name: Install unzip
           command: apt-get update && apt-get install unzip
 
+  macos-setup:
+    steps:
+      - checkout
+      - run:
+          name: Install Emacs latest
+          command: |
+            echo "HOMEBREW_NO_AUTO_UPDATE=1" >> $BASH_ENV
+            brew install homebrew/cask/emacs
+      - run:
+          name: Install Eldev
+          command: curl -fsSL 
https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev > x.sh && 
source ./x.sh
+
   setup-windows:
     steps:
       - checkout
@@ -74,6 +86,13 @@ jobs:
       - setup
       - test
 
+  test-macos-emacs-latest:
+    macos:
+      xcode: "14.0.0"
+    steps:
+      - macos-setup
+      - test
+
   test-windows-emacs-latest:
     executor: win/default
     steps:
@@ -100,4 +119,5 @@ workflows:
       - test-emacs-28
       - test-emacs-master
       - test-lint
+      - test-macos-emacs-latest
       - test-windows-emacs-latest
diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 0000000000..902abb29f2
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,2 @@
+[codespell]
+skip = .git,.eldev,logo
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6dbf5d833c..efc548ab52 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -3,26 +3,68 @@ name: CI
 on: [push, pull_request]
 
 jobs:
-  test:
+  integration:
+    # Run integration tests for all OSs and EMACS_VERSIONs.
     runs-on: ${{matrix.os}}
 
     strategy:
       matrix:
-        os: [macos-latest]
-        emacs_version: ['26.3', '27.2', '28.1']
+        os: [macos-latest, ubuntu-latest, windows-latest]
+        emacs_version: ['26.3', '27.2', '28.2']
 
     steps:
     - name: Set up Emacs
+      if: "!startsWith (matrix.os, 'windows')"
       uses: purcell/setup-emacs@master
       with:
         version: ${{matrix.emacs_version}}
 
+    - name: Set up Emacs on Windows
+      if: startsWith (matrix.os, 'windows')
+      uses: jcs090218/setup-emacs-windows@master
+      with:
+        version: ${{matrix.emacs_version}}
+
     - name: Install Eldev
+      if: "!startsWith (matrix.os, 'windows')"
       run: curl -fsSL 
https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh
 
+    - name: Install Eldev on MS-Windows
+      if: startsWith (matrix.os, 'windows')
+      run: |
+        # Remove expired DST Root CA X3 certificate. Workaround
+        # for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=51038
+        # bug on Emacs 27.2.
+        gci cert:\LocalMachine\Root\DAC9024F54D8F6DF94935FB1732638CA6AD77C13
+        gci cert:\LocalMachine\Root\DAC9024F54D8F6DF94935FB1732638CA6AD77C13 | 
Remove-Item
+
+        curl.exe -fsSL 
https://raw.github.com/doublep/eldev/master/webinstall/github-eldev.bat | cmd /Q
+
     - name: Check out the source code
       uses: actions/checkout@v2
 
-    - name: Test the project
+    - name: Prepare java
+      uses: actions/setup-java@v3
+      with:
+        distribution: 'temurin'
+        # shadow requires java 11
+        java-version: 11
+
+    - name: Install Clojure Tools
+      # Use SHA until
+      # https://github.com/DeLaGuardo/setup-clojure/issues/78 is
+      # released
+      uses: DeLaGuardo/setup-clojure@1376ded6747c79645e82c856f16375af5f5de307
+      with:
+        bb: '1.0.165'
+        cli: '1.10.3.1013'
+        lein: '2.9.10'
+
+    - uses: actions/setup-node@v3
+      with:
+        node-version: 16
+    - run: npm install shadow-cljs@2.20.13 -g
+
+    - name: Test integration
       run: |
-        eldev -p -dtT test
+        eldev -p -dtTC test --test-type integration
diff --git a/Eldev b/Eldev
index d70c016779..a4cbaf2615 100644
--- a/Eldev
+++ b/Eldev
@@ -10,12 +10,36 @@
 
 (eldev-add-loading-roots 'test "test/utils")
 
-;; Otherwise `cider-test.el' will be considered a test file.
-(setf eldev-test-fileset "./test/")
-;; This file is _supposed_ to be excluded from automated testing.  Since Eldev
-;; uses everything inside `test/' subdirectory, tell it to leave this file 
alone
-;; explicitly.
-(setf eldev-standard-excludes `(:or ,eldev-standard-excludes 
"test/cider-tests--no-auto.el"))
+(defvar cider-test-type 'main)
+(setf eldev-standard-excludes `(:or ,eldev-standard-excludes
+                                    ;; Avoid including files in test 
"projects".
+                                    (eldev-pcase-exhaustive cider-test-type
+                                                            (`main        
"./test/*/")
+                                                            (`integration 
'("./test/"   "!./test/integration"))
+                                                            (`all         
'("./test/*/" "!./test/integration")))
+                                    "test/integration/projects"
+                                    ;; This file is _supposed_ to be excluded
+                                    ;; from automated testing.
+                                    "test/cider-tests--no-auto.el"))
+
+(eldev-defoption cider-test-selection (type)
+  "Select tests to run; type can be `main', `integration' or `all'"
+  :options        (-T --test-type)
+  :for-command    test
+  :value          TYPE
+  :default-value  cider-test-type
+  (unless (memq (intern type) '(main integration all))
+    (signal 'eldev-wrong-option-usage `("unknown test type `%s'" ,type)))
+  (setf cider-test-type (intern type)))
+
+(add-hook 'eldev-test-hook
+          (lambda ()
+            (eldev-verbose "Using cider tests of type `%s'" cider-test-type)))
+(add-hook 'eldev-executing-command-hook
+          (lambda (command)
+            (unless (eq command 'test)
+              ;; So that e.g. byte-compilation works on all tests.
+              (setf cider-test-type 'all))))
 
 ;; CIDER cannot be compiled otherwise.
 (setf eldev-build-load-before-byte-compiling t)
diff --git a/cider-connection.el b/cider-connection.el
index f7a18d255f..a54cb2bbf4 100644
--- a/cider-connection.el
+++ b/cider-connection.el
@@ -180,6 +180,8 @@ buffer."
                      ;; Sync request will hang if the server is dead.
                      (process-live-p (get-buffer-process 
nrepl-server-buffer))))
         (nrepl-sync-request:close repl)
+        ;; give a chance to the REPL to respond to the closing of the 
connection
+        (sleep-for 0.5)
         (delete-process proc)))
     (when-let* ((messages-buffer (and nrepl-log-messages
                                       (nrepl-messages-buffer repl))))
diff --git a/doc/modules/ROOT/pages/contributing/hacking.adoc 
b/doc/modules/ROOT/pages/contributing/hacking.adoc
index 212a60852e..42247f4b1d 100644
--- a/doc/modules/ROOT/pages/contributing/hacking.adoc
+++ b/doc/modules/ROOT/pages/contributing/hacking.adoc
@@ -84,9 +84,20 @@ all the details.
 
 If you prefer running all tests outside Emacs that's also an option.
 
-Run all tests with:
+There are two test types, `main` (unit tests) and `integration`. By
+default only main tests are run.
 
- $ eldev test
+Run all unit tests with:
+
+ $ eldev[.bat] test
+
+Run integration tests with:
+
+ $ eldev[.bat] test --test-type integration
+
+or all tests with
+
+ $ eldev[.bat] test --test-type all
 
 NOTE: Tests may not run correctly inside Emacs' `shell-mode` buffers. Running
 them in a terminal is recommended.
diff --git a/nrepl-client.el b/nrepl-client.el
index 612c2e9a03..e8ac80df89 100644
--- a/nrepl-client.el
+++ b/nrepl-client.el
@@ -627,12 +627,33 @@ If NO-ERROR is non-nil, show messages instead of throwing 
an error."
 ;;; Client: Process Handling
 
 (defun nrepl--kill-process (proc)
-  "Kill PROC using the appropriate, os specific way.
-Implement a workaround to clean up an orphaned JVM process left around
-after exiting the REPL on some windows machines."
-  (if (memq system-type '(cygwin windows-nt))
-      (interrupt-process proc)
-    (kill-process proc)))
+  "Attempt to kill PROC tree.
+On MS-Windows, using the standard API is highly likely to leave the child
+processes still running in the background as orphans.  As a workaround, an
+attempt is made to delegate the task to the `taskkill` program, which comes
+with windows since at least Windows XP, and fallback to the Emacs API if it
+can't be found.
+
+It is expected that the `(process-status PROC)` return value after PROC is
+killed is `exit` when `taskkill` is used and `signal` otherwise."
+  (cond
+   ((and (eq system-type 'windows-nt)
+         (process-live-p proc)
+         (executable-find "taskkill"))
+    ;; try to use `taskkill` if available
+    (with-temp-buffer
+      (call-process-shell-command (format "taskkill /PID %s /T /F" (process-id 
proc))
+                                  nil (buffer-name) )
+      ;; useful for debugging.
+      ;;(message ":PROCESS-KILL-OUPUT %s" (buffer-string))
+      ))
+
+   ((memq system-type '(cygwin windows-nt))
+    ;; fallback, this is considered to work better than `kill-process` on
+    ;; MS-Windows.
+    (interrupt-process proc))
+
+   (t (kill-process proc))))
 
 (defun nrepl-kill-server-buffer (server-buf)
   "Kill SERVER-BUF and its process."
@@ -1090,8 +1111,22 @@ match groups:
 1  for the port, and
 2  for the host (babashka only).")
 
+(defun cider--process-plist-put (proc prop val)
+  "Change value in PROC's plist of PROP to VAL.
+Value is changed using `plist-put`, of which see."
+  (thread-first
+    proc
+    (process-plist)
+    (plist-put prop val)
+    (thread-last (set-process-plist proc))))
+
 (defun nrepl-server-filter (process output)
-  "Process nREPL server output from PROCESS contained in OUTPUT."
+  "Process nREPL server output from PROCESS contained in OUTPUT.
+
+The PROCESS plist is updated as (non-exhaustive list):
+
+:cider--nrepl-server-ready set to t when the server is successfully brought
+up."
   ;; In Windows this can be false:
   (let ((server-buffer (process-buffer process)))
     (when (buffer-live-p server-buffer)
@@ -1117,6 +1152,7 @@ match groups:
             (setq nrepl-endpoint (list :host host
                                        :port port))
             (message "[nREPL] server started on %s" port)
+            (cider--process-plist-put process :cider--nrepl-server-ready t)
             (when nrepl-on-port-callback
               (funcall nrepl-on-port-callback (process-buffer process)))))))))
 
@@ -1129,16 +1165,11 @@ match groups:
 
 (declare-function cider--close-connection "cider-connection")
 (defun nrepl-server-sentinel (process event)
-  "Handle nREPL server PROCESS EVENT."
-  (let* ((server-buffer (process-buffer process))
-         (clients (seq-filter (lambda (b)
-                                (eq (buffer-local-value 'nrepl-server-buffer b)
-                                    server-buffer))
-                              (buffer-list)))
-         (problem (if (and server-buffer (buffer-live-p server-buffer))
-                      (with-current-buffer server-buffer
-                        (buffer-substring (point-min) (point-max)))
-                    "")))
+  "Handle nREPL server PROCESS EVENT.
+On a fatal EVENT, attempt to close any open client connections, and signal
+an `error' if the nREPL PROCESS exited because it couldn't start up."
+  ;; only interested on fatal signals.
+  (when (not (process-live-p process))
     (emacs-bug-46284/when-27.1-windows-nt
      ;; There is a bug in emacs 27.1 (since fixed) that sets all EVENT
      ;; descriptions for signals to "unknown signal". We correct this by
@@ -1151,17 +1182,22 @@ match groups:
          (2 (setq event "Interrupt"))
          ;; SIGKILL==9 emacs nt/inc/ms-w32.h
          (9 (setq event "Killed")))))
-
-    (when server-buffer
-      (kill-buffer server-buffer))
-    (cond
-     ((string-match-p "^killed\\|^interrupt" event)
-      nil)
-     ((string-match-p "^hangup" event)
-      (mapc #'cider--close-connection clients))
-     ;; On Windows, a failed start sends the "finished" event. On Linux it 
sends
-     ;; "exited abnormally with code 1".
-     (t (error "Could not start nREPL server: %s" problem)))))
+    (let* ((server-buffer (process-buffer process))
+           (clients (seq-filter (lambda (b)
+                                  (eq (buffer-local-value 'nrepl-server-buffer 
b)
+                                      server-buffer))
+                                (buffer-list))))
+      ;; close any known open client connections
+      (when server-buffer
+        (kill-buffer server-buffer))
+      (mapc #'cider--close-connection clients)
+
+      (if (process-get process :cider--nrepl-server-ready)
+          (message "nREPL server exited.")
+        (let ((problem (when (and server-buffer (buffer-live-p server-buffer))
+                         (with-current-buffer server-buffer
+                           (buffer-substring (point-min) (point-max))))))
+          (error "Could not start nREPL server: %s (%S)" problem (string-trim 
event)))))))
 
 
 ;;; Messages
diff --git a/test/cider-tests.el b/test/cider-tests.el
index f223ed03bc..231ee49e5a 100644
--- a/test/cider-tests.el
+++ b/test/cider-tests.el
@@ -555,11 +555,12 @@
               "(do (require '[shadow.cljs.devtools.api :as shadow]) 
(shadow/browser-repl))")))
   (describe "can watch multiple builds"
     (it "watches 2 builds and selects user-defined builds"
-      (setq-local cider-shadow-default-options "client-build")
-      (setq-local cider-shadow-watched-builds '("client-build" "other-build"))
-      (expect (cider-shadow-cljs-init-form)
-              :to-equal
-              "(do (require '[shadow.cljs.devtools.api :as shadow]) 
(shadow/watch :client-build) (shadow/watch :other-build) (shadow/nrepl-select 
:client-build))"))))
+      (with-temp-buffer
+        (setq-local cider-shadow-default-options "client-build")
+        (setq-local cider-shadow-watched-builds '("client-build" 
"other-build"))
+        (expect (cider-shadow-cljs-init-form)
+                :to-equal
+                "(do (require '[shadow.cljs.devtools.api :as shadow]) 
(shadow/watch :client-build) (shadow/watch :other-build) (shadow/nrepl-select 
:client-build))")))))
 
 (describe "cider--resolve-project-command"
   (it "if command starts with ./ it resolves relative to clojure-project-dir"
diff --git a/test/integration/integration-tests.el 
b/test/integration/integration-tests.el
new file mode 100644
index 0000000000..00989f2936
--- /dev/null
+++ b/test/integration/integration-tests.el
@@ -0,0 +1,231 @@
+;;; integration-tests.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:
+
+;; Integration tests
+
+;; This file is part of CIDER
+
+;;; Code:
+
+(require 'buttercup)
+(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))))))
+
+(describe "jack in"
+  ;; See "bb" case for basic commentary
+  ;;
+  ;; 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 bb"
+      (with-temp-dir temp-dir
+        ;; set up a project directory in temp
+        (let* ((project-dir temp-dir)
+               (bb-edn (expand-file-name "bb.edn" project-dir)))
+          (write-region "{}" nil bb-edn)
+
+          (with-temp-buffer
+            ;; set default directory to temp project
+            (setq-local default-directory project-dir)
+
+            (unwind-protect
+                ;; jack in and get repl buffer
+                (let* ((nrepl-proc (cider-jack-in-clj '()))
+                       (nrepl-buf (process-buffer nrepl-proc)))
+                  ;; give it some time to setup the clj REPL
+                  (nrepl-tests-sleep-until 5 (cider-repls 'clj nil))
+
+                  ;; send command to the REPL, and stdout/stderr to
+                  ;; corresponding eval- variables.
+                  (let ((repl-buffer (cider-current-repl))
+                        (eval-err '())
+                        (eval-out '()))
+                    (expect repl-buffer :not :to-be nil)
+
+                    ;; send command to the REPL
+                    (cider-interactive-eval
+                     ;; ask REPL to return a string that uniquely identifies 
it.
+                     "(print :bb? (some? (System/getProperty 
\"babashka.version\")))"
+                     (lambda (return)
+                       (nrepl-dbind-response
+                           return
+                           (out err)
+                         (when err (push err eval-err))
+                         (when out (push out eval-out)))) )
+
+                    ;; wait for the response to come back.
+                    (nrepl-tests-sleep-until 5 eval-out)
+
+                    ;; ensure there are no errors and response is as expected.
+                    (expect eval-err :to-equal '())
+                    (expect eval-out :to-equal '(":bb? true"))
+
+                    ;; exit the REPL.
+                    (cider-quit repl-buffer)
+
+                    ;; wait for the REPL to exit
+                    (nrepl-tests-sleep-until 5 (not (eq (process-status 
nrepl-proc) 'run)))
+                    (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))))))))))
+
+  (it "to clojure tools cli"
+      (with-temp-dir temp-dir
+        (let* ((project-dir temp-dir)
+               (deps-edn (expand-file-name "deps.edn" project-dir)))
+          (write-region "{}" nil deps-edn)
+          (with-temp-buffer
+            (setq-local default-directory project-dir)
+            (unwind-protect
+                (let* ((nrepl-proc (cider-jack-in-clj `()))
+                       (nrepl-buf (process-buffer nrepl-proc)))
+
+                  ;; high duration since on windows it takes a long time to 
startup
+                  (nrepl-tests-sleep-until 90 (cider-repls 'clj nil))
+                  (let ((repl-buffer (cider-current-repl))
+                        (eval-err '())
+                        (eval-out '()))
+                    (expect repl-buffer :not :to-be nil)
+                    (cider-interactive-eval
+                     "(print :clojure? (some? (clojure-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 '(":clojure? true"))
+                    (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))))))))))
+
+  (it "to leiningen"
+      (with-temp-dir temp-dir
+        (let* ((project-dir temp-dir)
+               (project-clj (expand-file-name "project.clj" project-dir)))
+          (write-region "(defproject cider/integration \"test\"
+                           :dependencies [[org.clojure/clojure \"1.10.3\"]])"
+                        nil project-clj)
+          (with-temp-buffer
+            (setq-local default-directory project-dir)
+            (unwind-protect
+                (let* ((nrepl-proc (cider-jack-in-clj `()))
+                       (nrepl-buf (process-buffer nrepl-proc)))
+                  (nrepl-tests-sleep-until 90 (cider-repls 'clj nil))
+                  (let ((repl-buffer (cider-current-repl))
+                        (eval-err '())
+                        (eval-out '()))
+                    (expect repl-buffer :not :to-be nil)
+                    (cider-interactive-eval
+                     "(print :clojure? (some? (clojure-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 '(":clojure? true"))
+                    (cider-quit repl-buffer)
+                    (nrepl-tests-sleep-until 15 (not (eq (process-status 
nrepl-proc) 'run)))
+                    (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))))))))))
+
+  (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* ((nrepl-proc (cider-jack-in-cljs '(:cljs-repl-type 
shadow)))
+                         (nrepl-buf (process-buffer nrepl-proc)))
+                    (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))))))))))))
+
+(provide 'integration-tests)
+
+;;; integration-tests.el ends here
+
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*")))
diff --git a/test/utils/nrepl-tests-utils.el b/test/utils/nrepl-tests-utils.el
index e7a4a17164..0552b51d43 100644
--- a/test/utils/nrepl-tests-utils.el
+++ b/test/utils/nrepl-tests-utils.el
@@ -25,6 +25,8 @@
 
 ;;; Code:
 
+(require 'nrepl-client)
+
 (defmacro nrepl-tests-log/init! (enable? name log-filename &optional clean?)
   "Create a NAME/log! elisp function to log messages to LOG-FILENAME,
 taking the same arguments as `message'. Messages are appended to
@@ -97,5 +99,19 @@ calling process."
           ;; invoke mock server
           " -l test/nrepl-server-mock.el -f nrepl-server-mock-start"))
 
+(defun nrepl-start-mock-server-process ()
+  "Start and return the mock nrepl server process."
+  (let* ((up? nil)
+         (server-process (nrepl-start-server-process
+                          default-directory
+                          (nrepl-server-mock-invocation-string)
+                          (lambda (server-buffer)
+                            (setq up? t)))))
+    ;; server has reported its endpoint
+    (nrepl-tests-sleep-until 2 up?)
+    server-process))
 
 (provide 'nrepl-tests-utils)
+
+;;; nrepl-tests-utils.el ends here
+



reply via email to

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