OLD | NEW |
---|---|
(Empty) | |
1 // Variables used in js-test.js assertions. | |
2 var exceptionName; | |
3 var exceptionMessage; | |
4 var exceptionProto; | |
5 var closeEvent; | |
6 | |
7 // Constants. | |
8 const invalidAccessErr = "InvalidAccessError"; | |
9 const syntaxErr = "SyntaxError"; | |
10 const normalClosure = 1000; | |
11 const abnormalClosure = 1006; | |
12 const url = "ws://127.0.0.1:8880/close"; | |
13 const ws_handlers = ["onopen", "onerror", "onclose", "onmessage"]; | |
14 | |
15 // An explicit timeout is used so that we can capture the test output. | |
16 var timeout; | |
17 | |
18 const badCodesTestCodes = [ | |
19 999, 1001, 2999, 5000, 65536 + 1000, 0x100000000 + 1000, 2999.9, NaN, "0", " 100", 1/0, -1/0, 0/0, | |
20 ]; | |
21 | |
22 const badReasonTestReasons = [ | |
23 "123456789012345678901234567890123456789012345678901234567890123456789012345 6789012345678901234567890123456789012345678901234", // 124 Byte | |
24 "123456789012345678901234567890123456789012345678901234567890123456789012345 67890123456789012345678901234567890123456789012\u00a9", // length is 123, but 12 4 Byte in UTF-8 | |
25 ]; | |
26 | |
27 function createFailHandler(name, ws, reject) | |
28 { | |
29 return function () { | |
yhirano
2015/02/27 06:26:44
Please be consistent whether you put a space after
Adam Rice
2015/02/27 09:34:28
Originally this test used function () {...} style,
| |
30 removeAllHandlers(ws); | |
31 reject(name + " was called."); | |
32 }; | |
33 } | |
34 | |
35 function setDefaultHandlers(ws, reject) | |
36 { | |
37 ws_handlers.forEach(function (handler) { | |
38 ws[handler] = createFailHandler(handler, ws, reject); | |
39 }); | |
40 } | |
41 | |
42 // Ensure that the WebSocket can be garbage collected. | |
43 function removeAllHandlers(ws) | |
44 { | |
45 ws_handlers.forEach(function (handler) { | |
46 ws[handler] = undefined; | |
47 }); | |
48 } | |
49 | |
50 // Verify that close() throws an exception when an invalid close code is passed. | |
51 function badCodesTest() | |
52 { | |
53 return new Promise(function (resolve, reject) { | |
54 debug("badCodesTest: started"); | |
55 var ws = new WebSocket(url); | |
56 setDefaultHandlers(ws, reject); | |
57 for (var id = 0; id < badCodesTestCodes.length; ++id) { | |
yhirano
2015/02/27 06:26:44
[optional] You can use |for (var test_code of badC
Adam Rice
2015/02/27 09:34:28
I didn't know that worked yet. Thanks.
| |
58 var test_code = badCodesTestCodes[id]; | |
59 debug("badCodesTest: " + test_code); | |
60 try { | |
61 ws.close(test_code); | |
62 reject("Exception not thrown for code " + test_code); | |
63 return; | |
64 } catch (e) { | |
65 exceptionName = e.name; | |
66 exceptionMessage = e.message; | |
67 exceptionProto = Object.getPrototypeOf(e); | |
68 shouldBeTrue("exceptionProto === DOMException.prototype"); | |
69 shouldBeEqualToString("exceptionName", invalidAccessErr); | |
70 var expectedCode = test_code; | |
71 if (!expectedCode) | |
72 expectedCode = 0; | |
73 else if (expectedCode > 65535) | |
74 expectedCode = 65535; | |
75 else if (expectedCode < 0) | |
76 expectedCode = 0; | |
77 expectedCode = Math.floor(expectedCode); | |
78 shouldBeEqualToString("exceptionMessage", "Failed to execute 'cl ose' on 'WebSocket': The code must be either 1000, or between 3000 and 4999. " + expectedCode + " is neither."); | |
79 } | |
80 } | |
81 removeAllHandlers(ws); | |
82 resolve(); | |
83 }); | |
84 } | |
85 | |
86 // Verify that passing a valid code does not throw an exception. | |
87 function goodCodeTest() | |
88 { | |
89 return new Promise(function (resolve, reject) { | |
90 debug("goodCodeTest: started"); | |
91 var ws = new WebSocket(url); | |
92 setDefaultHandlers(ws, reject); | |
93 ws.onclose = function (e) | |
94 { | |
95 closeEvent = e; | |
96 shouldBeEqualToNumber("closeEvent.code", abnormalClosure); | |
97 resolve(); | |
98 }; | |
99 ws.onerror = function() | |
100 { | |
101 testPassed("onerror was called."); | |
102 }; | |
103 ws.close(1000.0); | |
104 }); | |
105 } | |
106 | |
107 // Verify that unpaired surrogates in the reason string are converted to U+FFFD | |
108 // before sending to the remote server. | |
109 function invalidUnicodeReasonTest() | |
110 { | |
111 return new Promise(function (resolve, reject) { | |
112 debug("invalidUnicodeReasonTest: started"); | |
113 var ws = new WebSocket(url); | |
yhirano
2015/02/27 06:26:44
+setDefaultHandlers
Adam Rice
2015/02/27 09:34:28
Done.
| |
114 ws.onopen = function() { | |
115 // 0xD834 is an unpaired surrogate. | |
116 var invalidString = String.fromCharCode(0xD834); | |
117 ws.close(1000, invalidString); | |
118 }; | |
119 ws.onclose = function(e) { | |
120 closeEvent = e; | |
121 shouldBeTrue("closeEvent.wasClean"); | |
122 shouldBeEqualToString("closeEvent.reason", "\uFFFD"); | |
123 resolve(); | |
124 }; | |
125 }); | |
126 } | |
127 | |
128 // Verify that invalid reason strings passed to close() result in an exception | |
129 // being thrown. | |
130 function badReasonTest() | |
131 { | |
132 return new Promise(function (resolve, reject) { | |
133 debug("badReasonTest: started"); | |
134 var ws = new WebSocket(url); | |
135 setDefaultHandlers(ws, reject); | |
136 for (var id = 0; id < badReasonTestReasons.length; ++id) { | |
137 var test_reason = badReasonTestReasons[id]; | |
138 debug("badReasonTest: " + test_reason); | |
139 try { | |
140 ws.close(normalClosure, test_reason); | |
141 reject("Exception not thrown for bad reason " + test_reason); | |
142 return; | |
143 } catch (e) { | |
144 exceptionName = e.name; | |
145 exceptionProto = Object.getPrototypeOf(e); | |
146 shouldBeTrue("exceptionProto === DOMException.prototype"); | |
147 shouldBeEqualToString("exceptionName", syntaxErr); | |
148 } | |
149 } | |
150 removeAllHandlers(ws); | |
151 resolve(); | |
152 }); | |
153 } | |
154 | |
155 // Verify that a valid reason code passed to close() does not result in an | |
156 // exception. | |
157 function goodReasonTest() | |
158 { | |
159 return new Promise(function (resolve, reject) { | |
160 debug("goodReasonTest: started"); | |
161 var ws = new WebSocket(url); | |
yhirano
2015/02/27 06:26:44
+setDefaultHandlers
Adam Rice
2015/02/27 09:34:28
Done.
| |
162 ws.onclose = function (e) | |
163 { | |
164 closeEvent = e; | |
165 shouldBeEqualToNumber("closeEvent.code", abnormalClosure); | |
166 resolve(); | |
167 }; | |
168 ws.onerror = function() | |
169 { | |
170 testPassed("onerror was called."); | |
171 }; | |
172 // 123 byte reason should not throw. | |
173 ws.close(normalClosure, "12345678901234567890123456789012345678901234567 8901234567890123456789012345678901234567890123456789012345678901234567890123"); | |
174 }); | |
175 } | |
176 | |
177 // Verify that valid close codes and reasons are correctly send to the | |
178 // WebSocket server. | |
179 function codeAndReasonTest() | |
180 { | |
181 const codes = [ | |
182 1000, | |
183 3000, | |
184 4000, | |
185 4999 | |
186 ]; | |
187 const reasons = [ | |
188 "OK, Bye!", | |
189 "3000", | |
190 "code is 4000", | |
191 "\u00a9 Google" | |
192 ]; | |
193 return new Promise(function(resolve, reject) { | |
194 debug("codeAndReasonTest: started"); | |
195 // Tests are run in series to produce deterministic output. | |
196 var promise = Promise.resolve(); | |
197 for (var id = 0; id < codes.length; ++id) { | |
198 promise = promise.then(codeAndReasonSingleCase(codes[id], reasons[id ])); | |
199 } | |
200 promise.then(resolve); | |
201 }); | |
202 } | |
203 | |
204 // (Return a function which returns a Promise to) handle a single code/reason | |
205 // pair for the codeAndReasonTest. | |
206 function codeAndReasonSingleCase(test_code, test_reason) { | |
207 return function() { | |
208 return new Promise(function (resolve, reject) { | |
209 debug("codeAndReasonTest: " + test_code + ", '" + test_reason + "'") ; | |
210 var ws = new WebSocket(url); | |
211 setDefaultHandlers(ws, reject); | |
212 ws.onopen = function () | |
213 { | |
214 ws.close(test_code, test_reason); | |
215 }; | |
216 ws.onclose = function (e) | |
217 { | |
218 closeEvent = e; | |
219 shouldBeTrue("closeEvent.wasClean"); | |
220 shouldBeEqualToNumber("closeEvent.code", test_code); | |
221 shouldBeEqualToString("closeEvent.reason", test_reason); | |
222 resolve(); | |
223 }; | |
224 }); | |
225 }; | |
226 } | |
227 | |
228 function cleanup() { | |
229 clearTimeout(timeout); | |
230 finishJSTest(); | |
231 } | |
232 | |
233 function onTimeout() { | |
234 handleRejection("Timeout"); | |
235 } | |
236 | |
237 function handleRejection(reason) { | |
238 if (reason instanceof Error) { | |
239 // Get a stack trace if an exception fired. | |
240 testFailed(reason.stack); | |
241 } else { | |
242 testFailed(reason); | |
243 } | |
244 cleanup(); | |
245 } | |
246 | |
247 function testClose() { | |
248 // Set an explicit timeout in order to keep text output on failure. | |
249 timeout = setTimeout(onTimeout, 5000); | |
250 // Tests are run in series to produce deterministic output. | |
251 badCodesTest() | |
252 .then(goodCodeTest) | |
253 .then(invalidUnicodeReasonTest) | |
254 .then(badReasonTest) | |
255 .then(goodReasonTest) | |
256 .then(codeAndReasonTest) | |
257 .then(cleanup) | |
258 .catch(handleRejection); | |
259 } | |
OLD | NEW |