aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorJoão Távora2018-06-28 13:05:38 +0100
committerJoão Távora2018-06-29 23:05:19 +0100
commit76523866743f39b508e64c34a61af638a4a306b5 (patch)
tree2cdda939bf4381b6b970bb3141078416dcd00b89 /test
parent08594a975a3d95b1c1eae38af608e487e2edfafc (diff)
downloademacs-scratch/add-jsonrpc.tar.gz
emacs-scratch/add-jsonrpc.zip
Add lisp/jsonrpc.elscratch/add-jsonrpc
* lisp/jsonrpc.el: New file * test/lisp/jsonrpc-tests.el: New file
Diffstat (limited to 'test')
-rw-r--r--test/lisp/jsonrpc-tests.el242
1 files changed, 242 insertions, 0 deletions
diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el
new file mode 100644
index 00000000000..bfdb513ada4
--- /dev/null
+++ b/test/lisp/jsonrpc-tests.el
@@ -0,0 +1,242 @@
1;;; jsonrpc-tests.el --- tests for jsonrpc.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2018 Free Software Foundation, Inc.
4
5;; Author: João Távora <joaotavora@gmail.com>
6;; Maintainer: João Távora <joaotavora@gmail.com>
7;; Keywords: tests
8
9;; This program is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; This program is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;; About "deferred" tests, `jsonrpc--test-client' has a flag that we
25;; test this flag in the this `jsonrpc-connection-ready-p' API method.
26;; It holds any `jsonrpc-request's and `jsonrpc-async-request's
27;; explicitly passed `:deferred'. After clearing the flag, the held
28;; requests are actually sent to the server in the next opportunity
29;; (when receiving or sending something to the server).
30
31;;; Code:
32
33(require 'ert)
34(require 'jsonrpc)
35(require 'eieio)
36
37(defclass jsonrpc--test-endpoint (jsonrpc-process-connection)
38 ((scp :accessor jsonrpc--shutdown-complete-p)))
39
40(defclass jsonrpc--test-client (jsonrpc--test-endpoint)
41 ((hold-deferred :initform t :accessor jsonrpc--hold-deferred)))
42
43(cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body)
44 (declare (indent 1) (debug t))
45 (let ((server (gensym "server-")) (listen-server (gensym "listen-server-")))
46 `(let* (,server
47 (,listen-server
48 (make-network-process
49 :name "Emacs RPC server" :server t :host "localhost"
50 :service 0
51 :log (lambda (_server client _message)
52 (setq ,server
53 (make-instance
54 'jsonrpc--test-endpoint
55 :name (process-name client)
56 :process client
57 :request-dispatcher
58 (lambda (_endpoint method params)
59 (unless (memq method '(+ - * / vconcat append
60 sit-for ignore))
61 (signal 'jsonrpc-error
62 `((jsonrpc-error-message
63 . "Sorry, this isn't allowed")
64 (jsonrpc-error-code . -32601))))
65 (apply method (append params nil)))
66 :on-shutdown
67 (lambda (conn)
68 (setf (jsonrpc--shutdown-complete-p conn) t)))))))
69 (,endpoint-sym (make-instance
70 'jsonrpc--test-client
71 "Emacs RPC client"
72 :process
73 (open-network-stream "JSONRPC test tcp endpoint"
74 nil "localhost"
75 (process-contact ,listen-server
76 :service))
77 :on-shutdown
78 (lambda (conn)
79 (setf (jsonrpc--shutdown-complete-p conn) t)))))
80 (unwind-protect
81 (progn
82 (cl-assert ,endpoint-sym)
83 ,@body
84 (kill-buffer (jsonrpc--events-buffer ,endpoint-sym))
85 (when ,server
86 (kill-buffer (jsonrpc--events-buffer ,server))))
87 (unwind-protect
88 (jsonrpc-shutdown ,endpoint-sym)
89 (unwind-protect
90 (jsonrpc-shutdown ,server)
91 (cl-loop do (delete-process ,listen-server)
92 while (progn (accept-process-output nil 0.1)
93 (process-live-p ,listen-server))
94 do (jsonrpc--message
95 "test listen-server is still running, waiting"))))))))
96
97(ert-deftest returns-3 ()
98 "A basic test for adding two numbers in our test RPC."
99 (jsonrpc--with-emacsrpc-fixture (conn)
100 (should (= 3 (jsonrpc-request conn '+ [1 2])))))
101
102(ert-deftest errors-with--32601 ()
103 "Errors with -32601"
104 (jsonrpc--with-emacsrpc-fixture (conn)
105 (condition-case err
106 (progn
107 (jsonrpc-request conn 'delete-directory "~/tmp")
108 (ert-fail "A `jsonrpc-error' should have been signalled!"))
109 (jsonrpc-error
110 (should (= -32601 (cdr (assoc 'jsonrpc-error-code (cdr err)))))))))
111
112(ert-deftest signals-an--32603-JSONRPC-error ()
113 "Signals an -32603 JSONRPC error."
114 (jsonrpc--with-emacsrpc-fixture (conn)
115 (condition-case err
116 (progn
117 (jsonrpc-request conn '+ ["a" 2])
118 (ert-fail "A `jsonrpc-error' should have been signalled!"))
119 (jsonrpc-error
120 (should (= -32603 (cdr (assoc 'jsonrpc-error-code (cdr err)))))))))
121
122(ert-deftest times-out ()
123 "Request for 3-sec sit-for with 1-sec timeout times out."
124 (jsonrpc--with-emacsrpc-fixture (conn)
125 (should-error
126 (jsonrpc-request conn 'sit-for [3] :timeout 1))))
127
128(ert-deftest doesnt-time-out ()
129 :tags '(:expensive-test)
130 "Request for 1-sec sit-for with 2-sec timeout succeeds."
131 (jsonrpc--with-emacsrpc-fixture (conn)
132 (jsonrpc-request conn 'sit-for [1] :timeout 2)))
133
134(ert-deftest stretching-it-but-works ()
135 "Vector of numbers or vector of vector of numbers are serialized."
136 (jsonrpc--with-emacsrpc-fixture (conn)
137 ;; (vconcat [1 2 3] [3 4 5]) => [1 2 3 3 4 5] which can be
138 ;; serialized.
139 (should (equal
140 [1 2 3 3 4 5]
141 (jsonrpc-request conn 'vconcat [[1 2 3] [3 4 5]])))))
142
143(ert-deftest json-el-cant-serialize-this ()
144 "Can't serialize a response that is half-vector/half-list."
145 (jsonrpc--with-emacsrpc-fixture (conn)
146 (should-error
147 ;; (append [1 2 3] [3 4 5]) => (1 2 3 . [3 4 5]), which can't be
148 ;; serialized
149 (jsonrpc-request conn 'append [[1 2 3] [3 4 5]]))))
150
151(cl-defmethod jsonrpc-connection-ready-p
152 ((conn jsonrpc--test-client) what)
153 (and (cl-call-next-method)
154 (or (not (string-match "deferred" what))
155 (not (jsonrpc--hold-deferred conn)))))
156
157(ert-deftest deferred-action-toolate ()
158 :tags '(:expensive-test)
159 "Deferred request fails because noone clears the flag."
160 (jsonrpc--with-emacsrpc-fixture (conn)
161 (should-error
162 (jsonrpc-request conn '+ [1 2]
163 :deferred "deferred-testing" :timeout 0.5)
164 :type 'jsonrpc-error)
165 (should
166 (= 3 (jsonrpc-request conn '+ [1 2]
167 :timeout 0.5)))))
168
169(ert-deftest deferred-action-intime ()
170 :tags '(:expensive-test)
171 "Deferred request barely makes it after event clears a flag."
172 ;; Send an async request, which returns immediately. However the
173 ;; success fun which sets the flag only runs after some time.
174 (jsonrpc--with-emacsrpc-fixture (conn)
175 (jsonrpc-async-request conn
176 'sit-for [0.5]
177 :success-fn
178 (lambda (_result)
179 (setf (jsonrpc--hold-deferred conn) nil)))
180 ;; Now wait for an answer to this request, which should be sent as
181 ;; soon as the previous one is answered.
182 (should
183 (= 3 (jsonrpc-request conn '+ [1 2]
184 :deferred "deferred"
185 :timeout 1)))))
186
187(ert-deftest deferred-action-complex-tests ()
188 :tags '(:expensive-test)
189 "Test a more complex situation with deferred requests."
190 (jsonrpc--with-emacsrpc-fixture (conn)
191 (let (n-deferred-1
192 n-deferred-2
193 second-deferred-went-through-p)
194 ;; This returns immediately
195 (jsonrpc-async-request
196 conn
197 'sit-for [0.1]
198 :success-fn
199 (lambda (_result)
200 ;; this only gets runs after the "first deferred" is stashed.
201 (setq n-deferred-1
202 (hash-table-count (jsonrpc--deferred-actions conn)))))
203 (should-error
204 ;; This stashes the request and waits. It will error because
205 ;; no-one clears the "hold deferred" flag.
206 (jsonrpc-request conn 'ignore ["first deferred"]
207 :deferred "first deferred"
208 :timeout 0.5)
209 :type 'jsonrpc-error)
210 ;; The error means the deferred actions stash is now empty
211 (should (zerop (hash-table-count (jsonrpc--deferred-actions conn))))
212 ;; Again, this returns immediately.
213 (jsonrpc-async-request
214 conn
215 'sit-for [0.1]
216 :success-fn
217 (lambda (_result)
218 ;; This gets run while "third deferred" below is waiting for
219 ;; a reply. Notice that we clear the flag in time here.
220 (setq n-deferred-2 (hash-table-count (jsonrpc--deferred-actions conn)))
221 (setf (jsonrpc--hold-deferred conn) nil)))
222 ;; This again stashes a request and returns immediately.
223 (jsonrpc-async-request conn 'ignore ["second deferred"]
224 :deferred "second deferred"
225 :timeout 1
226 :success-fn
227 (lambda (_result)
228 (setq second-deferred-went-through-p t)))
229 ;; And this also stashes a request, but waits. Eventually the
230 ;; flag is cleared in time and both requests go through.
231 (jsonrpc-request conn 'ignore ["third deferred"]
232 :deferred "third deferred"
233 :timeout 1)
234 (should second-deferred-went-through-p)
235 (should (eq 1 n-deferred-1))
236 (should (eq 2 n-deferred-2))
237 (should (eq 0 (hash-table-count (jsonrpc--deferred-actions conn)))))))
238
239
240
241(provide 'jsonrpc-tests)
242;;; jsonrpc-tests.el ends here