diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8fd31cd77..0e51ec25c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,4 +78,7 @@ jobs: - name: Test integration run: | - eldev -p -dtTC test --test-type integration + # The tests occasionally fail on macos&win in what is seems to + # be GH connectivity runner issues. We attempt to address this + # problem by rerunning the tests more than once. + eldev -p -dtTC test --test-type integration || eldev -p -dtTC test --test-type integration diff --git a/CHANGELOG.md b/CHANGELOG.md index 936d8c97b..141ed0545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - [#3341](https://github.com/clojure-emacs/cider/issues/3341): Escape clojure-cli args on MS-Windows on non powershell invocations. - [#3353](https://github.com/clojure-emacs/cider/issues/3353): Fix regression which caused new connections to prompt for reusing dead REPLs. - [#3355](https://github.com/clojure-emacs/cider/pull/3355): Fix `cider-mode` disabling itself after a disconnect when `cider-auto-mode` is set to nil. +- [#3362](https://github.com/clojure-emacs/cider/issues/3362): Fix `sesman-restart` regression issue. ### Changes diff --git a/nrepl-client.el b/nrepl-client.el index a3d2672b7..beb9b32db 100644 --- a/nrepl-client.el +++ b/nrepl-client.el @@ -1191,8 +1191,9 @@ up." (declare-function cider--close-connection "cider-connection") (defun nrepl-server-sentinel (process event) "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." +If the nREPL PROCESS failed to initiate and encountered a fatal EVENT +signal, raise an 'error'. Additionally, if the EVENT signal is SIGHUP, +close any existing client connections." ;; only interested on fatal signals. (when (not (process-live-p process)) (emacs-bug-46284/when-27.1-windows-nt @@ -1212,8 +1213,10 @@ an `error' if the nREPL PROCESS exited because it couldn't start up." (eq (buffer-local-value 'nrepl-server-buffer b) server-buffer)) (buffer-list)))) - ;; close any known open client connections - (mapc #'cider--close-connection clients) + + ;; see https://github.com/clojure-emacs/cider/pull/3333 + (when (string-match-p "^hangup" event) + (mapc #'cider--close-connection clients)) (if (process-get process :cider--nrepl-server-ready) (progn diff --git a/test/cider-tests.el b/test/cider-tests.el index e023d2763..8729331de 100644 --- a/test/cider-tests.el +++ b/test/cider-tests.el @@ -668,6 +668,37 @@ ;; kill server (delete-process (get-buffer-process client-buffer)))))))) +(describe "sesman" + (it "can restart session" + (with-temp-buffer + (let* ((server-process (nrepl-start-mock-server-process)) + (server-buffer (process-buffer server-process))) + ;; wait for the connection to be established + (nrepl-tests-poll-until (local-variable-p 'nrepl-endpoint server-buffer) 5) + (let ((client-buffer (cider-connect-sibling-clj + `(:repl-buffer ,(current-buffer)) + server-buffer)) + (endpoint-bef) + (endpoint-aft)) + (expect (buffer-local-value 'cider-repl-type client-buffer) + :to-equal 'clj) + + (with-current-buffer (cider-current-repl) + (setq endpoint-bef nrepl-endpoint)) + + (sesman-restart) + ;; wait until a new server is brought up by continuously checking that + ;; the port has changed. If it remains the same, an exception is + ;; thrown, causing the test to fail. + (nrepl-tests-poll-until (when-let ((repl (cider-current-repl))) + (with-current-buffer repl + (setq endpoint-aft nrepl-endpoint) + ;; (message ":endpoints %S %S" endpoint-bef endpoint-aft) + (not (= (plist-get endpoint-bef :port) (plist-get endpoint-aft :port))))) + 5) + ;; kill server + (delete-process (get-buffer-process client-buffer))))))) + (provide 'cider-tests) ;;; cider-tests.el ends here diff --git a/test/nrepl-server-mock.el b/test/nrepl-server-mock.el index 77a731366..54643c083 100644 --- a/test/nrepl-server-mock.el +++ b/test/nrepl-server-mock.el @@ -31,15 +31,17 @@ (require 'nrepl-client) (require 'nrepl-tests-utils "test/utils/nrepl-tests-utils") (require 'queue) +(require 'cl) (defun nrepl-server-mock-filter (proc output) "Handle the nREPL message found in OUTPUT sent by the client PROC. Minimal implementation, just enough for fulfilling clients' testing requirements." - (mock/log! ":mock.filter/output %s :msg %s" proc output) + ;; (mock/log! ":mock.filter/output %s :msg %s" proc output) (condition-case error-details (let* ((msg (queue-dequeue (cdr (nrepl-bdecode output)))) + (_ (mock/log! ":mock.filter/msg :in %S" msg)) (response (pcase msg (`(dict "op" "clone" "id" ,id) `(dict "id" ,id @@ -48,10 +50,20 @@ requirements." "new-session" "a-new-session")) (`(dict "op" "describe" "session" ,session "id" ,id) + `(dict "id" ,id "session" ,session "status" + ("done"))) + ;; Eval op can include other fields in addition to the + ;; code, we only need the signature and the session and + ;; id fields at the end. + (`(dict "op" "eval" "code" ,_code . ,rest) + (cl-destructuring-bind (_ session _ id) (seq-drop rest (- (seq-length rest) 4)) + `(dict "id" ,id "session" ,session "status" + ("done")))) + (`(dict "op" "close" "session" ,session "id" ,id) `(dict "id" ,id "session" ,session "status" ("done")))))) - (mock/log! ":mock.filter/msg :in %s :out %s" msg response) + (mock/log! ":mock.filter/msg :out %S" response) (if (not response) (progn (mock/log! ":mock.filter/unsupported-msg :in %s :msg %s"