blob: 5ae023d6a0b929bd46ff2613a581058d489753dd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
;;; test-signel-rpc-dispatch.el --- Tests for signel JSON-RPC success-result dispatch -*- lexical-binding: t; -*-
;;; Commentary:
;; signel's JSON-RPC dispatch (signel.el in the fork at ~/code/signel) routes
;; incoming `receive' notifications and errors, but successful
;; `((id . N) (result . VALUE))' responses had no path until this work added a
;; request-callback table. These tests cover the new behavior: a registered
;; callback fires with the result and is then removed; an error response
;; also removes the handler so a retry starts clean; an unregistered id is a
;; silent no-op; passing SUCCESS-CALLBACK to `signel--send-rpc' registers it
;; under the returned id.
;;
;; The dispatch tests exercise `signel--dispatch' directly with synthetic JSON
;; alists; no live process is needed. The send-rpc test stubs `get-process'
;; and `process-send-string' so it doesn't require a running signal-cli.
;;; Code:
(require 'ert)
(require 'cl-lib)
(eval-and-compile
(add-to-list 'load-path (expand-file-name "~/code/signel")))
(require 'signel)
(defun test-signel-rpc--reset ()
"Reset signel dispatch state to a clean baseline before each test."
(clrhash signel--request-handler-map)
(clrhash signel--request-buffer-map)
(setq signel--rpc-id-counter 0))
(ert-deftest test-signel-rpc-dispatch-result-invokes-callback ()
"Normal: a result response with a registered id fires the callback with the
result value and removes the handler."
(test-signel-rpc--reset)
(let ((captured nil))
(puthash 7 (lambda (val) (setq captured val)) signel--request-handler-map)
(signel--dispatch '((jsonrpc . "2.0") (id . 7)
(result . ((contacts . [1 2 3])))))
(should (equal captured '((contacts . [1 2 3]))))
(should-not (gethash 7 signel--request-handler-map))))
(ert-deftest test-signel-rpc-dispatch-unknown-id-is-noop ()
"Boundary: a result response with an unregistered id is a silent no-op:
neither receive nor error handler fires, and the handler map stays empty."
(test-signel-rpc--reset)
(let ((called nil))
(cl-letf (((symbol-function 'signel--handle-error)
(lambda (&rest _) (setq called 'error)))
((symbol-function 'signel--handle-receive)
(lambda (&rest _) (setq called 'receive))))
(signel--dispatch '((jsonrpc . "2.0") (id . 99) (result . "anything"))))
(should-not called)
(should (zerop (hash-table-count signel--request-handler-map)))))
(ert-deftest test-signel-rpc-dispatch-error-cleans-up-handler ()
"Error: an error response with a registered id removes the handler without
firing the callback, leaving the map clean for a retry."
(test-signel-rpc--reset)
(let ((fired nil))
(puthash 11 (lambda (&rest _) (setq fired t))
signel--request-handler-map)
(cl-letf (((symbol-function 'signel--handle-error) (lambda (&rest _) nil)))
(signel--dispatch '((jsonrpc . "2.0") (id . 11)
(error . ((code . -1) (message . "boom"))))))
(should-not fired)
(should-not (gethash 11 signel--request-handler-map))))
(ert-deftest test-signel-rpc-send-rpc-registers-success-callback ()
"Normal: passing a SUCCESS-CALLBACK to `signel--send-rpc' stores it under
the returned id so the matching response can route to it."
(test-signel-rpc--reset)
(let ((cb (lambda (_) 'ok))
(sent nil))
(cl-letf (((symbol-function 'get-process) (lambda (&rest _) 'fake-proc))
((symbol-function 'process-send-string)
(lambda (_ s) (setq sent s)))
((symbol-function 'signel--log) (lambda (&rest _) nil)))
(let ((id (signel--send-rpc "listContacts" nil nil cb)))
(should (eq cb (gethash id signel--request-handler-map)))
(should (stringp sent))))))
(ert-deftest test-signel-rpc-stop-clears-handler-map ()
"Normal (reconnect-invalidation): `signel-stop' clears the handler map so a
restart starts with no stale callbacks waiting for responses that will never
arrive."
(test-signel-rpc--reset)
(puthash 13 (lambda (&rest _) nil) signel--request-handler-map)
(cl-letf (((symbol-function 'get-process) (lambda (&rest _) nil)))
(signel-stop))
(should (zerop (hash-table-count signel--request-handler-map))))
(provide 'test-signel-rpc-dispatch)
;;; test-signel-rpc-dispatch.el ends here
|