|
33 | 33 | (require 'queue) |
34 | 34 | (require 'cl) |
35 | 35 |
|
| 36 | +(defun nrepl-server-mock--get-keys (dict keys) |
| 37 | + "Get the values for KEYS from nrepl-dict DICT. |
| 38 | +Get them as a list, so they can be easily consumed by |
| 39 | +`cl-destructuring-bind`." |
| 40 | + (mapcar (lambda (k) (nrepl-dict-get dict k)) keys)) |
| 41 | + |
36 | 42 | (defun nrepl-server-mock-filter (proc output) |
37 | 43 | "Handle the nREPL message found in OUTPUT sent by the client PROC. |
38 | 44 | Minimal implementation, just enough for fulfilling clients' testing |
39 | | -requirements." |
| 45 | +requirements. |
| 46 | +
|
| 47 | +Additional complexity is added by the fact that bencoded dictionaries |
| 48 | +must have their keys in sorted order. But we don't want to have to |
| 49 | +remember to write them down as such in the test values here (because |
| 50 | +there is ample room for mistakes that are harder to debug)." |
40 | 51 | ;; (mock/log! ":mock.filter/output %s :msg %s" proc output) |
41 | 52 |
|
42 | 53 | (condition-case error-details |
43 | 54 | (let* ((msg (queue-dequeue (cdr (nrepl-bdecode output)))) |
44 | 55 | (_ (mock/log! ":mock.filter/msg :in %S" msg)) |
| 56 | + ;; Message id and session are needed for all request |
| 57 | + ;; messages and responses. Get them once here. |
| 58 | + (msg-id (nrepl-dict-get msg "id")) |
| 59 | + (msg-session (nrepl-dict-get msg "session")) |
45 | 60 | (response (pcase msg |
46 | | - (`(dict "op" "clone" |
47 | | - "client-name" "CIDER" |
48 | | - "client-version" ,cider-version |
49 | | - "id" ,id) |
50 | | - `(dict "id" ,id |
| 61 | + ((pred (lambda (msg) |
| 62 | + (let ((keys '("client-version"))) |
| 63 | + (cl-destructuring-bind (client-version) (nrepl-server-mock--get-keys msg keys) |
| 64 | + (bencodable-obj-equal? msg |
| 65 | + `(dict "op" "clone" |
| 66 | + "client-name" "CIDER" |
| 67 | + "client-version" ,client-version |
| 68 | + "id" ,msg-id)))))) |
| 69 | + `(dict "id" ,msg-id |
51 | 70 | "session" "a-session" |
52 | 71 | "status" ("done") |
53 | 72 | "new-session" "a-new-session")) |
54 | 73 |
|
55 | | - (`(dict "op" "describe" "session" ,session "id" ,id) |
56 | | - `(dict "id" ,id "session" ,session "status" |
57 | | - ("done"))) |
| 74 | + ((pred (bencodable-obj-equal? `(dict "op" "describe" |
| 75 | + "id" ,msg-id |
| 76 | + "session" ,msg-session))) |
| 77 | + `(dict "id" ,msg-id |
| 78 | + "session" ,msg-session |
| 79 | + "status" ("done"))) |
| 80 | + |
58 | 81 | ;; Eval op can include other fields in addition to the |
59 | 82 | ;; code, we only need the signature and the session and |
60 | | - ;; id fields at the end. |
61 | | - (`(dict "op" "eval" "code" ,_code . ,rest) |
62 | | - (cl-destructuring-bind (_ session _ id) (seq-drop rest (- (seq-length rest) 4)) |
63 | | - `(dict "id" ,id "session" ,session "status" |
64 | | - ("done")))) |
65 | | - (`(dict "op" "close" "session" ,session "id" ,id) |
66 | | - `(dict "id" ,id "session" ,session "status" |
67 | | - ("done")))))) |
| 83 | + ;; id fields. |
| 84 | + ((pred (lambda (msg) |
| 85 | + (let ((keys '("op"))) |
| 86 | + (cl-destructuring-bind (op) (nrepl-server-mock--get-keys msg keys) |
| 87 | + (bencodable-obj-equal? `(dict "op" ,op |
| 88 | + "id" ,msg-id |
| 89 | + "session" ,msg-session) |
| 90 | + `(dict "op" "eval" |
| 91 | + "id" ,msg-id |
| 92 | + "session" ,msg-session)))))) |
| 93 | + `(dict "id" ,msg-id |
| 94 | + "session" ,msg-session |
| 95 | + "status" ("done"))) |
| 96 | + |
| 97 | + ((pred (bencodable-obj-equal? `(dict "op" "close" |
| 98 | + "id" ,msg-id |
| 99 | + "session" ,msg-session))) |
| 100 | + `(dict "id" ,msg-id |
| 101 | + "session" ,msg-session |
| 102 | + "status" ("done")))))) |
68 | 103 |
|
69 | 104 | (mock/log! ":mock.filter/msg :out %S" response) |
70 | 105 | (if (not response) |
|
0 commit comments