content/base/test/test_websocket.html

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     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)
  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)
  1012     ok(true, "test 35b open");
  1013     wsb.close();
  1014   };
  1016   wsb.onclose = function(e)
  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   };
  1027 function test36()
  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)
  1034     ok(true, "test 36 open");
  1036     try {
  1037       ws.close(13200);
  1038       ok(false, "testing custom close code out of range");
  1040      catch (e) {
  1041        ok(true, "testing custom close code out of range");
  1042        ws.close(3200);
  1044   };
  1046   ws.onclose = function(e)
  1048     ok(true, "test 36 close");
  1049     ok(e.wasClean, "test 36 closed cleanly");
  1050     doTest(37);
  1051   };
  1054 function test37()
  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)
  1061     ok(true, "test 37 open");
  1063     try {
  1064 	ws.close(3100,"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
  1065       ok(false, "testing custom close reason out of range");
  1067      catch (e) {
  1068        ok(true, "testing custom close reason out of range");
  1069        ws.close(3100,"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012");
  1071   };
  1073   ws.onclose = function(e)
  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)
  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");
  1089       catch (e) {
  1090         ok(true, "testing custom close reason out of range 37b");
  1091         wsb.close();
  1095     wsb.onclose = function(e)
  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)
  1105         ok(true, "test 37c open");
  1106         wsc.close();
  1109       wsc.onclose = function(e)
  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);  
  1119 function test38()
  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)
  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)
  1134     ok(true, "test 38 close");
  1135     doTest(39);
  1136   };
  1139 function test39()
  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)
  1147     status_test39 = "opened";
  1148     ok(true, "test 39 open");
  1149     ws.close();
  1150   };
  1152   ws.onclose = function(e)
  1154     ok(true, "test 39 close");
  1155     ok(status_test39 == "opened", "test 39 did open"); 
  1156     doTest(40);
  1157   };
  1160 function test40()
  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)
  1171     status_test40 = "opened";
  1172     ok(false, "test 40 open");
  1173     ws.close();
  1174   };
  1176   ws.onclose = function(e)
  1178     ok(true, "test 40 close");
  1179     ok(status_test40 == "started", "test 40 did not open"); 
  1180     doTest(41);
  1181   };
  1184 function test41()
  1186   var ws = CreateTestWS("ws://example.com/tests/content/base/test/file_websocket", "test-41a", 1);
  1188   ws.onopen = function(e)
  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)
  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)
  1204       ok(true, "test 41b open");
  1205       wsb.close();
  1208     wsb.onclose = function(e)
  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)
  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();
  1223       wsc.onclose = function(e)
  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);
  1247 function test42()
  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()
  1259     ws.send(data[0]);
  1260     ws.send(data[1]);
  1261     ws.send(data[2]);
  1264   ws.onmessage = function(e)
  1266     ok(e.data == data[index], "bad received message in test-42! index="+index);
  1267     index++;
  1268     if (index == 3)
  1269       ws.close();
  1272   ws.onclose = function(e)
  1274     doTest(43);
  1278 function test43()
  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)
  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)
  1302     ok(true, "test 43 close");
  1303     doTest(44);
  1304   };
  1308 function test44()
  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()
  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);
  1324   ws.onmessage = function(e)
  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();
  1331   ws.onclose = function(e)
  1333     ok(ws.readyState == 3, "onclose bad readyState in test-44!");
  1334     shouldCloseCleanly(e);
  1335     doTest(45);
  1339 function createDOMFile(fileName, fileData)
  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];
  1360 function test45()
  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()
  1371     ok(ws.readyState == 1, "open bad readyState in test-45!");
  1372     ws.send(blobFile);
  1375   var test45blob;
  1377   ws.onmessage = function(e)
  1379     test45blob = e.data;
  1380     ok(test45blob instanceof Blob, "We should be receiving a Blob");
  1382     ws.close();
  1385   ws.onclose = function(e)
  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)
  1394       ok(reader.result == "flob", "response should be 'flob': got '" 
  1395          + reader.result + "'");
  1396     };
  1397     reader.onerror = function(event)
  1399       testFailed("Failed to read blob: error code = " + reader.error.code);
  1400     };
  1401     reader.onloadend = function(event)
  1403       doTest(46);
  1404     };
  1406     reader.readAsBinaryString(test45blob);
  1410 function test46()
  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()
  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!");
  1420   ws.onmessage = function(e)
  1422     ok(false, "received message after calling close in test-46!");
  1424   ws.onclose = function(e)
  1426     ok(ws.readyState == 3, "onclose bad readyState in test-46!");
  1427     shouldCloseCleanly(e);
  1428     doTest(47);
  1432 function test47()
  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)
  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;
  1446   ws.onclose = function(e)
  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);
  1467 var ranAllTests = false;
  1469 function maybeFinished()
  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 + "!");
  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();
  1496 function testWebSocket ()
  1498   doTest(first_test);
  1501 SimpleTest.waitForExplicitFinish();
  1503 </script>
  1504 </pre>
  1506 <div id="feedback">
  1507 </div>
  1509 </body>
  1510 </html>

mercurial