summaryrefslogtreecommitdiffstats
path: root/dom/websocket/tests/websocket_tests.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /dom/websocket/tests/websocket_tests.js
parentInitial commit. (diff)
downloadfirefox-upstream/124.0.1.tar.xz
firefox-upstream/124.0.1.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--dom/websocket/tests/websocket_tests.js1488
1 files changed, 1488 insertions, 0 deletions
diff --git a/dom/websocket/tests/websocket_tests.js b/dom/websocket/tests/websocket_tests.js
new file mode 100644
index 0000000000..188daac2f9
--- /dev/null
+++ b/dom/websocket/tests/websocket_tests.js
@@ -0,0 +1,1488 @@
+// test1: client tries to connect to a http scheme location;
+function test1() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "http://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-1"
+ );
+
+ ws.onmessage = function () {
+ ok(true, "created websocket with http scheme");
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test2: assure serialization of the connections;
+// this test expects that the serialization list to connect to the proxy
+// is empty.
+function test2() {
+ return new Promise(function (resolve, reject) {
+ var waitTest2Part1 = true;
+ var waitTest2Part2 = true;
+
+ var ws1 = CreateTestWS(
+ "ws://sub2.test2.example.com/tests/dom/websocket/tests/file_websocket",
+ "test-2.1"
+ );
+ var ws2 = CreateTestWS(
+ "ws://sub2.test2.example.com/tests/dom/websocket/tests/file_websocket",
+ "test-2.2"
+ );
+
+ var ws2CanConnect = false;
+
+ function maybeFinished() {
+ if (!waitTest2Part1 && !waitTest2Part2) {
+ resolve();
+ }
+ }
+
+ ws1.onopen = function () {
+ ok(true, "ws1 open in test 2");
+ ws2CanConnect = true;
+ ws1.close();
+ };
+
+ ws1.onclose = function (e) {
+ waitTest2Part1 = false;
+ maybeFinished();
+ };
+
+ ws2.onopen = function () {
+ ok(ws2CanConnect, "shouldn't connect yet in test-2!");
+ ws2.close();
+ };
+
+ ws2.onclose = function (e) {
+ waitTest2Part2 = false;
+ maybeFinished();
+ };
+ });
+}
+
+// test3: client tries to connect to an non-existent ws server;
+function test3() {
+ return new Promise(function (resolve, reject) {
+ var hasError = false;
+ var ws = CreateTestWS("ws://this.websocket.server.probably.does.not.exist");
+
+ ws.onopen = shouldNotOpen;
+
+ ws.onerror = function (e) {
+ hasError = true;
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ ok(hasError, "rcvd onerror event");
+ is(e.code, 1006, "test-3 close code should be 1006 but is:" + e.code);
+ resolve();
+ };
+ });
+}
+
+// test4: client tries to connect using a relative url;
+function test4() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS("file_websocket", "test-4");
+
+ ws.onmessage = function () {
+ ok(true, "created websocket with relative scheme");
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test5: client uses an invalid protocol value;
+function test5() {
+ return new Promise(function (resolve, reject) {
+ try {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ ""
+ );
+ ok(false, "couldn't accept an empty string in the protocol parameter");
+ } catch (e) {
+ ok(true, "couldn't accept an empty string in the protocol parameter");
+ }
+
+ try {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "\n"
+ );
+ ok(
+ false,
+ "couldn't accept any not printable ASCII character in the protocol parameter"
+ );
+ } catch (e) {
+ ok(
+ true,
+ "couldn't accept any not printable ASCII character in the protocol parameter"
+ );
+ }
+
+ try {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test 5"
+ );
+ ok(false, "U+0020 not acceptable in protocol parameter");
+ } catch (e) {
+ ok(true, "U+0020 not acceptable in protocol parameter");
+ }
+
+ resolve();
+ });
+}
+
+// test6: counter and encoding check;
+function test6() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-6"
+ );
+ var counter = 1;
+
+ ws.onopen = function () {
+ ws.send(counter);
+ };
+
+ ws.onmessage = function (e) {
+ if (counter == 5) {
+ is(e.data, "あいうえお", "test-6 counter 5 data ok");
+ ws.close();
+ } else {
+ is(parseInt(e.data), counter + 1, "bad counter");
+ counter += 2;
+ ws.send(counter);
+ }
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test7: onmessage event origin property check
+function test7() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://sub2.test2.example.org/tests/dom/websocket/tests/file_websocket",
+ "test-7"
+ );
+ var gotmsg = false;
+
+ ws.onopen = function () {
+ ok(true, "test 7 open");
+ };
+
+ ws.onmessage = function (e) {
+ ok(true, "test 7 message");
+ is(
+ e.origin,
+ "ws://sub2.test2.example.org",
+ "onmessage origin set to ws:// host"
+ );
+ gotmsg = true;
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(gotmsg, "recvd message in test 7 before close");
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test8: client calls close() and the server sends the close frame (with no
+// code or reason) in acknowledgement;
+function test8() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-8"
+ );
+
+ ws.onopen = function () {
+ is(ws.protocol, "test-8", "test-8 subprotocol selection");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ // We called close() with no close code: so pywebsocket will also send no
+ // close code, which translates to code 1005
+ is(e.code, 1005, "test-8 close code has wrong value:" + e.code);
+ is(e.reason, "", "test-8 close reason has wrong value:" + e.reason);
+ resolve();
+ };
+ });
+}
+
+// test9: client closes the connection before the ws connection is established;
+function test9() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://test2.example.org/tests/dom/websocket/tests/file_websocket",
+ "test-9"
+ );
+
+ ws._receivedErrorEvent = false;
+
+ ws.onopen = shouldNotOpen;
+
+ ws.onerror = function (e) {
+ ws._receivedErrorEvent = true;
+ };
+
+ ws.onclose = function (e) {
+ ok(ws._receivedErrorEvent, "Didn't received the error event in test 9.");
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+
+ ws.close();
+ });
+}
+
+// test10: client sends a message before the ws connection is established;
+function test10() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://sub1.test1.example.com/tests/dom/websocket/tests/file_websocket",
+ "test-10"
+ );
+
+ ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ resolve();
+ };
+
+ try {
+ ws.send("client data");
+ ok(false, "Couldn't send data before connecting!");
+ } catch (e) {
+ ok(true, "Couldn't send data before connecting!");
+ }
+
+ ws.onopen = function () {
+ ok(true, "test 10 opened");
+ ws.close();
+ };
+ });
+}
+
+// test11: a simple hello echo;
+function test11() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-11"
+ );
+ is(ws.readyState, 0, "create bad readyState in test-11!");
+
+ ws.onopen = function () {
+ is(ws.readyState, 1, "open bad readyState in test-11!");
+ ws.send("client data");
+ };
+
+ ws.onmessage = function (e) {
+ is(e.data, "server data", "bad received message in test-11!");
+ ws.close(1000, "Have a nice day");
+
+ // this ok() is disabled due to a race condition - it state may have
+ // advanced through 2 (closing) and into 3 (closed) before it is evald
+ // ok(ws.readyState == 2, "onmessage bad readyState in test-11!");
+ };
+
+ ws.onclose = function (e) {
+ is(ws.readyState, 3, "onclose bad readyState in test-11!");
+ shouldCloseCleanly(e);
+ is(e.code, 1000, "test 11 got wrong close code: " + e.code);
+ is(
+ e.reason,
+ "Have a nice day",
+ "test 11 got wrong close reason: " + e.reason
+ );
+ resolve();
+ };
+ });
+}
+
+// test12: client sends a message containing unpaired surrogates
+function test12() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-12"
+ );
+
+ ws.onopen = function () {
+ try {
+ // send an unpaired surrogate
+ ws._gotMessage = false;
+ ws.send("a\ud800b");
+ ok(true, "ok to send an unpaired surrogate");
+ } catch (e) {
+ ok(
+ false,
+ "shouldn't fail any more when sending an unpaired surrogate!"
+ );
+ }
+ };
+
+ ws.onmessage = function (msg) {
+ is(
+ msg.data,
+ "SUCCESS",
+ "Unpaired surrogate in UTF-16 not converted in test-12"
+ );
+ ws._gotMessage = true;
+ // Must support unpaired surrogates in close reason, too
+ ws.close(1000, "a\ud800b");
+ };
+
+ ws.onclose = function (e) {
+ is(ws.readyState, 3, "onclose bad readyState in test-12!");
+ ok(ws._gotMessage, "didn't receive message!");
+ shouldCloseCleanly(e);
+ is(e.code, 1000, "test 12 got wrong close code: " + e.code);
+ is(
+ e.reason,
+ "a\ufffdb",
+ "test 11 didn't get replacement char in close reason: " + e.reason
+ );
+ resolve();
+ };
+ });
+}
+
+// test13: server sends an invalid message;
+function test13() {
+ return new Promise(function (resolve, reject) {
+ // previous versions of this test counted the number of protocol errors
+ // returned, but the protocol stack typically closes down after reporting a
+ // protocol level error - trying to resync is too dangerous
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-13"
+ );
+ ws._timesCalledOnError = 0;
+
+ ws.onerror = function () {
+ ws._timesCalledOnError++;
+ };
+
+ ws.onclose = function (e) {
+ ok(ws._timesCalledOnError > 0, "no error events");
+ resolve();
+ };
+ });
+}
+
+// test14: server sends the close frame, it doesn't close the tcp connection
+// and it keeps sending normal ws messages;
+function test14() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-14"
+ );
+
+ ws.onmessage = function () {
+ ok(
+ false,
+ "shouldn't received message after the server sent the close frame"
+ );
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test15: server closes the tcp connection, but it doesn't send the close
+// frame;
+function test15() {
+ return new Promise(function (resolve, reject) {
+ /*
+ * DISABLED: see comments for test-15 case in file_websocket_wsh.py
+ */
+ resolve();
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-15"
+ );
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+
+ // termination of the connection might cause an error event if it happens in OPEN
+ ws.onerror = function () {};
+ });
+}
+
+// test16: client calls close() and tries to send a message;
+function test16() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-16"
+ );
+
+ ws.onopen = function () {
+ ws.close();
+ ok(
+ !ws.send("client data"),
+ "shouldn't send message after calling close()"
+ );
+ };
+
+ ws.onmessage = function () {
+ ok(false, "shouldn't send message after calling close()");
+ };
+
+ ws.onerror = function () {};
+
+ ws.onclose = function () {
+ resolve();
+ };
+ });
+}
+
+// test17: see bug 572975 - all event listeners set
+function test17() {
+ return new Promise(function (resolve, reject) {
+ var status_test17 = "not started";
+
+ var test17func = function () {
+ var local_ws = new WebSocket(
+ "ws://sub1.test2.example.org/tests/dom/websocket/tests/file_websocket",
+ "test-17"
+ );
+ status_test17 = "started";
+
+ local_ws.onopen = function (e) {
+ status_test17 = "opened";
+ e.target.send("client data");
+ forcegc();
+ };
+
+ local_ws.onerror = function () {
+ ok(false, "onerror called on test " + current_test + "!");
+ };
+
+ local_ws.onmessage = function (e) {
+ ok(e.data == "server data", "Bad message in test-17");
+ status_test17 = "got message";
+ forcegc();
+ };
+
+ local_ws.onclose = function (e) {
+ ok(status_test17 == "got message", "Didn't got message in test-17!");
+ shouldCloseCleanly(e);
+ status_test17 = "closed";
+ forcegc();
+ resolve();
+ };
+
+ window._test17 = null;
+ forcegc();
+ };
+
+ window._test17 = test17func;
+ window._test17();
+ });
+}
+
+// The tests that expects that their websockets neither open nor close MUST
+// be in the end of the tests, i.e. HERE, in order to prevent blocking the other
+// tests.
+
+// test18: client tries to connect to an http resource;
+function test18() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_http_resource.txt"
+ );
+ ws.onopen = shouldNotOpen;
+ ws.onerror = ignoreError;
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test19: server closes the tcp connection before establishing the ws
+// connection;
+function test19() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-19"
+ );
+ ws.onopen = shouldNotOpen;
+ ws.onerror = ignoreError;
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test20: see bug 572975 - only on error and onclose event listeners set
+function test20() {
+ return new Promise(function (resolve, reject) {
+ var test20func = function () {
+ var local_ws = new WebSocket(
+ "ws://sub1.test1.example.org/tests/dom/websocket/tests/file_websocket",
+ "test-20"
+ );
+
+ local_ws.onerror = function () {
+ ok(false, "onerror called on test " + current_test + "!");
+ };
+
+ local_ws.onclose = function (e) {
+ ok(true, "test 20 closed despite gc");
+ resolve();
+ };
+
+ local_ws = null;
+ window._test20 = null;
+ forcegc();
+ };
+
+ window._test20 = test20func;
+ window._test20();
+ });
+}
+
+// test21: see bug 572975 - same as test 17, but delete strong event listeners
+// when receiving the message event;
+function test21() {
+ return new Promise(function (resolve, reject) {
+ var test21func = function () {
+ var local_ws = new WebSocket(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-21"
+ );
+ var received_message = false;
+
+ local_ws.onopen = function (e) {
+ e.target.send("client data");
+ forcegc();
+ e.target.onopen = null;
+ forcegc();
+ };
+
+ local_ws.onerror = function () {
+ ok(false, "onerror called on test " + current_test + "!");
+ };
+
+ local_ws.onmessage = function (e) {
+ is(e.data, "server data", "Bad message in test-21");
+ received_message = true;
+ forcegc();
+ e.target.onmessage = null;
+ forcegc();
+ };
+
+ local_ws.onclose = function (e) {
+ shouldCloseCleanly(e);
+ ok(received_message, "close transitioned through onmessage");
+ resolve();
+ };
+
+ local_ws = null;
+ window._test21 = null;
+ forcegc();
+ };
+
+ window._test21 = test21func;
+ window._test21();
+ });
+}
+
+// test22: server takes too long to establish the ws connection;
+function test22() {
+ return new Promise(function (resolve, reject) {
+ const pref_open = "network.websocket.timeout.open";
+ SpecialPowers.setIntPref(pref_open, 5);
+
+ var ws = CreateTestWS(
+ "ws://sub2.test2.example.org/tests/dom/websocket/tests/file_websocket",
+ "test-22"
+ );
+
+ ws.onopen = shouldNotOpen;
+ ws.onerror = ignoreError;
+
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+
+ SpecialPowers.clearUserPref(pref_open);
+ });
+}
+
+// test23: should detect WebSocket on window object;
+function test23() {
+ return new Promise(function (resolve, reject) {
+ ok("WebSocket" in window, "WebSocket should be available on window object");
+ resolve();
+ });
+}
+
+// test24: server rejects sub-protocol string
+function test24() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-does-not-exist"
+ );
+
+ ws.onopen = shouldNotOpen;
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+
+ ws.onerror = function () {};
+ });
+}
+
+// test25: ctor with valid empty sub-protocol array
+function test25() {
+ return new Promise(function (resolve, reject) {
+ var prots = [];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ // This test errors because the server requires a sub-protocol, but
+ // the test just wants to ensure that the ctor doesn't generate an
+ // exception
+ ws.onerror = ignoreError;
+ ws.onopen = shouldNotOpen;
+
+ ws.onclose = function (e) {
+ is(ws.protocol, "", "test25 subprotocol selection");
+ ok(true, "test 25 protocol array close");
+ resolve();
+ };
+ });
+}
+
+// test26: ctor with invalid sub-protocol array containing 1 empty element
+function test26() {
+ return new Promise(function (resolve, reject) {
+ var prots = [""];
+
+ try {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+ ok(false, "testing empty element sub protocol array");
+ } catch (e) {
+ ok(true, "testing empty sub element protocol array");
+ }
+
+ resolve();
+ });
+}
+
+// test27: ctor with invalid sub-protocol array containing an empty element in
+// list
+function test27() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test27", ""];
+
+ try {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+ ok(false, "testing empty element mixed sub protocol array");
+ } catch (e) {
+ ok(true, "testing empty element mixed sub protocol array");
+ }
+
+ resolve();
+ });
+}
+
+// test28: ctor using valid 1 element sub-protocol array
+function test28() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test28"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 28 protocol array open");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ is(ws.protocol, "test28", "test28 subprotocol selection");
+ ok(true, "test 28 protocol array close");
+ resolve();
+ };
+ });
+}
+
+// test29: ctor using all valid 5 element sub-protocol array
+function test29() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test29a", "test29b"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 29 protocol array open");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 29 protocol array close");
+ resolve();
+ };
+ });
+}
+
+// test30: ctor using valid 1 element sub-protocol array with element server
+// will reject
+function test30() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-does-not-exist"];
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = shouldNotOpen;
+
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ resolve();
+ };
+
+ ws.onerror = function () {};
+ });
+}
+
+// test31: ctor using valid 2 element sub-protocol array with 1 element server
+// will reject and one server will accept
+function test31() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-does-not-exist", "test31"];
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 31 protocol array open");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ is(ws.protocol, "test31", "test31 subprotocol selection");
+ ok(true, "test 31 protocol array close");
+ resolve();
+ };
+ });
+}
+
+// test32: ctor using invalid sub-protocol array that contains duplicate items
+function test32() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test32", "test32"];
+
+ try {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+ ok(false, "testing duplicated element sub protocol array");
+ } catch (e) {
+ ok(true, "testing duplicated sub element protocol array");
+ }
+
+ resolve();
+ });
+}
+
+// test33: test for sending/receiving custom close code (but no close reason)
+function test33() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test33"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 33 open");
+ ws.close(3131); // pass code but not reason
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 33 close");
+ shouldCloseCleanly(e);
+ is(e.code, 3131, "test 33 got wrong close code: " + e.code);
+ is(e.reason, "", "test 33 got wrong close reason: " + e.reason);
+ resolve();
+ };
+ });
+}
+
+// test34: test for receiving custom close code and reason
+function test34() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-34"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 34 open");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 34 close");
+ ok(e.wasClean, "test 34 closed cleanly");
+ is(e.code, 1001, "test 34 custom server code");
+ is(e.reason, "going away now", "test 34 custom server reason");
+ resolve();
+ };
+ });
+}
+
+// test35: test for sending custom close code and reason
+function test35() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-35a"
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 35a open");
+ ws.close(3500, "my code");
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 35a close");
+ ok(e.wasClean, "test 35a closed cleanly");
+ var wsb = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-35b"
+ );
+
+ wsb.onopen = function (event) {
+ ok(true, "test 35b open");
+ wsb.close();
+ };
+
+ wsb.onclose = function (event) {
+ ok(true, "test 35b close");
+ ok(event.wasClean, "test 35b closed cleanly");
+ is(event.code, 3501, "test 35 custom server code");
+ is(event.reason, "my code", "test 35 custom server reason");
+ resolve();
+ };
+ };
+ });
+}
+
+// test36: negative test for sending out of range close code
+function test36() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-36"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 36 open");
+
+ try {
+ ws.close(13200);
+ ok(false, "testing custom close code out of range");
+ } catch (ex) {
+ ok(true, "testing custom close code out of range");
+ ws.close(3200);
+ }
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 36 close");
+ ok(e.wasClean, "test 36 closed cleanly");
+ resolve();
+ };
+ });
+}
+
+// test37: negative test for too long of a close reason
+function test37() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-37"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 37 open");
+
+ try {
+ ws.close(
+ 3100,
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
+ );
+ ok(false, "testing custom close reason out of range");
+ } catch (ex) {
+ ok(true, "testing custom close reason out of range");
+ ws.close(
+ 3100,
+ "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012"
+ );
+ }
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 37 close");
+ ok(e.wasClean, "test 37 closed cleanly");
+
+ var wsb = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-37b"
+ );
+
+ wsb.onopen = function (event) {
+ // now test that a rejected close code and reason dont persist
+ ok(true, "test 37b open");
+ try {
+ wsb.close(
+ 3101,
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
+ );
+ ok(false, "testing custom close reason out of range 37b");
+ } catch (ex) {
+ ok(true, "testing custom close reason out of range 37b");
+ wsb.close();
+ }
+ };
+
+ wsb.onclose = function (event) {
+ ok(true, "test 37b close");
+ ok(event.wasClean, "test 37b closed cleanly");
+
+ var wsc = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-37c"
+ );
+
+ wsc.onopen = function (eventInner) {
+ ok(true, "test 37c open");
+ wsc.close();
+ };
+
+ wsc.onclose = function (eventInner) {
+ isnot(
+ eventInner.code,
+ 3101,
+ "test 37c custom server code not present"
+ );
+ is(
+ eventInner.reason,
+ "",
+ "test 37c custom server reason not present"
+ );
+ resolve();
+ };
+ };
+ };
+ });
+}
+
+// test38: ensure extensions attribute is defined
+function test38() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-38"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 38 open");
+ isnot(ws.extensions, undefined, "extensions attribute defined");
+ // is(ws.extensions, "deflate-stream", "extensions attribute deflate-stream");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 38 close");
+ resolve();
+ };
+ });
+}
+
+// test39: a basic wss:// connectivity test
+function test39() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-39"];
+
+ var ws = CreateTestWS(
+ "wss://example.com/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+ status_test39 = "started";
+
+ ws.onopen = function (e) {
+ status_test39 = "opened";
+ ok(true, "test 39 open");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 39 close");
+ is(status_test39, "opened", "test 39 did open");
+ resolve();
+ };
+ });
+}
+
+// test40: negative test for wss:// with no cert
+function test40() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-40"];
+
+ var ws = CreateTestWS(
+ "wss://nocert.example.com/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ status_test40 = "started";
+ ws.onerror = ignoreError;
+
+ ws.onopen = function (e) {
+ status_test40 = "opened";
+ ok(false, "test 40 open");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 40 close");
+ is(status_test40, "started", "test 40 did not open");
+ resolve();
+ };
+ });
+}
+
+// test41: HSTS
+function test41() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://example.com/tests/dom/websocket/tests/file_websocket",
+ "test-41a",
+ 1
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 41a open");
+ is(
+ ws.url,
+ "ws://example.com/tests/dom/websocket/tests/file_websocket",
+ "test 41a initial ws should not be redirected"
+ );
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 41a close");
+
+ // Since third-party loads can't set HSTS state, this will not set
+ // HSTS for example.com.
+ var wsb = CreateTestWS(
+ "wss://example.com/tests/dom/websocket/tests/file_websocket",
+ "test-41b",
+ 1
+ );
+
+ wsb.onopen = function (event) {
+ ok(true, "test 41b open");
+ wsb.close();
+ };
+
+ wsb.onclose = function (event) {
+ ok(true, "test 41b close");
+
+ // try ws:// again, it should be done over ws:// again
+ var wsc = CreateTestWS(
+ "ws://example.com/tests/dom/websocket/tests/file_websocket",
+ "test-41c"
+ );
+
+ wsc.onopen = function () {
+ ok(true, "test 41c open");
+ is(
+ wsc.url,
+ "ws://example.com/tests/dom/websocket/tests/file_websocket",
+ "test 41c ws should not be redirected by hsts to wss"
+ );
+ wsc.close();
+ };
+
+ wsc.onclose = function () {
+ ok(true, "test 41c close");
+ resolve();
+ };
+ };
+ };
+ });
+}
+
+// test42: non-char utf-8 sequences
+function test42() {
+ return new Promise(function (resolve, reject) {
+ // test some utf-8 non-characters. They should be allowed in the
+ // websockets context. Test via round trip echo.
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-42"
+ );
+ var data = ["U+FFFE \ufffe", "U+FFFF \uffff", "U+10FFFF \udbff\udfff"];
+ var index = 0;
+
+ ws.onopen = function () {
+ ws.send(data[0]);
+ ws.send(data[1]);
+ ws.send(data[2]);
+ };
+
+ ws.onmessage = function (e) {
+ is(
+ e.data,
+ data[index],
+ "bad received message in test-42! index=" + index
+ );
+ index++;
+ if (index == 3) {
+ ws.close();
+ }
+ };
+
+ ws.onclose = function (e) {
+ resolve();
+ };
+ });
+}
+
+// test43: Test setting binaryType attribute
+function test43() {
+ return new Promise(function (resolve, reject) {
+ var prots = ["test-43"];
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ prots
+ );
+
+ ws.onopen = function (e) {
+ ok(true, "test 43 open");
+ // Test binaryType setting
+ ws.binaryType = "arraybuffer";
+ ws.binaryType = "blob";
+ ws.binaryType = ""; // illegal
+ is(ws.binaryType, "blob");
+ ws.binaryType = "ArrayBuffer"; // illegal
+ is(ws.binaryType, "blob");
+ ws.binaryType = "Blob"; // illegal
+ is(ws.binaryType, "blob");
+ ws.binaryType = "mcfoofluu"; // illegal
+ is(ws.binaryType, "blob");
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "test 43 close");
+ resolve();
+ };
+ });
+}
+
+// test44: Test sending/receving binary ArrayBuffer
+function test44() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-44"
+ );
+ is(ws.readyState, 0, "bad readyState in test-44!");
+ ws.binaryType = "arraybuffer";
+
+ ws.onopen = function () {
+ is(ws.readyState, 1, "open bad readyState in test-44!");
+ var buf = new ArrayBuffer(3);
+ // create byte view
+ var view = new Uint8Array(buf);
+ view[0] = 5;
+ view[1] = 0; // null byte
+ view[2] = 7;
+ ws.send(buf);
+ };
+
+ ws.onmessage = function (e) {
+ ok(e.data instanceof ArrayBuffer, "Should receive an arraybuffer!");
+ var view = new Uint8Array(e.data);
+ ok(
+ view.length == 2 && view[0] == 0 && view[1] == 4,
+ "testing Reply arraybuffer"
+ );
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ is(ws.readyState, 3, "onclose bad readyState in test-44!");
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test45: Test sending/receving binary Blob
+function test45() {
+ return new Promise(function (resolve, reject) {
+ function test45Real(blobFile) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-45"
+ );
+ is(ws.readyState, 0, "bad readyState in test-45!");
+ // ws.binaryType = "blob"; // Don't need to specify: blob is the default
+
+ ws.onopen = function () {
+ is(ws.readyState, 1, "open bad readyState in test-45!");
+ ws.send(blobFile);
+ };
+
+ var test45blob;
+
+ ws.onmessage = function (e) {
+ test45blob = e.data;
+ ok(test45blob instanceof Blob, "We should be receiving a Blob");
+
+ ws.close();
+ };
+
+ ws.onclose = function (e) {
+ is(ws.readyState, 3, "onclose bad readyState in test-45!");
+ shouldCloseCleanly(e);
+
+ // check blob contents
+ var reader = new FileReader();
+ reader.onload = function (event) {
+ is(
+ reader.result,
+ "flob",
+ "response should be 'flob': got '" + reader.result + "'"
+ );
+ };
+
+ reader.onerror = function (event) {
+ testFailed("Failed to read blob: error code = " + reader.error.code);
+ };
+
+ reader.onloadend = function (event) {
+ resolve();
+ };
+
+ reader.readAsBinaryString(test45blob);
+ };
+ }
+
+ SpecialPowers.createFiles(
+ [{ name: "testBlobFile", data: "flob" }],
+ function (files) {
+ test45Real(files[0]);
+ },
+ function (msg) {
+ testFailed("Failed to create file for test45: " + msg);
+ resolve();
+ }
+ );
+ });
+}
+
+// test46: Test that we don't dispatch incoming msgs once in CLOSING state
+function test46() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-46"
+ );
+ is(ws.readyState, 0, "create bad readyState in test-46!");
+
+ ws.onopen = function () {
+ is(ws.readyState, 1, "open bad readyState in test-46!");
+ ws.close();
+ is(ws.readyState, 2, "close must set readyState to 2 in test-46!");
+ };
+
+ ws.onmessage = function (e) {
+ ok(false, "received message after calling close in test-46!");
+ };
+
+ ws.onclose = function (e) {
+ is(ws.readyState, 3, "onclose bad readyState in test-46!");
+ shouldCloseCleanly(e);
+ resolve();
+ };
+ });
+}
+
+// test47: Make sure onerror/onclose aren't called during close()
+function test47() {
+ return new Promise(function (resolve, reject) {
+ var hasError = false;
+ var ws = CreateTestWS(
+ "ws://another.websocket.server.that.probably.does.not.exist"
+ );
+
+ ws.onopen = shouldNotOpen;
+
+ ws.onerror = function (e) {
+ is(
+ ws.readyState,
+ 3,
+ "test-47: readyState should be CLOSED(3) in onerror: got " +
+ ws.readyState
+ );
+ ok(!ws._withinClose, "onerror() called during close()!");
+ hasError = true;
+ };
+
+ ws.onclose = function (e) {
+ shouldCloseNotCleanly(e);
+ ok(hasError, "test-47: should have called onerror before onclose");
+ is(
+ ws.readyState,
+ 3,
+ "test-47: readyState should be CLOSED(3) in onclose: got " +
+ ws.readyState
+ );
+ ok(!ws._withinClose, "onclose() called during close()!");
+ is(e.code, 1006, "test-47 close code should be 1006 but is:" + e.code);
+ resolve();
+ };
+
+ // Call close before we're connected: throws error
+ // Make sure we call onerror/onclose asynchronously
+ ws._withinClose = 1;
+ ws.close(3333, "Closed before we were open: error");
+ ws._withinClose = 0;
+ is(
+ ws.readyState,
+ 2,
+ "test-47: readyState should be CLOSING(2) after close(): got " +
+ ws.readyState
+ );
+ });
+}
+
+// test48: see bug 1227136 - client calls close() from onopen() and waits until
+// WebSocketChannel::mSocketIn is nulled out on socket thread.
+function test48() {
+ return new Promise(function (resolve, reject) {
+ const pref_close = "network.websocket.timeout.close";
+ SpecialPowers.setIntPref(pref_close, 1);
+
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-48"
+ );
+
+ ws.onopen = function () {
+ ws.close();
+
+ var date = new Date();
+ var curDate = null;
+ do {
+ curDate = new Date();
+ } while (curDate - date < 1500);
+ };
+
+ ws.onclose = function (e) {
+ ok(true, "ws close in test 48");
+ resolve();
+ };
+
+ SpecialPowers.clearUserPref(pref_close);
+ });
+}
+
+function test49() {
+ return new Promise(function (resolve, reject) {
+ var ws = CreateTestWS(
+ "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+ "test-49"
+ );
+ var gotError = 0;
+ ok(ws.readyState == 0, "create bad readyState in test-49!");
+
+ ws.onopen = function () {
+ ok(false, "Connection must fail in test-49");
+ };
+
+ ws.onerror = function (e) {
+ gotError = 1;
+ };
+
+ ws.onclose = function (e) {
+ ok(gotError, "Should get error in test-49!");
+ resolve();
+ };
+ });
+}