Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 574 lines (543 sloc) 27.659 kB
0202adc @ahyatt Finish and test the server filter function.
authored
1 ;; websocket-test.el --- Unit tests for the websocket layer
59697b4 @ahyatt Initial checkin of files. These files were initially part of the
authored
2
3 ;; Copyright (c) 2010 Andrew Hyatt
4 ;;
5 ;; Author: Andrew Hyatt <ahyatt at gmail dot com>
6 ;; Maintainer: Andrew Hyatt <ahyatt at gmail dot com>
7 ;;
8 ;; This program is free software; you can redistribute it and/or
9 ;; modify it under the terms of the GNU General Public License as
10 ;; published by the Free Software Foundation; either version 2 of the
11 ;; License, or (at your option) any later version.
12 ;;
13 ;; This program is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;; General Public License for more details.
17 ;;
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program; if not, write to the Free Software
20 ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 ;; 02110-1301, USA.
22
23 ;;; Commentary:
24 ;; This defines and runs ert unit tests. You can download ert from:
25 ;; http://github.com/ohler/ert, it also comes with Emacs 24 and above.
26
27 (require 'ert)
9d8794a @tkf Suppress compilation warning in websocket-test.el
tkf authored
28 (require 'websocket)
29 (eval-when-compile (require 'cl))
59697b4 @ahyatt Initial checkin of files. These files were initially part of the
authored
30
45245a4 @tkf Add test websocket-genbytes-length
tkf authored
31 (ert-deftest websocket-genbytes-length ()
32 (loop repeat 100
82e85aa @ahyatt Fix test for websocket-genbytes
authored
33 do (should (= (string-bytes (websocket-genbytes 16)) 16))))
45245a4 @tkf Add test websocket-genbytes-length
tkf authored
34
b5bbce1 @ahyatt Add a function to calculate the accept header expected.
authored
35 (ert-deftest websocket-calculate-accept ()
36 ;; This example comes straight from RFC 6455
37 (should
38 (equal "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
237b190 @ahyatt Various whitespace changes
authored
39 (websocket-calculate-accept "dGhlIHNhbXBsZSBub25jZQ=="))))
b5bbce1 @ahyatt Add a function to calculate the accept header expected.
authored
40
f4e1aa8 @ahyatt Add helper functions for websocket-get-opcode and
authored
41 (defconst websocket-test-hello "\x81\x05\x48\x65\x6c\x6c\x6f"
42 "'Hello' string example, taken from the RFC.")
237b190 @ahyatt Various whitespace changes
authored
43
4c8dbe2 @ahyatt Implement masking and unmasking.
authored
44 (defconst websocket-test-masked-hello
45 "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58"
46 "'Hello' masked string example, taken from the RFC.")
f4e1aa8 @ahyatt Add helper functions for websocket-get-opcode and
authored
47
39f1f28 @tkf Force test to pass in 32-bit Emacs
tkf authored
48 (defconst websocket-test-64-bit-p
49 (calc-eval '("2^32 <= $") 'pred most-positive-fixnum))
50
b948e95 @ahyatt Fixed payload len logic, and rewrote the bit-grabbing bits to just
authored
51 (ert-deftest websocket-get-bytes ()
52 (should (equal #x5 (websocket-get-bytes "\x5" 1)))
53 (should (equal #x101 (websocket-get-bytes "\x1\x1" 2)))
39f1f28 @tkf Force test to pass in 32-bit Emacs
tkf authored
54 (let ((f (lambda () (websocket-get-bytes "\x0\x0\x0\x1\x0\x0\x0\x1" 8))))
55 (if websocket-test-64-bit-p
56 (should (equal #x100000001 (funcall f)))
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
57 (should-error (funcall f) :type 'websocket-unparseable-frame)))
b948e95 @ahyatt Fixed payload len logic, and rewrote the bit-grabbing bits to just
authored
58 (should-error (websocket-get-bytes "\x0\x0\x0" 3))
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
59 (should-error (websocket-get-bytes "\x0" 2) :type 'websocket-unparseable-frame))
b948e95 @ahyatt Fixed payload len logic, and rewrote the bit-grabbing bits to just
authored
60
f4e1aa8 @ahyatt Add helper functions for websocket-get-opcode and
authored
61 (ert-deftest websocket-get-opcode ()
62 (should (equal 'text (websocket-get-opcode websocket-test-hello))))
63
64 (ert-deftest websocket-get-payload-len ()
b948e95 @ahyatt Fixed payload len logic, and rewrote the bit-grabbing bits to just
authored
65 (should (equal '(5 . 1)
66 (websocket-get-payload-len
67 (substring websocket-test-hello 1))))
f4e1aa8 @ahyatt Add helper functions for websocket-get-opcode and
authored
68 (should (equal '(200 . 3)
69 (websocket-get-payload-len
b948e95 @ahyatt Fixed payload len logic, and rewrote the bit-grabbing bits to just
authored
70 (bindat-pack '((:len u8) (:val u16))
71 `((:len . 126)
f4e1aa8 @ahyatt Add helper functions for websocket-get-opcode and
authored
72 (:val . 200))))))
73 ;; we don't want to hit up any limits even on strange emacs builds,
74 ;; so this test has a pretty small test value
75 (should (equal '(70000 . 9)
76 (websocket-get-payload-len
b948e95 @ahyatt Fixed payload len logic, and rewrote the bit-grabbing bits to just
authored
77 (bindat-pack '((:len u8) (:val vec 2 u32))
78 `((:len . 127)
f4e1aa8 @ahyatt Add helper functions for websocket-get-opcode and
authored
79 (:val . [0 70000])))))))
ae51a78 @ahyatt Code to read a frame. Does not yet support masking.
authored
80
81 (ert-deftest websocket-read-frame ()
7900cda @ahyatt Return the length of the websocket frame from websocket-read-frame.
authored
82 (should (equal (make-websocket-frame :opcode 'text :payload "Hello"
b0a2970 @ahyatt Add completep in frame
authored
83 :length (length websocket-test-hello)
84 :completep t)
4c8dbe2 @ahyatt Implement masking and unmasking.
authored
85 (websocket-read-frame websocket-test-hello)))
7900cda @ahyatt Return the length of the websocket frame from websocket-read-frame.
authored
86 (should (equal (make-websocket-frame :opcode 'text :payload "Hello"
b0a2970 @ahyatt Add completep in frame
authored
87 :length (length websocket-test-hello)
88 :completep t)
7900cda @ahyatt Return the length of the websocket frame from websocket-read-frame.
authored
89 (websocket-read-frame (concat websocket-test-hello
90 "should-not-be-read"))))
91 (should (equal (make-websocket-frame :opcode 'text :payload "Hello"
b0a2970 @ahyatt Add completep in frame
authored
92 :length (length websocket-test-masked-hello)
93 :completep t)
51b5764 @ahyatt Ensure the websocket frame is complete, and return NIL if not.
authored
94 (websocket-read-frame websocket-test-masked-hello)))
b0a2970 @ahyatt Add completep in frame
authored
95 (should (equal (make-websocket-frame :opcode 'text :payload "Hello"
96 :length (length websocket-test-hello)
97 :completep nil)
1081075 @ahyatt More whitespace changes
authored
98 (websocket-read-frame
99 (concat (unibyte-string
100 (logand (string-to-char
101 (substring websocket-test-hello 0 1))
102 127))
103 (substring websocket-test-hello 1)))))
51b5764 @ahyatt Ensure the websocket frame is complete, and return NIL if not.
authored
104 (dotimes (i (- (length websocket-test-hello) 1))
105 (should-not (websocket-read-frame
106 (substring websocket-test-hello 0
107 (- (length websocket-test-hello) (+ i 1))))))
108 (dotimes (i (- (length websocket-test-masked-hello) 1))
109 (should-not (websocket-read-frame
110 (substring websocket-test-masked-hello 0
111 (- (length websocket-test-masked-hello) (+ i 1)))))))
8da9119 @ahyatt Separate out the handshake verification logic, and test it. Look for
authored
112
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
113 (defun websocket-test-header-with-lines (&rest lines)
114 (mapconcat 'identity (append lines '("\r\n")) "\r\n"))
8da9119 @ahyatt Separate out the handshake verification logic, and test it. Look for
authored
115
6c42988 @ahyatt Check for HTTP 101 response code, and if there is any failure in the
authored
116 (ert-deftest websocket-verify-response-code ()
117 (should (websocket-verify-response-code "HTTP/1.1 101"))
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
118 (should
119 (eq 400 (cdr (should-error (websocket-verify-response-code "HTTP/1.1 400")
120 :type 'websocket-received-error-http-response))))
121 (should
122 (eq 200 (cdr (should-error (websocket-verify-response-code "HTTP/1.1 200"))))))
6c42988 @ahyatt Check for HTTP 101 response code, and if there is any failure in the
authored
123
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
124 (ert-deftest websocket-verify-headers ()
125 (let ((accept "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
126 (invalid-accept "Sec-WebSocket-Accept: bad")
127 (upgrade "Upgrade: websocket")
128 (connection "Connection: upgrade")
129 (ws (websocket-inner-create
130 :conn "fake-conn" :url "ws://foo/bar"
131 :accept-string "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="))
132 (ws-with-protocol
133 (websocket-inner-create
134 :conn "fake-conn" :url "ws://foo/bar"
135 :accept-string "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
5a8b995 @ahyatt Add server header generation, and refactor protocol and extension han…
authored
136 :protocols '("myprotocol")))
881c6ca @ahyatt Implement support for specifying extensions.
authored
137 (ws-with-extensions
138 (websocket-inner-create
139 :conn "fake-conn" :url "ws://foo/bar"
140 :accept-string "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
141 :extensions '("ext1" "ext2"))))
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
142 (should (websocket-verify-headers
143 ws
144 (websocket-test-header-with-lines accept upgrade connection)))
145 (should-error
146 (websocket-verify-headers
147 ws
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
148 (websocket-test-header-with-lines invalid-accept upgrade connection))
149 :type 'websocket-invalid-header)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
150 (should-error (websocket-verify-headers
151 ws
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
152 (websocket-test-header-with-lines upgrade connection))
153 :type 'websocket-invalid-header)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
154 (should-error (websocket-verify-headers
155 ws
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
156 (websocket-test-header-with-lines accept connection))
157 :type 'websocket-invalid-header)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
158 (should-error (websocket-verify-headers
159 ws
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
160 (websocket-test-header-with-lines accept upgrade))
161 :type 'websocket-invalid-header)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
162 (should-error (websocket-verify-headers
163 ws-with-protocol
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
164 (websocket-test-header-with-lines accept upgrade connection))
165 :type 'websocket-invalid-header)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
166 (should-error
167 (websocket-verify-headers
168 ws-with-protocol
169 (websocket-test-header-with-lines accept upgrade connection
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
170 "Sec-Websocket-Protocol: foo"))
171 :type 'websocket-invalid-header)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
172 (should
173 (websocket-verify-headers
174 ws-with-protocol
175 (websocket-test-header-with-lines accept upgrade connection
881c6ca @ahyatt Implement support for specifying extensions.
authored
176 "Sec-Websocket-Protocol: myprotocol")))
5a8b995 @ahyatt Add server header generation, and refactor protocol and extension han…
authored
177 (should (equal '("myprotocol")
178 (websocket-negotiated-protocols ws-with-protocol)))
881c6ca @ahyatt Implement support for specifying extensions.
authored
179 (should-error
180 (websocket-verify-headers
181 ws-with-extensions
182 (websocket-test-header-with-lines accept upgrade connection
183 "Sec-Websocket-Extensions: foo")))
184 (should
185 (websocket-verify-headers
186 ws-with-extensions
187 (websocket-test-header-with-lines
188 accept upgrade connection "Sec-Websocket-Extensions: ext1, ext2; a=1")))
189 (should (equal '("ext1" "ext2; a=1")
5a8b995 @ahyatt Add server header generation, and refactor protocol and extension han…
authored
190 (websocket-negotiated-extensions ws-with-extensions)))
881c6ca @ahyatt Implement support for specifying extensions.
authored
191 (should
192 (websocket-verify-headers
193 ws-with-extensions
194 (websocket-test-header-with-lines accept upgrade connection
195 "Sec-Websocket-Extensions: ext1"
196 "Sec-Websocket-Extensions: ext2; a=1")))
197 (should (equal '("ext1" "ext2; a=1")
5a8b995 @ahyatt Add server header generation, and refactor protocol and extension han…
authored
198 (websocket-negotiated-extensions ws-with-extensions)))))
881c6ca @ahyatt Implement support for specifying extensions.
authored
199
200 (ert-deftest websocket-create-headers ()
201 (let ((system-name "mysystem")
202 (base-headers (concat "Host: www.example.com\r\n"
203 "Upgrade: websocket\r\n"
204 "Connection: Upgrade\r\n"
23b132e @ahyatt Fix failing ert tests
authored
205 "Sec-WebSocket-Key: key\r\n"
881c6ca @ahyatt Implement support for specifying extensions.
authored
206 "Origin: mysystem\r\n"
207 "Sec-WebSocket-Version: 13\r\n")))
208 (should (equal (concat base-headers "\r\n")
209 (websocket-create-headers "ws://www.example.com/path"
210 "key" nil nil)))
211 (should (equal (concat base-headers
212 "Sec-WebSocket-Protocol: protocol\r\n\r\n")
213 (websocket-create-headers "ws://www.example.com/path"
5a8b995 @ahyatt Add server header generation, and refactor protocol and extension han…
authored
214 "key" '("protocol") nil)))
881c6ca @ahyatt Implement support for specifying extensions.
authored
215 (should (equal
216 (concat base-headers
217 "Sec-WebSocket-Extensions: ext1; a; b=2, ext2\r\n\r\n")
218 (websocket-create-headers "ws://www.example.com/path"
219 "key" nil
220 '(("ext1" . ("a" "b=2"))
221 ("ext2")))))))
3a7798f @ahyatt Added frame processing, and more of the structure to use it.
authored
222
223 (ert-deftest websocket-process-frame ()
224 (let* ((sent)
225 (processed)
226 (deleted)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
227 (websocket (websocket-inner-create
228 :conn t :url t
229 :on-message (lambda (websocket frame)
230 (setq
231 processed
232 (websocket-frame-payload frame)))
233 :accept-string t)))
3a7798f @ahyatt Added frame processing, and more of the structure to use it.
authored
234 (dolist (opcode '(text binary continuation))
235 (setq processed nil)
236 (should (equal
237 "hello"
238 (progn
14e94a4 @ahyatt Revamp how error processing works, increasing user control and
authored
239 (funcall (websocket-process-frame
240 websocket
241 (make-websocket-frame :opcode opcode :payload "hello")))
3a7798f @ahyatt Added frame processing, and more of the structure to use it.
authored
242 processed))))
243 (setq sent nil)
244 (flet ((websocket-send (websocket content) (setq sent content)))
245 (should (equal
7bc2aae @ahyatt Make websocket-send work on frames, and use it to send pongs.
authored
246 (make-websocket-frame :opcode 'pong :completep t)
3a7798f @ahyatt Added frame processing, and more of the structure to use it.
authored
247 (progn
14e94a4 @ahyatt Revamp how error processing works, increasing user control and
authored
248 (funcall (websocket-process-frame websocket
249 (make-websocket-frame :opcode 'ping)))
3a7798f @ahyatt Added frame processing, and more of the structure to use it.
authored
250 sent))))
251 (flet ((delete-process (conn) (setq deleted t)))
252 (should (progn
14e94a4 @ahyatt Revamp how error processing works, increasing user control and
authored
253 (funcall
254 (websocket-process-frame websocket
255 (make-websocket-frame :opcode 'close)))
3a7798f @ahyatt Added frame processing, and more of the structure to use it.
authored
256 deleted)))))
2148c5a @ahyatt Create the websocket-to-bytes function, to encode a number in a
authored
257
14e94a4 @ahyatt Revamp how error processing works, increasing user control and
authored
258 (ert-deftest websocket-process-frame-error-handling ()
259 (let* ((error-called)
260 (websocket (websocket-inner-create
261 :conn t :url t :accept-string t
262 :on-message (lambda (websocket frame)
263 (message "In on-message")
264 (error "err"))
265 :on-error (lambda (ws type err)
266 (should (eq 'on-message type))
267 (setq error-called t)))))
268 (funcall (websocket-process-frame websocket
269 (make-websocket-frame :opcode 'text
270 :payload "hello")))
271 (should error-called)))
272
2148c5a @ahyatt Create the websocket-to-bytes function, to encode a number in a
authored
273 (ert-deftest websocket-to-bytes ()
274 ;; We've tested websocket-get-bytes by itself, now we can use it to
275 ;; help test websocket-to-bytes.
276 (should (equal 30 (websocket-get-bytes (websocket-to-bytes 30 1) 1)))
277 (should (equal 300 (websocket-get-bytes (websocket-to-bytes 300 2) 2)))
39f1f28 @tkf Force test to pass in 32-bit Emacs
tkf authored
278 (let ((f (lambda () (websocket-to-bytes 70000 8))))
279 (if websocket-test-64-bit-p
280 (should (equal 70000 (websocket-get-bytes (funcall f) 8)))
281 (should-error (funcall f))))
2148c5a @ahyatt Create the websocket-to-bytes function, to encode a number in a
authored
282 (should-error (websocket-to-bytes 30 3))
cf885f0 @ahyatt Fix issue on < 64-bit systems in packing an 8 byte value.
authored
283 (should-error (websocket-to-bytes 300 1))
284 ;; I'd like to test the error for 32-byte systems on 8-byte lengths,
285 ;; but elisp does not allow us to temporarily set constants such as
286 ;; most-positive-fixnum.
287 )
2148c5a @ahyatt Create the websocket-to-bytes function, to encode a number in a
authored
288
3596d84 @ahyatt Write and test websocket-encode-frame.
authored
289 (ert-deftest websocket-encode-frame ()
290 ;; We've tested websocket-read-frame, now we can use that to help
291 ;; test websocket-encode-frame.
655cf1e @ahyatt Support outbound masking
authored
292 (let ((websocket-mask-frames nil))
293 (should (equal
294 websocket-test-hello
295 (websocket-encode-frame
296 (make-websocket-frame :opcode 'text :payload "Hello" :completep t))))
39f1f28 @tkf Force test to pass in 32-bit Emacs
tkf authored
297 (dolist (len (if websocket-test-64-bit-p '(200 70000) '(200 60000)))
237b190 @ahyatt Various whitespace changes
authored
298 (let ((long-string (make-string len ?x)))
299 (should (equal long-string
300 (websocket-frame-payload
301 (websocket-read-frame
302 (websocket-encode-frame
1081075 @ahyatt More whitespace changes
authored
303 (make-websocket-frame :opcode 'text
304 :payload long-string)))))))))
655cf1e @ahyatt Support outbound masking
authored
305 (let ((websocket-mask-frames t))
306 (flet ((websocket-genbytes (n) (substring websocket-test-masked-hello 2 6)))
237b190 @ahyatt Various whitespace changes
authored
307 (should (equal websocket-test-masked-hello
308 (websocket-encode-frame
1081075 @ahyatt More whitespace changes
authored
309 (make-websocket-frame :opcode 'text :payload "Hello"
310 :completep t))))))
3596d84 @ahyatt Write and test websocket-encode-frame.
authored
311 (should-not
312 (websocket-frame-completep
313 (websocket-read-frame
1081075 @ahyatt More whitespace changes
authored
314 (websocket-encode-frame (make-websocket-frame :opcode 'text
315 :payload "Hello"
316 :completep nil)))))
0e04e15 @ahyatt Fix issue with encoding & decoding non-payload frames, and fix the
authored
317 (dolist (opcode '(close ping pong))
3596d84 @ahyatt Write and test websocket-encode-frame.
authored
318 (should (equal
319 opcode
320 (websocket-frame-opcode
321 (websocket-read-frame
0e04e15 @ahyatt Fix issue with encoding & decoding non-payload frames, and fix the
authored
322 (websocket-encode-frame (make-websocket-frame :opcode opcode
323 :completep t))))))))
3596d84 @ahyatt Write and test websocket-encode-frame.
authored
324
33ff92c @ahyatt Update websocket-close and test
authored
325 (ert-deftest websocket-close ()
5c2b235 @ahyatt Implement proper behavior on closing of server.
authored
326 (let ((sent-frames)
327 (processes-deleted))
33ff92c @ahyatt Update websocket-close and test
authored
328 (flet ((websocket-send (websocket frame) (push frame sent-frames))
329 (websocket-openp (websocket) t)
330 (kill-buffer (buffer))
5c2b235 @ahyatt Implement proper behavior on closing of server.
authored
331 (delete-process (proc))
332 (process-buffer (conn) (add-to-list 'processes-deleted conn)))
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
333 (websocket-close (websocket-inner-create
334 :conn "fake-conn"
335 :url t
336 :accept-string t))
33ff92c @ahyatt Update websocket-close and test
authored
337 (should (equal sent-frames (list
338 (make-websocket-frame :opcode 'close
5c2b235 @ahyatt Implement proper behavior on closing of server.
authored
339 :completep t))))
340 (should (equal processes-deleted '("fake-conn"))))))
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
341
342 (ert-deftest websocket-outer-filter ()
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
343 (let* ((fake-ws (websocket-inner-create
344 :conn t :url t :accept-string t
345 :on-open (lambda (websocket)
346 (should (eq (websocket-ready-state websocket)
347 'open))
348 (setq open-callback-called t)
14e94a4 @ahyatt Revamp how error processing works, increasing user control and
authored
349 (error "Ignore me!"))
350 :on-error (lambda (ws type err))))
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
351 (processed-frames)
352 (frame1 (make-websocket-frame :opcode 'text :payload "foo" :completep t
353 :length 9))
354 (frame2 (make-websocket-frame :opcode 'text :payload "bar" :completep t
355 :length 9))
078fbf3 @ahyatt Implemented onopen callback. Soon to be renamed.
authored
356 (open-callback-called)
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
357 (websocket-frames
358 (concat
359 (websocket-encode-frame frame1)
360 (websocket-encode-frame frame2))))
14e94a4 @ahyatt Revamp how error processing works, increasing user control and
authored
361 (flet ((websocket-process-frame
362 (websocket frame)
363 (lexical-let ((frame frame))
364 (lambda () (push frame processed-frames))))
6c42988 @ahyatt Check for HTTP 101 response code, and if there is any failure in the
authored
365 (websocket-verify-response-code (output) t)
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
366 (websocket-verify-headers (websocket output) t))
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
367 (websocket-outer-filter fake-ws "Sec-")
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
368 (should (eq (websocket-ready-state fake-ws) 'connecting))
078fbf3 @ahyatt Implemented onopen callback. Soon to be renamed.
authored
369 (should-not open-callback-called)
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
370 (websocket-outer-filter fake-ws "WebSocket-Accept: acceptstring")
078fbf3 @ahyatt Implemented onopen callback. Soon to be renamed.
authored
371 (should-not open-callback-called)
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
372 (websocket-outer-filter fake-ws (concat
373 "\r\n\r\n"
374 (substring websocket-frames 0 2)))
078fbf3 @ahyatt Implemented onopen callback. Soon to be renamed.
authored
375 (should open-callback-called)
b89e002 @ahyatt Test for websocket-outer-filter, plus removing some useless code from…
authored
376 (websocket-outer-filter fake-ws (substring websocket-frames 2))
a723952 @ahyatt Fix issue with inflight-input not being cleared out.
authored
377 (should (equal (list frame2 frame1) processed-frames))
378 (should-not (websocket-inflight-input fake-ws)))
4040ae0 @jscheid Add test case for bugfix in 8513a7e38d7bf3538d235668ec16081cbd561460.
jscheid authored
379 (flet ((websocket-ready-state (websocket) 'connecting)
380 (websocket-close (websocket)))
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
381 (should (eq 500 (cdr (should-error
382 (websocket-outer-filter fake-ws "HTTP/1.1 500\r\n\r\n")
383 :type 'websocket-received-error-http-response)))))))
6c42988 @ahyatt Check for HTTP 101 response code, and if there is any failure in the
authored
384
385 (ert-deftest websocket-outer-filter-bad-connection ()
386 (let* ((on-open-calledp)
387 (websocket-closed-calledp)
388 (fake-ws (websocket-inner-create
389 :conn t :url t :accept-string t
390 :on-open (lambda (websocket)
391 (setq on-open-calledp t)))))
392 (flet ((websocket-verify-response-code (output) t)
393 (websocket-verify-headers (websocket output) (error "Bad headers!"))
394 (websocket-close (websocket) (setq websocket-closed-calledp t)))
395 (condition-case err
396 (progn (websocket-outer-filter fake-ws "HTTP/1.1 101\r\n\r\n")
397 (error "Should have thrown an error!"))
398 (error
399 (should-not on-open-calledp)
400 (should websocket-closed-calledp))))))
a5f1895 @ahyatt Re-apply the error handling, removed by accident during the merge.
authored
401
d2e4272 @ahyatt Check frame validity, and test it as part of websocket-send
authored
402 (ert-deftest websocket-send ()
fb26aa7 @ahyatt Make the API more like W3C's API.
authored
403 (let ((ws (websocket-inner-create :conn t :url t :accept-string t)))
d2e4272 @ahyatt Check frame validity, and test it as part of websocket-send
authored
404 (flet ((websocket-ensure-connected (websocket))
405 (websocket-openp (websocket) t)
406 (process-send-string (conn string)))
407 ;; Just make sure there is no error.
408 (websocket-send ws (make-websocket-frame :opcode 'ping
409 :completep t)))
410 (should-error (websocket-send ws
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
411 (make-websocket-frame :opcode 'text)))
d2e4272 @ahyatt Check frame validity, and test it as part of websocket-send
authored
412 (should-error (websocket-send ws
413 (make-websocket-frame :opcode 'close
414 :payload "bye!"
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
415 :completep t))
416 :type 'websocket-illegal-frame)
d2e4272 @ahyatt Check frame validity, and test it as part of websocket-send
authored
417 (should-error (websocket-send ws
8904556 @ahyatt Switch from using generic errors, to using named symbols.
authored
418 (make-websocket-frame :opcode :close))
419 :type 'websocket-illegal-frame)))
d2e4272 @ahyatt Check frame validity, and test it as part of websocket-send
authored
420
a98e56f @ahyatt Beginning of server functionality. Completed header checking.
authored
421 (ert-deftest websocket-verify-client-headers ()
422 (let* ((http "HTTP/1.1")
423 (host "Host: authority")
424 (upgrade "Upgrade: websocket")
23b132e @ahyatt Fix failing ert tests
authored
425 (key (format "Sec-Websocket-Key: %s" "key"))
a98e56f @ahyatt Beginning of server functionality. Completed header checking.
authored
426 (version "Sec-Websocket-Version: 13")
427 (origin "Origin: origin")
428 (protocol "Sec-Websocket-Protocol: protocol")
429 (extensions1 "Sec-Websocket-Extensions: foo")
430 (extensions2 "Sec-Websocket-Extensions: bar; baz=2")
431 (all-required-headers (list host upgrade key version)))
432 ;; Test that all these headers are necessary
433 (should (equal
434 '(:key "key" :protocols ("protocol") :extensions ("foo" "bar; baz=2"))
435 (websocket-verify-client-headers
436 (mapconcat 'identity (append (list http "" protocol extensions1 extensions2)
437 all-required-headers) "\r\n"))))
438 (should (websocket-verify-client-headers
439 (mapconcat 'identity
440 (mapcar 'upcase
441 (append (list http "" protocol extensions1 extensions2)
442 all-required-headers)) "\r\n")))
443 (dolist (header all-required-headers)
444 (should-not (websocket-verify-client-headers
445 (mapconcat 'identity (append (list http "")
446 (remove header all-required-headers))
447 "\r\n"))))
448 (should-not (websocket-verify-client-headers
449 (mapconcat 'identity (append (list "HTTP/1.0" "") all-required-headers)
450 "\r\n")))))
451
5a8b995 @ahyatt Add server header generation, and refactor protocol and extension han…
authored
452 (ert-deftest websocket-intersect ()
453 (should (equal '(2) (websocket-intersect '(1 2) '(2 3))))
454 (should (equal nil (websocket-intersect '(1 2) '(3 4))))
455 (should (equal '(1 2) (websocket-intersect '(1 2) '(1 2)))))
456
457 (ert-deftest websocket-get-server-response ()
458 (let ((ws (websocket-inner-create :conn t :url t :accept-string "key"
459 :protocols '("spa" "spb")
460 :extensions '("sea" "seb"))))
461 (should (equal (concat
462 "HTTP/1.1 101 Switching Protocols\r\n"
463 "Upgrade: websocket\r\n"
464 "Connection: Upgrade\r\n"
465 "Sec-WebSocket-Accept: key\r\n\r\n")
466 (websocket-get-server-response ws nil nil)))
467 (should (string-match "Sec-Websocket-Protocol: spb\r\n"
468 (websocket-get-server-response ws '("spb" "spc") nil)))
469 (should-not (string-match "Sec-Websocket-Protocol:"
470 (websocket-get-server-response ws '("spc") nil)))
471 (let ((output (websocket-get-server-response ws '("spa" "spb") nil)))
472 (should (string-match "Sec-Websocket-Protocol: spa\r\n" output))
473 (should (string-match "Sec-Websocket-Protocol: spb\r\n" output)))
474 (should (string-match "Sec-Websocket-Extensions: sea"
475 (websocket-get-server-response ws nil '("sea" "sec"))))
476 (should-not (string-match "Sec-Websocket-Extensions:"
477 (websocket-get-server-response ws nil '("sec"))))
478 (let ((output (websocket-get-server-response ws nil '("sea" "seb"))))
479 (should (string-match "Sec-Websocket-Extensions: sea\r\n" output))
480 (should (string-match "Sec-Websocket-Extensions: seb\r\n" output)))))
481
0202adc @ahyatt Finish and test the server filter function.
authored
482 (ert-deftest websocket-server-filter ()
483 (let ((on-open-called)
484 (ws (websocket-inner-create :conn t :url t :accept-string "key"
485 :on-open (lambda (ws) (setq on-open-called t))))
486 (closed)
487 (response)
488 (processed))
489 (flet ((process-send-string (p text) (setq response text))
490 (websocket-close (ws) (setq closed t))
491 (process-get (process sym) ws))
492 ;; Bad request, in two parts
23b132e @ahyatt Fix failing ert tests
authored
493 (flet ((websocket-verify-client-headers (text) nil))
0202adc @ahyatt Finish and test the server filter function.
authored
494 (websocket-server-filter nil "HTTP/1.0 GET /foo \r\n")
495 (should-not closed)
496 (websocket-server-filter nil "\r\n")
497 (should (equal response "HTTP/1.1 400 Bad Request\r\n\r\n"))
498 (should-not (websocket-inflight-input ws)))
499 ;; Good request, followed by packet
500 (setq closed nil
501 response nil)
502 (setf (websocket-inflight-input ws) nil)
23b132e @ahyatt Fix failing ert tests
authored
503 (flet ((websocket-verify-client-headers (text) t)
0202adc @ahyatt Finish and test the server filter function.
authored
504 (websocket-get-server-response (ws protocols extensions)
505 "response")
506 (websocket-process-input-on-open-ws (ws text)
507 (setq processed t)
508 (should
509 (equal text websocket-test-hello))))
510 (websocket-server-filter nil
511 (concat "\r\n\r\n" websocket-test-hello))
512 (should (equal (websocket-ready-state ws) 'open))
513 (should-not closed)
514 (should (equal response "response"))
515 (should processed)))))
74d5c10 @ahyatt Fix many issues with server connections.
authored
516
517 (ert-deftest websocket-complete-server-response-test ()
518 ;; Example taken from RFC
519 (should (equal
520 (concat "HTTP/1.1 101 Switching Protocols\r\n"
521 "Upgrade: websocket\r\n"
522 "Connection: Upgrade\r\n"
523 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
524 "Sec-WebSocket-Protocol: chat\r\n\r\n"
525 )
526 (let ((header-info
527 (websocket-verify-client-headers
528 (concat "GET /chat HTTP/1.1\r\n"
529 "Host: server.example.com\r\n"
530 "Upgrade: websocket\r\n"
531 "Connection: Upgrade\r\n"
532 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
533 "Origin: http://example.com\r\n"
534 "Sec-WebSocket-Protocol: chat, superchat\r\n"
535 "Sec-WebSocket-Version: 13\r\n"))))
536 (should header-info)
537 (let ((ws (websocket-inner-create
538 :conn t :url t
539 :accept-string (websocket-calculate-accept
540 (plist-get header-info :key))
541 :protocols '("chat"))))
542 (websocket-get-server-response
543 ws
544 (plist-get header-info :protocols)
545 (plist-get header-info :extension)))))))
5c2b235 @ahyatt Implement proper behavior on closing of server.
authored
546
547 (ert-deftest websocket-server-close ()
548 (let ((websocket-server-websockets
549 (list (websocket-inner-create :conn 'conn-a :url t :accept-string t
550 :server-conn 'a
551 :ready-state 'open)
552 (websocket-inner-create :conn 'conn-b :url t :accept-string t
553 :server-conn 'b
554 :ready-state 'open)
555 (websocket-inner-create :conn 'conn-c :url t :accept-string t
556 :server-conn 'b
557 :ready-state 'closed)))
558 (deleted-processes)
559 (closed-websockets))
560 (flet ((delete-process (conn) (add-to-list 'deleted-processes conn))
561 (websocket-close (ws)
562 ;; we always remove on closing in the
563 ;; actual code.
564 (setq websocket-server-websockets
565 (remove ws websocket-server-websockets))
566 (should-not (eq (websocket-ready-state ws) 'closed))
567 (add-to-list 'closed-websockets ws)))
568 (websocket-server-close 'b))
569 (should (equal deleted-processes '(b)))
570 (should (eq 1 (length closed-websockets)))
571 (should (eq 'conn-b (websocket-conn (car closed-websockets))))
572 (should (eq 1 (length websocket-server-websockets)))
573 (should (eq 'conn-a (websocket-conn (car websocket-server-websockets))))))
Something went wrong with that request. Please try again.