Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"></meta>
5 <title>WebSocket test</title>
6 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
8 </head>
9 <body onload="testWebSocket()">
10 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=472529">Mozilla Bug </a>
11 <p id="display">
12 <input id="fileList" type="file"></input>
13 </p>
14 <div id="content">
15 </div>
16 <pre id="test">
17 <script class="testbody" type="text/javascript">
19 /*
20 * tests:
21 * 1. client tries to connect to a http scheme location;
22 * 2. assure serialization of the connections;
23 * 3. client tries to connect to an non-existent ws server;
24 * 4. client tries to connect using a relative url;
25 * 5. client uses an invalid protocol value;
26 * 6. counter and encoding check;
27 * 7. onmessage event origin property check
28 * 8. client calls close() and the server sends the close frame (with no code
29 * or reason) in acknowledgement;
30 * 9. client closes the connection before the ws connection is established;
31 * 10. client sends a message before the ws connection is established;
32 * 11. a simple hello echo;
33 * 12. client sends a message containing unpaired surrogates
34 * 13. server sends an invalid message;
35 * 14. server sends the close frame, it doesn't close the tcp connection and
36 * it keeps sending normal ws messages;
37 * 15. server closes the tcp connection, but it doesn't send the close frame;
38 * 16. client calls close() and tries to send a message;
39 * 17. see bug 572975 - all event listeners set
40 * 18. client tries to connect to an http resource;
41 * 19. server closes the tcp connection before establishing the ws connection;
42 * 20. see bug 572975 - only on error and onclose event listeners set
43 * 21. see bug 572975 - same as test 17, but delete strong event listeners when
44 * receiving the message event;
45 * 22. server takes too long to establish the ws connection;
46 * 23. should detect WebSocket on window object;
47 * 24. server rejects sub-protocol string
48 * 25. ctor with valid empty sub-protocol array
49 * 26. ctor with invalid sub-protocol array containing 1 empty element
50 * 27. ctor with invalid sub-protocol array containing an empty element in list
51 * 28. ctor using valid 1 element sub-protocol array
52 * 29. ctor using all valid 5 element sub-protocol array
53 * 30. ctor using valid 1 element sub-protocol array with element server will
54 * reject
55 * 31. ctor using valid 2 element sub-protocol array with 1 element server
56 * will reject and one server will accept.
57 * 32. ctor using invalid sub-protocol array that contains duplicate items
58 * 33. test for sending/receiving custom close code (but no close reason)
59 * 34. test for receiving custom close code and reason
60 * 35. test for sending custom close code and reason
61 * 36. negative test for sending out of range close code
62 * 37. negative test for too long of a close reason
63 * 38. ensure extensions attribute is defined
64 * 39. a basic wss:// connectivity test
65 * 40. negative test for wss:// with no cert
66 * 41. HSTS
67 * 42. non-char utf-8 sequences
68 * 43. Test setting binaryType attribute
69 * 44. Test sending/receving binary ArrayBuffer
70 * 45. Test sending/receving binary Blob
71 * 46. Test that we don't dispatch incoming msgs once in CLOSING state
72 * 47. Make sure onerror/onclose aren't called during close()
73 */
75 var first_test = 1;
76 var last_test = 47;
79 // Set this to >1 if you want to run the suite multiple times to probe for
80 // random orange failures.
81 // - Do NOT check into mozilla-central with a value != 1.
82 // - Too large a count will wind up causing tryserver to timeout the test (which
83 // is ok, but means all testruns will be orange). If I set first_test to >22
84 // (i.e don't run any of the tests that require waiting) I can get ~250-300
85 // iterations of the remaining tests w/o a timeout.
86 var testsuite_iterations = 1;
89 var current_test = first_test;
90 var testsuite_iteration = 1;
92 var test_started = new Array(last_test);
93 var all_ws = [];
95 function shouldNotOpen(e)
96 {
97 var ws = e.target;
98 ok(false, "onopen shouldn't be called on test " + ws._testNumber + "!");
99 }
101 function shouldNotReceiveCloseEvent(e)
102 {
103 var ws = e.target;
104 var extendedErrorInfo = "";
105 if (!ws._testNumber) {
106 extendedErrorInfo += "\nws members:\n";
107 for (var i in ws) {
108 extendedErrorInfo += (i + ": " + ws[i] + "\n");
109 }
111 extendedErrorInfo += "\ne members:\n";
112 for (var i in e) {
113 extendedErrorInfo += (i + ": " + e[i] + "\n");
114 }
115 }
117 // FIXME: see bug 578276. This should be a test failure, but it's too flaky on the tbox.
118 ok(true, "onclose shouldn't be called on test " + ws._testNumber + "!" + extendedErrorInfo);
119 }
121 function shouldCloseCleanly(e)
122 {
123 var ws = e.target;
124 ok(e.wasClean, "the ws connection in test " + ws._testNumber + " should be closed cleanly");
125 }
127 function shouldCloseNotCleanly(e)
128 {
129 var ws = e.target;
130 ok(!e.wasClean, "the ws connection in test " + ws._testNumber + " shouldn't be closed cleanly");
131 }
133 function ignoreError(e)
134 {
135 }
137 function CreateTestWS(ws_location, ws_protocol, no_increment_test)
138 {
139 var ws;
141 try {
142 if (ws_protocol == undefined) {
143 ws = new WebSocket(ws_location);
144 } else {
145 ws = new WebSocket(ws_location, ws_protocol);
146 }
149 ws._testNumber = current_test;
150 ws._receivedCloseEvent = false;
151 ok(true, "Created websocket for test " + ws._testNumber +"\n");
153 ws.onerror = function(e)
154 {
155 ok(false, "onerror called on test " + e.target._testNumber + "!");
156 };
157 ws.addEventListener("close", function(e)
158 {
159 ws._receivedCloseEvent = true;
160 }, false);
161 }
162 catch (e) {
163 throw e;
164 }
165 finally {
166 if (!no_increment_test) {
167 current_test++;
168 }
169 }
171 all_ws.push(ws);
172 return ws;
173 }
175 function forcegc()
176 {
177 SpecialPowers.forceGC();
178 SpecialPowers.gc();
179 setTimeout(function()
180 {
181 SpecialPowers.gc();
182 }, 1);
183 }
185 function doTest(number)
186 {
187 if (number > last_test) {
188 ranAllTests = true;
189 maybeFinished();
190 return;
191 }
193 if (testsuite_iteration > 1) {
194 $("feedback").innerHTML = "test suite iteration #" + testsuite_iteration + " of " + testsuite_iterations +
195 ": executing test: " + number + " of " + last_test + " tests.";
196 } else {
197 $("feedback").innerHTML = "executing test: " + number + " of " + last_test + " tests.";
198 }
200 var fnTest = eval("test" + number + "");
202 if (test_started[number] === true) {
203 doTest(number + 1);
204 return;
205 }
207 test_started[number] = true;
208 fnTest();
209 }
210 doTest.timeoutId = null;
212 function test1()
213 {
214 try {
215 var ws = CreateTestWS("http://mochi.test:8888/tests/content/base/test/file_websocket");
216 ok(false, "test1 failed");
217 }
218 catch (e) {
219 ok(true, "test1 failed");
220 }
221 doTest(2);
222 }
224 // this test expects that the serialization list to connect to the proxy
225 // is empty. Use different domain so we can run this in the background
226 // and not delay other tests.
228 var waitTest2Part1 = false;
229 var waitTest2Part2 = false;
231 function test2()
232 {
233 waitTest2Part1 = true;
234 waitTest2Part2 = true;
236 var ws1 = CreateTestWS("ws://sub2.test2.example.com/tests/content/base/test/file_websocket", "test-2.1");
237 current_test--; // CreateTestWS incremented this
238 var ws2 = CreateTestWS("ws://sub2.test2.example.com/tests/content/base/test/file_websocket", "test-2.2");
240 var ws2CanConnect = false;
242 // the server will delay ws1 for 5 seconds, but the other tests can
243 // proceed in parallel
244 doTest(3);
246 ws1.onopen = function()
247 {
248 ok(true, "ws1 open in test 2");
249 ws2CanConnect = true;
250 ws1.close();
251 }
253 ws1.onclose = function(e)
254 {
255 waitTest2Part1 = false;
256 maybeFinished();
257 };
259 ws2.onopen = function()
260 {
261 ok(ws2CanConnect, "shouldn't connect yet in test-2!");
262 ws2.close();
263 }
265 ws2.onclose = function(e)
266 {
267 waitTest2Part2 = false;
268 maybeFinished();
269 };
270 }
272 function test3()
273 {
274 var hasError = false;
275 var ws = CreateTestWS("ws://this.websocket.server.probably.does.not.exist");
276 ws.onopen = shouldNotOpen;
277 ws.onerror = function (e)
278 {
279 hasError = true;
280 }
282 ws.onclose = function(e)
283 {
284 shouldCloseNotCleanly(e);
285 ok(hasError, "rcvd onerror event");
286 ok(e.code == 1006, "test-3 close code should be 1006 but is:" + e.code);
287 doTest(4);
288 };
289 }
291 function test4()
292 {
293 try {
294 var ws = CreateTestWS("file_websocket");
295 ok(false, "test-4 failed");
296 }
297 catch (e) {
298 ok(true, "test-4 failed");
299 }
300 doTest(5);
301 }
303 function test5()
304 {
305 try {
306 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "");
307 ok(false, "couldn't accept an empty string in the protocol parameter");
308 }
309 catch (e) {
310 ok(true, "couldn't accept an empty string in the protocol parameter");
311 }
312 current_test--; // CreateTestWS incremented this
313 try {
314 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "\n");
315 ok(false, "couldn't accept any not printable ASCII character in the protocol parameter");
316 }
317 catch (e) {
318 ok(true, "couldn't accept any not printable ASCII character in the protocol parameter");
319 }
320 current_test--; // CreateTestWS incremented this
321 try {
322 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 5");
323 ok(false, "U+0020 not acceptable in protocol parameter");
324 }
325 catch (e) {
326 ok(true, "U+0020 not acceptable in protocol parameter");
327 }
328 doTest(6);
329 }
331 function test6()
332 {
333 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-6");
334 var counter = 1;
335 ws.onopen = function()
336 {
337 ws.send(counter);
338 }
339 ws.onmessage = function(e)
340 {
341 if (counter == 5) {
342 ok(e.data == "あいうえお", "test-6 counter 5 data ok");
343 ws.close();
344 } else {
345 ok(e.data == counter+1, "bad counter");
346 counter += 2;
347 ws.send(counter);
348 }
349 }
350 ws.onclose = function(e)
351 {
352 shouldCloseCleanly(e);
353 doTest(7);
354 };
355 }
357 function test7()
358 {
359 var ws = CreateTestWS("ws://sub2.test2.example.org/tests/content/base/test/file_websocket", "test-7");
360 var gotmsg = false;
362 ws.onopen = function()
363 {
364 ok(true, "test 7 open");
365 }
366 ws.onmessage = function(e)
367 {
368 ok(true, "test 7 message");
369 ok(e.origin == "ws://sub2.test2.example.org", "onmessage origin set to ws:// host");
370 gotmsg = true;
371 ws.close();
372 }
373 ws.onclose = function(e)
374 {
375 ok(gotmsg, "recvd message in test 7 before close");
376 shouldCloseCleanly(e);
377 doTest(8);
378 };
379 }
381 function test8()
382 {
383 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-8");
384 ws.onopen = function()
385 {
386 ok(ws.protocol == "test-8", "test-8 subprotocol selection");
387 ws.close();
388 }
389 ws.onclose = function(e)
390 {
391 shouldCloseCleanly(e);
392 // We called close() with no close code: so pywebsocket will also send no
393 // close code, which translates to code 1005
394 ok(e.code == 1005, "test-8 close code has wrong value:" + e.code);
395 ok(e.reason == "", "test-8 close reason has wrong value:" + e.reason);
396 doTest(9);
397 };
398 }
400 var waitTest9 = false;
402 function test9()
403 {
404 waitTest9 = true;
406 var ws = CreateTestWS("ws://test2.example.org/tests/content/base/test/file_websocket", "test-9");
407 ws._receivedErrorEvent = false;
408 ws.onopen = shouldNotOpen;
409 ws.onerror = function(e)
410 {
411 ws._receivedErrorEvent = true;
412 };
413 ws.onclose = function(e)
414 {
415 ok(ws._receivedErrorEvent, "Didn't received the error event in test 9.");
416 shouldCloseNotCleanly(e);
417 waitTest9 = false;
418 maybeFinished();
419 };
421 ws.close();
423 // the server injects a delay, so proceed with this in the background
424 doTest(10);
425 }
427 var waitTest10 = false;
429 function test10()
430 {
431 waitTest10 = true;
433 var ws = CreateTestWS("ws://sub1.test1.example.com/tests/content/base/test/file_websocket", "test-10");
434 ws.onclose = function(e)
435 {
436 shouldCloseCleanly(e);
437 waitTest10 = false;
438 maybeFinished();
439 }
441 try {
442 ws.send("client data");
443 ok(false, "Couldn't send data before connecting!");
444 }
445 catch (e) {
446 ok(true, "Couldn't send data before connecting!");
447 }
448 ws.onopen = function()
449 {
450 ok(true, "test 10 opened");
451 ws.close();
452 }
454 // proceed with this test in the background
455 doTest(11);
456 }
458 function test11()
459 {
460 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-11");
461 ok(ws.readyState == 0, "create bad readyState in test-11!");
462 ws.onopen = function()
463 {
464 ok(ws.readyState == 1, "open bad readyState in test-11!");
465 ws.send("client data");
466 }
467 ws.onmessage = function(e)
468 {
469 ok(e.data == "server data", "bad received message in test-11!");
470 ws.close(1000, "Have a nice day");
472 // this ok() is disabled due to a race condition - it state may have
473 // advanced through 2 (closing) and into 3 (closed) before it is evald
474 // ok(ws.readyState == 2, "onmessage bad readyState in test-11!");
475 }
476 ws.onclose = function(e)
477 {
478 ok(ws.readyState == 3, "onclose bad readyState in test-11!");
479 shouldCloseCleanly(e);
480 ok(e.code == 1000, "test 11 got wrong close code: " + e.code);
481 ok(e.reason == "Have a nice day", "test 11 got wrong close reason: " + e.reason);
482 doTest(12);
483 }
484 }
486 function test12()
487 {
488 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-12");
489 ws.onopen = function()
490 {
491 try {
492 // send an unpaired surrogate
493 ws._gotMessage = false;
494 ws.send("a\ud800b");
495 ok(true, "ok to send an unpaired surrogate");
496 }
497 catch (e) {
498 ok(false, "shouldn't fail any more when sending an unpaired surrogate!");
499 }
500 }
502 ws.onmessage = function(msg)
503 {
504 ok(msg.data == "SUCCESS", "Unpaired surrogate in UTF-16 not converted in test-12");
505 ws._gotMessage = true;
506 // Must support unpaired surrogates in close reason, too
507 ws.close(1000, "a\ud800b");
508 }
510 ws.onclose = function(e)
511 {
512 ok(ws.readyState == 3, "onclose bad readyState in test-12!");
513 ok(ws._gotMessage, "didn't receive message!");
514 shouldCloseCleanly(e);
515 ok(e.code == 1000, "test 12 got wrong close code: " + e.code);
516 ok(e.reason == "a\ufffdb", "test 11 didn't get replacement char in close reason: " + e.reason);
517 doTest(13);
518 }
519 }
521 function test13()
522 {
523 // previous versions of this test counted the number of protocol errors returned, but the
524 // protocol stack typically closes down after reporting a protocol level error - trying
525 // to resync is too dangerous
527 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-13");
528 ws._timesCalledOnError = 0;
529 ws.onerror = function()
530 {
531 ws._timesCalledOnError++;
532 }
533 ws.onclose = function(e)
534 {
535 ok(ws._timesCalledOnError > 0, "no error events");
536 doTest(14);
537 }
538 }
540 function test14()
541 {
542 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-14");
543 ws.onmessage = function()
544 {
545 ok(false, "shouldn't received message after the server sent the close frame");
546 }
547 ws.onclose = function(e)
548 {
549 shouldCloseCleanly(e);
550 // Skip test 15 for now: broken
551 doTest(16);
552 };
553 }
555 /*
556 * DISABLED: see comments for test-15 case in file_websocket_wsh.py
557 *
558 function test15()
559 {
560 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-15");
561 ws.onclose = function(e)
562 {
563 shouldCloseNotCleanly(e);
564 doTest(16);
565 };
567 // termination of the connection might cause an error event if it happens in OPEN
568 ws.onerror = function()
569 {
570 }
572 }
573 */
575 function test16()
576 {
577 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-16");
578 ws.onopen = function()
579 {
580 ws.close();
581 ok(!ws.send("client data"), "shouldn't send message after calling close()");
582 }
583 ws.onmessage = function()
584 {
585 ok(false, "shouldn't send message after calling close()");
586 }
588 ws.onerror = function()
589 {
590 }
591 ws.onclose = function()
592 {
593 doTest(17);
594 }
595 }
597 var status_test17 = "not started";
599 var waitTest17 = false;
601 var test17func = function()
602 {
603 waitTest17 = true;
605 var local_ws = new WebSocket("ws://sub1.test2.example.org/tests/content/base/test/file_websocket", "test-17");
606 local_ws._testNumber = "local17";
607 local_ws._testNumber = current_test++;
609 status_test17 = "started";
611 local_ws.onopen = function(e)
612 {
613 status_test17 = "opened";
614 e.target.send("client data");
615 forcegc();
616 };
618 local_ws.onerror = function()
619 {
620 ok(false, "onerror called on test " + e.target._testNumber + "!");
621 };
623 local_ws.onmessage = function(e)
624 {
625 ok(e.data == "server data", "Bad message in test-17");
626 status_test17 = "got message";
627 forcegc();
628 };
630 local_ws.onclose = function(e)
631 {
632 ok(status_test17 == "got message", "Didn't got message in test-17!");
633 shouldCloseCleanly(e);
634 status_test17 = "closed";
635 forcegc();
636 waitTest17 = false;
637 maybeFinished();
638 };
640 local_ws = null;
641 window._test17 = null;
642 forcegc();
644 // do this in the background
645 doTest(18);
646 forcegc();
647 }
649 function test17()
650 {
651 window._test17 = test17func;
652 window._test17();
653 }
655 // The tests that expects that their websockets neither open nor close MUST
656 // be in the end of the tests, i.e. HERE, in order to prevent blocking the other
657 // tests.
659 function test18()
660 {
661 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket_http_resource.txt");
662 ws.onopen = shouldNotOpen;
663 ws.onerror = ignoreError;
664 ws.onclose = function(e)
665 {
666 shouldCloseNotCleanly(e);
667 doTest(19);
668 };
669 }
671 function test19()
672 {
673 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-19");
674 ws.onopen = shouldNotOpen;
675 ws.onerror = ignoreError;
676 ws.onclose = function(e)
677 {
678 shouldCloseNotCleanly(e);
679 doTest(20);
680 };
681 }
683 var waitTest20 = false;
685 var test20func = function()
686 {
687 waitTest20 = true;
689 var local_ws = new WebSocket("ws://sub1.test1.example.org/tests/content/base/test/file_websocket", "test-20");
690 local_ws._testNumber = "local20";
691 local_ws._testNumber = current_test++;
693 local_ws.onerror = function()
694 {
695 ok(false, "onerror called on test " + e.target._testNumber + "!");
696 };
698 local_ws.onclose = function(e)
699 {
700 ok(true, "test 20 closed despite gc");
701 waitTest20 = false;
702 maybeFinished();
703 };
705 local_ws = null;
706 window._test20 = null;
707 forcegc();
709 // let test run in the background
710 doTest(21);
711 }
713 function test20()
714 {
715 window._test20 = test20func;
716 window._test20();
717 }
719 var waitTest21 = false;
721 test21func = function()
722 {
723 waitTest21 = true;
725 var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-21");
726 local_ws._testNumber = current_test++;
727 var received_message = false;
729 local_ws.onopen = function(e)
730 {
731 e.target.send("client data");
732 forcegc();
733 e.target.onopen = null;
734 forcegc();
735 };
737 local_ws.onerror = function()
738 {
739 ok(false, "onerror called on test " + e.target._testNumber + "!");
740 };
742 local_ws.onmessage = function(e)
743 {
744 ok(e.data == "server data", "Bad message in test-21");
745 received_message = true;
746 forcegc();
747 e.target.onmessage = null;
748 forcegc();
749 };
751 local_ws.onclose = function(e)
752 {
753 shouldCloseCleanly(e);
754 ok(received_message, "close transitioned through onmessage");
755 waitTest21 = false;
756 maybeFinished();
757 };
759 local_ws = null;
760 window._test21 = null;
761 forcegc();
763 doTest(22);
765 }
767 function test21()
768 {
769 window._test21 = test21func;
770 window._test21();
771 }
773 var waitTest22 = false;
775 function test22()
776 {
777 waitTest22 = true;
779 const pref_open = "network.websocket.timeout.open";
780 SpecialPowers.setIntPref(pref_open, 5);
782 var ws = CreateTestWS("ws://sub2.test2.example.org/tests/content/base/test/file_websocket", "test-22");
783 ws.onopen = shouldNotOpen;
784 ws.onerror = ignoreError;
785 ws.onclose = function(e)
786 {
787 shouldCloseNotCleanly(e);
788 waitTest22 = false;
789 maybeFinished();
790 };
792 SpecialPowers.clearUserPref(pref_open);
793 doTest(23);
794 }
796 function test23()
797 {
798 current_test++;
799 is(true, "WebSocket" in window, "WebSocket should be available on window object");
800 doTest(24);
801 }
803 function test24()
804 {
805 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-does-not-exist");
806 ws.onopen = shouldNotOpen;
807 ws.onclose = function(e)
808 {
809 shouldCloseNotCleanly(e);
810 doTest(25);
811 };
812 ws.onerror = function()
813 {
814 }
815 }
817 function test25()
818 {
819 var prots=[];
821 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
823 // This test errors because the server requires a sub-protocol, but
824 // the test just wants to ensure that the ctor doesn't generate an
825 // exception
826 ws.onerror = ignoreError;
827 ws.onopen = shouldNotOpen;
829 ws.onclose = function(e)
830 {
831 ok(ws.protocol == "", "test25 subprotocol selection");
832 ok(true, "test 25 protocol array close");
833 doTest(26);
834 };
835 }
837 function test26()
838 {
839 var prots=[""];
841 try {
842 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
843 ok(false, "testing empty element sub protocol array");
844 }
845 catch (e) {
846 ok(true, "testing empty sub element protocol array");
847 }
848 doTest(27);
849 }
851 function test27()
852 {
853 var prots=["test27", ""];
855 try {
856 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
857 ok(false, "testing empty element mixed sub protocol array");
858 }
859 catch (e) {
860 ok(true, "testing empty element mixed sub protocol array");
861 }
862 doTest(28);
863 }
865 function test28()
866 {
867 var prots=["test28"];
869 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
870 ws.onopen = function(e)
871 {
872 ok(true, "test 28 protocol array open");
873 ws.close();
874 };
876 ws.onclose = function(e)
877 {
878 ok(ws.protocol == "test28", "test28 subprotocol selection");
879 ok(true, "test 28 protocol array close");
880 doTest(29);
881 };
882 }
884 function test29()
885 {
886 var prots=["test29a", "test29b"];
888 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
889 ws.onopen = function(e)
890 {
891 ok(true, "test 29 protocol array open");
892 ws.close();
893 };
895 ws.onclose = function(e)
896 {
897 ok(true, "test 29 protocol array close");
898 doTest(30);
899 };
900 }
902 function test30()
903 {
904 var prots=["test-does-not-exist"];
905 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
907 ws.onopen = shouldNotOpen;
908 ws.onclose = function(e)
909 {
910 shouldCloseNotCleanly(e);
911 doTest(31);
912 };
913 ws.onerror = function()
914 {
915 }
916 }
918 function test31()
919 {
920 var prots=["test-does-not-exist", "test31"];
921 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
923 ws.onopen = function(e)
924 {
925 ok(true, "test 31 protocol array open");
926 ws.close();
927 };
929 ws.onclose = function(e)
930 {
931 ok(ws.protocol == "test31", "test31 subprotocol selection");
932 ok(true, "test 31 protocol array close");
933 doTest(32);
934 };
935 }
937 function test32()
938 {
939 var prots=["test32","test32"];
941 try {
942 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
943 ok(false, "testing duplicated element sub protocol array");
944 }
945 catch (e) {
946 ok(true, "testing duplicated sub element protocol array");
947 }
948 doTest(33);
949 }
951 function test33()
952 {
953 var prots=["test33"];
955 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
956 ws.onopen = function(e)
957 {
958 ok(true, "test 33 open");
959 ws.close(3131); // pass code but not reason
960 };
962 ws.onclose = function(e)
963 {
964 ok(true, "test 33 close");
965 shouldCloseCleanly(e);
966 ok(e.code == 3131, "test 33 got wrong close code: " + e.code);
967 ok(e.reason === "", "test 33 got wrong close reason: " + e.reason);
968 doTest(34);
969 };
970 }
972 function test34()
973 {
974 var prots=["test-34"];
976 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
977 ws.onopen = function(e)
978 {
979 ok(true, "test 34 open");
980 ws.close();
981 };
983 ws.onclose = function(e)
984 {
985 ok(true, "test 34 close");
986 ok(e.wasClean, "test 34 closed cleanly");
987 ok(e.code == 1001, "test 34 custom server code");
988 ok(e.reason == "going away now", "test 34 custom server reason");
989 doTest(35);
990 };
991 }
993 function test35()
994 {
995 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-35a");
997 ws.onopen = function(e)
998 {
999 ok(true, "test 35a open");
1000 ws.close(3500, "my code");
1001 };
1003 ws.onclose = function(e)
1004 {
1005 ok(true, "test 35a close");
1006 ok(e.wasClean, "test 35a closed cleanly");
1007 current_test--; // CreateTestWS for 35a incremented this
1008 var wsb = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-35b");
1010 wsb.onopen = function(e)
1011 {
1012 ok(true, "test 35b open");
1013 wsb.close();
1014 };
1016 wsb.onclose = function(e)
1017 {
1018 ok(true, "test 35b close");
1019 ok(e.wasClean, "test 35b closed cleanly");
1020 ok(e.code == 3501, "test 35 custom server code");
1021 ok(e.reason == "my code", "test 35 custom server reason");
1022 doTest(36);
1023 };
1024 }
1025 }
1027 function test36()
1028 {
1029 var prots=["test-36"];
1031 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
1032 ws.onopen = function(e)
1033 {
1034 ok(true, "test 36 open");
1036 try {
1037 ws.close(13200);
1038 ok(false, "testing custom close code out of range");
1039 }
1040 catch (e) {
1041 ok(true, "testing custom close code out of range");
1042 ws.close(3200);
1043 }
1044 };
1046 ws.onclose = function(e)
1047 {
1048 ok(true, "test 36 close");
1049 ok(e.wasClean, "test 36 closed cleanly");
1050 doTest(37);
1051 };
1052 }
1054 function test37()
1055 {
1056 var prots=["test-37"];
1058 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
1059 ws.onopen = function(e)
1060 {
1061 ok(true, "test 37 open");
1063 try {
1064 ws.close(3100,"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
1065 ok(false, "testing custom close reason out of range");
1066 }
1067 catch (e) {
1068 ok(true, "testing custom close reason out of range");
1069 ws.close(3100,"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012");
1070 }
1071 };
1073 ws.onclose = function(e)
1074 {
1075 ok(true, "test 37 close");
1076 ok(e.wasClean, "test 37 closed cleanly");
1078 current_test--; // CreateTestWS for 37 incremented this
1079 var wsb = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-37b");
1081 wsb.onopen = function(e)
1082 {
1083 // now test that a rejected close code and reason dont persist
1084 ok(true, "test 37b open");
1085 try {
1086 wsb.close(3101,"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
1087 ok(false, "testing custom close reason out of range 37b");
1088 }
1089 catch (e) {
1090 ok(true, "testing custom close reason out of range 37b");
1091 wsb.close();
1092 }
1093 }
1095 wsb.onclose = function(e)
1096 {
1097 ok(true, "test 37b close");
1098 ok(e.wasClean, "test 37b closed cleanly");
1100 current_test--; // CreateTestWS for 37 incremented this
1101 var wsc = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-37c");
1103 wsc.onopen = function(e)
1104 {
1105 ok(true, "test 37c open");
1106 wsc.close();
1107 }
1109 wsc.onclose = function(e)
1110 {
1111 ok(e.code != 3101, "test 37c custom server code not present");
1112 ok(e.reason == "", "test 37c custom server reason not present");
1113 doTest(38);
1114 }
1115 }
1116 }
1117 }
1119 function test38()
1120 {
1121 var prots=["test-38"];
1123 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
1124 ws.onopen = function(e)
1125 {
1126 ok(true, "test 38 open");
1127 ok(ws.extensions != undefined, "extensions attribute defined");
1128 // ok(ws.extensions == "deflate-stream", "extensions attribute deflate-stream");
1129 ws.close();
1130 };
1132 ws.onclose = function(e)
1133 {
1134 ok(true, "test 38 close");
1135 doTest(39);
1136 };
1137 }
1139 function test39()
1140 {
1141 var prots=["test-39"];
1143 var ws = CreateTestWS("wss://example.com/tests/content/base/test/file_websocket", prots);
1144 status_test39 = "started";
1145 ws.onopen = function(e)
1146 {
1147 status_test39 = "opened";
1148 ok(true, "test 39 open");
1149 ws.close();
1150 };
1152 ws.onclose = function(e)
1153 {
1154 ok(true, "test 39 close");
1155 ok(status_test39 == "opened", "test 39 did open");
1156 doTest(40);
1157 };
1158 }
1160 function test40()
1161 {
1162 var prots=["test-40"];
1164 var ws = CreateTestWS("wss://nocert.example.com/tests/content/base/test/file_websocket", prots);
1166 status_test40 = "started";
1167 ws.onerror = ignoreError;
1169 ws.onopen = function(e)
1170 {
1171 status_test40 = "opened";
1172 ok(false, "test 40 open");
1173 ws.close();
1174 };
1176 ws.onclose = function(e)
1177 {
1178 ok(true, "test 40 close");
1179 ok(status_test40 == "started", "test 40 did not open");
1180 doTest(41);
1181 };
1182 }
1184 function test41()
1185 {
1186 var ws = CreateTestWS("ws://example.com/tests/content/base/test/file_websocket", "test-41a", 1);
1188 ws.onopen = function(e)
1189 {
1190 ok(true, "test 41a open");
1191 ok(ws.url == "ws://example.com/tests/content/base/test/file_websocket",
1192 "test 41a initial ws should not be redirected");
1193 ws.close();
1194 };
1196 ws.onclose = function(e)
1197 {
1198 ok(true, "test 41a close");
1200 // establish a hsts policy for example.com
1201 var wsb = CreateTestWS("wss://example.com/tests/content/base/test/file_websocket", "test-41b", 1);
1202 wsb.onopen = function(e)
1203 {
1204 ok(true, "test 41b open");
1205 wsb.close();
1206 }
1208 wsb.onclose = function(e)
1209 {
1210 ok(true, "test 41b close");
1212 // try ws:// again, it should be done over wss:// now due to hsts
1213 var wsc = CreateTestWS("ws://example.com/tests/content/base/test/file_websocket", "test-41c");
1215 wsc.onopen = function(e)
1216 {
1217 ok(true, "test 41c open");
1218 ok(wsc.url == "wss://example.com/tests/content/base/test/file_websocket",
1219 "test 41c ws should be redirected by hsts to wss");
1220 wsc.close();
1221 }
1223 wsc.onclose = function(e)
1224 {
1225 ok(true, "test 41c close");
1227 // clean up the STS state
1228 const Cc = SpecialPowers.Cc;
1229 const Ci = SpecialPowers.Ci;
1230 var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
1231 var thehost = ios.newURI("http://example.com", null, null);
1232 var sss = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService);
1233 var loadContext = SpecialPowers.wrap(window)
1234 .QueryInterface(Ci.nsIInterfaceRequestor)
1235 .getInterface(Ci.nsIWebNavigation)
1236 .QueryInterface(Ci.nsILoadContext);
1237 var flags = 0;
1238 if (loadContext.usePrivateBrowsing)
1239 flags |= Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
1240 sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, thehost, flags);
1241 doTest(42);
1242 }
1243 }
1244 }
1245 }
1247 function test42()
1248 {
1249 // test some utf-8 non-characters. They should be allowed in the
1250 // websockets context. Test via round trip echo.
1251 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-42");
1252 var data = ["U+FFFE \ufffe",
1253 "U+FFFF \uffff",
1254 "U+10FFFF \udbff\udfff"];
1255 var index = 0;
1257 ws.onopen = function()
1258 {
1259 ws.send(data[0]);
1260 ws.send(data[1]);
1261 ws.send(data[2]);
1262 }
1264 ws.onmessage = function(e)
1265 {
1266 ok(e.data == data[index], "bad received message in test-42! index="+index);
1267 index++;
1268 if (index == 3)
1269 ws.close();
1270 }
1272 ws.onclose = function(e)
1273 {
1274 doTest(43);
1275 }
1276 }
1278 function test43()
1279 {
1280 var prots=["test-43"];
1282 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", prots);
1283 ws.onopen = function(e)
1284 {
1285 ok(true, "test 43 open");
1286 // Test binaryType setting
1287 ws.binaryType = "arraybuffer";
1288 ws.binaryType = "blob";
1289 ws.binaryType = ""; // illegal
1290 is(ws.binaryType, "blob");
1291 ws.binaryType = "ArrayBuffer"; // illegal
1292 is(ws.binaryType, "blob");
1293 ws.binaryType = "Blob"; // illegal
1294 is(ws.binaryType, "blob");
1295 ws.binaryType = "mcfoofluu"; // illegal
1296 is(ws.binaryType, "blob");
1297 ws.close();
1298 };
1300 ws.onclose = function(e)
1301 {
1302 ok(true, "test 43 close");
1303 doTest(44);
1304 };
1305 }
1308 function test44()
1309 {
1310 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-44");
1311 ok(ws.readyState == 0, "bad readyState in test-44!");
1312 ws.binaryType = "arraybuffer";
1313 ws.onopen = function()
1314 {
1315 ok(ws.readyState == 1, "open bad readyState in test-44!");
1316 var buf = new ArrayBuffer(3);
1317 // create byte view
1318 var view = new Uint8Array(buf);
1319 view[0] = 5;
1320 view[1] = 0; // null byte
1321 view[2] = 7;
1322 ws.send(buf);
1323 }
1324 ws.onmessage = function(e)
1325 {
1326 ok(e.data instanceof ArrayBuffer, "Should receive an arraybuffer!");
1327 var view = new Uint8Array(e.data);
1328 ok(view.length == 2 && view[0] == 0 && view[1] ==4, "testing Reply arraybuffer" );
1329 ws.close();
1330 }
1331 ws.onclose = function(e)
1332 {
1333 ok(ws.readyState == 3, "onclose bad readyState in test-44!");
1334 shouldCloseCleanly(e);
1335 doTest(45);
1336 }
1337 }
1339 function createDOMFile(fileName, fileData)
1340 {
1341 // create File in profile dir
1342 var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
1343 .getService(SpecialPowers.Ci.nsIProperties);
1344 var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
1345 testFile.append(fileName);
1346 var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]
1347 .createInstance(SpecialPowers.Ci.nsIFileOutputStream);
1348 outStream.init(testFile, 0x02 | 0x08 | 0x20, 0666, 0);
1349 outStream.write(fileData, fileData.length);
1350 outStream.close();
1352 // Set filename into DOM <input> field, as if selected by user
1353 var fileList = document.getElementById('fileList');
1354 SpecialPowers.wrap(fileList).value = testFile.path;
1356 // return JS File object, aka Blob
1357 return fileList.files[0];
1358 }
1360 function test45()
1361 {
1362 var blobFile = createDOMFile("testBlobFile", "flob");
1364 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-45");
1365 ok(ws.readyState == 0, "bad readyState in test-45!");
1367 // ws.binaryType = "blob"; // Don't need to specify: blob is the default
1369 ws.onopen = function()
1370 {
1371 ok(ws.readyState == 1, "open bad readyState in test-45!");
1372 ws.send(blobFile);
1373 }
1375 var test45blob;
1377 ws.onmessage = function(e)
1378 {
1379 test45blob = e.data;
1380 ok(test45blob instanceof Blob, "We should be receiving a Blob");
1382 ws.close();
1383 }
1385 ws.onclose = function(e)
1386 {
1387 ok(ws.readyState == 3, "onclose bad readyState in test-45!");
1388 shouldCloseCleanly(e);
1390 // check blob contents
1391 var reader = new FileReader();
1392 reader.onload = function(event)
1393 {
1394 ok(reader.result == "flob", "response should be 'flob': got '"
1395 + reader.result + "'");
1396 };
1397 reader.onerror = function(event)
1398 {
1399 testFailed("Failed to read blob: error code = " + reader.error.code);
1400 };
1401 reader.onloadend = function(event)
1402 {
1403 doTest(46);
1404 };
1406 reader.readAsBinaryString(test45blob);
1407 }
1408 }
1410 function test46()
1411 {
1412 var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-46");
1413 ok(ws.readyState == 0, "create bad readyState in test-46!");
1414 ws.onopen = function()
1415 {
1416 ok(ws.readyState == 1, "open bad readyState in test-46!");
1417 ws.close()
1418 ok(ws.readyState == 2, "close must set readyState to 2 in test-46!");
1419 }
1420 ws.onmessage = function(e)
1421 {
1422 ok(false, "received message after calling close in test-46!");
1423 }
1424 ws.onclose = function(e)
1425 {
1426 ok(ws.readyState == 3, "onclose bad readyState in test-46!");
1427 shouldCloseCleanly(e);
1428 doTest(47);
1429 }
1430 }
1432 function test47()
1433 {
1434 var hasError = false;
1435 var ws = CreateTestWS("ws://another.websocket.server.that.probably.does.not.exist");
1436 ws.onopen = shouldNotOpen;
1438 ws.onerror = function (e)
1439 {
1440 ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onerror: got "
1441 + ws.readyState);
1442 ok(!ws._withinClose, "onerror() called during close()!");
1443 hasError = true;
1444 }
1446 ws.onclose = function(e)
1447 {
1448 shouldCloseNotCleanly(e);
1449 ok(hasError, "test-47: should have called onerror before onclose");
1450 ok(ws.readyState == 3, "test-47: readyState should be CLOSED(3) in onclose: got "
1451 + ws.readyState);
1452 ok(!ws._withinClose, "onclose() called during close()!");
1453 ok(e.code == 1006, "test-47 close code should be 1006 but is:" + e.code);
1454 doTest(48);
1455 };
1457 // Call close before we're connected: throws error
1458 // Make sure we call onerror/onclose asynchronously
1459 ws._withinClose = 1;
1460 ws.close(3333, "Closed before we were open: error");
1461 ws._withinClose = 0;
1462 ok(ws.readyState == 2, "test-47: readyState should be CLOSING(2) after close(): got "
1463 + ws.readyState);
1464 }
1467 var ranAllTests = false;
1469 function maybeFinished()
1470 {
1471 if (!ranAllTests)
1472 return;
1474 if (waitTest2Part1 || waitTest2Part2 || waitTest9 || waitTest10 ||
1475 waitTest17 || waitTest20 || waitTest21 || waitTest22)
1476 return;
1478 for (i = 0; i < all_ws.length; ++i) {
1479 if (all_ws[i] != shouldNotReceiveCloseEvent &&
1480 !all_ws[i]._receivedCloseEvent) {
1481 ok(false, "didn't called close on test " + all_ws[i]._testNumber + "!");
1482 }
1483 }
1485 if (testsuite_iteration++ < testsuite_iterations) {
1486 // play it again, Sam...
1487 ok(1, "starting testsuite iteration " + testsuite_iteration);
1488 test_started = new Array(last_test);
1489 doTest(current_test = first_test);
1490 } else {
1491 // all done
1492 SimpleTest.finish();
1493 }
1494 }
1496 function testWebSocket ()
1497 {
1498 doTest(first_test);
1499 }
1501 SimpleTest.waitForExplicitFinish();
1503 </script>
1504 </pre>
1506 <div id="feedback">
1507 </div>
1509 </body>
1510 </html>