Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Unified Diff: LayoutTests/http/tests/websocket/resources/close-common.js

Issue 913273004: [OBSOLETE] De-flake the websocket/close.html layout test (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Use Promises and improve failure behaviour. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « LayoutTests/http/tests/websocket/close_wsh.py ('k') | LayoutTests/http/tests/websocket/workers/close.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: LayoutTests/http/tests/websocket/resources/close-common.js
diff --git a/LayoutTests/http/tests/websocket/resources/close-common.js b/LayoutTests/http/tests/websocket/resources/close-common.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f7ba6fe7f44417d622b7bf207e93040d0ed2bd7
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/resources/close-common.js
@@ -0,0 +1,259 @@
+// Variables used in js-test.js assertions.
+var exceptionName;
+var exceptionMessage;
+var exceptionProto;
+var closeEvent;
+
+// Constants.
+const invalidAccessErr = "InvalidAccessError";
+const syntaxErr = "SyntaxError";
+const normalClosure = 1000;
+const abnormalClosure = 1006;
+const url = "ws://127.0.0.1:8880/close";
+const ws_handlers = ["onopen", "onerror", "onclose", "onmessage"];
+
+// An explicit timeout is used so that we can capture the test output.
+var timeout;
+
+const badCodesTestCodes = [
+ 999, 1001, 2999, 5000, 65536 + 1000, 0x100000000 + 1000, 2999.9, NaN, "0", "100", 1/0, -1/0, 0/0,
+];
+
+const badReasonTestReasons = [
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234", // 124 Byte
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012\u00a9", // length is 123, but 124 Byte in UTF-8
+];
+
+function createFailHandler(name, ws, reject)
+{
+ return function () {
yhirano 2015/02/27 06:26:44 Please be consistent whether you put a space after
Adam Rice 2015/02/27 09:34:28 Originally this test used function () {...} style,
+ removeAllHandlers(ws);
+ reject(name + " was called.");
+ };
+}
+
+function setDefaultHandlers(ws, reject)
+{
+ ws_handlers.forEach(function (handler) {
+ ws[handler] = createFailHandler(handler, ws, reject);
+ });
+}
+
+// Ensure that the WebSocket can be garbage collected.
+function removeAllHandlers(ws)
+{
+ ws_handlers.forEach(function (handler) {
+ ws[handler] = undefined;
+ });
+}
+
+// Verify that close() throws an exception when an invalid close code is passed.
+function badCodesTest()
+{
+ return new Promise(function (resolve, reject) {
+ debug("badCodesTest: started");
+ var ws = new WebSocket(url);
+ setDefaultHandlers(ws, reject);
+ for (var id = 0; id < badCodesTestCodes.length; ++id) {
yhirano 2015/02/27 06:26:44 [optional] You can use |for (var test_code of badC
Adam Rice 2015/02/27 09:34:28 I didn't know that worked yet. Thanks.
+ var test_code = badCodesTestCodes[id];
+ debug("badCodesTest: " + test_code);
+ try {
+ ws.close(test_code);
+ reject("Exception not thrown for code " + test_code);
+ return;
+ } catch (e) {
+ exceptionName = e.name;
+ exceptionMessage = e.message;
+ exceptionProto = Object.getPrototypeOf(e);
+ shouldBeTrue("exceptionProto === DOMException.prototype");
+ shouldBeEqualToString("exceptionName", invalidAccessErr);
+ var expectedCode = test_code;
+ if (!expectedCode)
+ expectedCode = 0;
+ else if (expectedCode > 65535)
+ expectedCode = 65535;
+ else if (expectedCode < 0)
+ expectedCode = 0;
+ expectedCode = Math.floor(expectedCode);
+ shouldBeEqualToString("exceptionMessage", "Failed to execute 'close' on 'WebSocket': The code must be either 1000, or between 3000 and 4999. " + expectedCode + " is neither.");
+ }
+ }
+ removeAllHandlers(ws);
+ resolve();
+ });
+}
+
+// Verify that passing a valid code does not throw an exception.
+function goodCodeTest()
+{
+ return new Promise(function (resolve, reject) {
+ debug("goodCodeTest: started");
+ var ws = new WebSocket(url);
+ setDefaultHandlers(ws, reject);
+ ws.onclose = function (e)
+ {
+ closeEvent = e;
+ shouldBeEqualToNumber("closeEvent.code", abnormalClosure);
+ resolve();
+ };
+ ws.onerror = function()
+ {
+ testPassed("onerror was called.");
+ };
+ ws.close(1000.0);
+ });
+}
+
+// Verify that unpaired surrogates in the reason string are converted to U+FFFD
+// before sending to the remote server.
+function invalidUnicodeReasonTest()
+{
+ return new Promise(function (resolve, reject) {
+ debug("invalidUnicodeReasonTest: started");
+ var ws = new WebSocket(url);
yhirano 2015/02/27 06:26:44 +setDefaultHandlers
Adam Rice 2015/02/27 09:34:28 Done.
+ ws.onopen = function() {
+ // 0xD834 is an unpaired surrogate.
+ var invalidString = String.fromCharCode(0xD834);
+ ws.close(1000, invalidString);
+ };
+ ws.onclose = function(e) {
+ closeEvent = e;
+ shouldBeTrue("closeEvent.wasClean");
+ shouldBeEqualToString("closeEvent.reason", "\uFFFD");
+ resolve();
+ };
+ });
+}
+
+// Verify that invalid reason strings passed to close() result in an exception
+// being thrown.
+function badReasonTest()
+{
+ return new Promise(function (resolve, reject) {
+ debug("badReasonTest: started");
+ var ws = new WebSocket(url);
+ setDefaultHandlers(ws, reject);
+ for (var id = 0; id < badReasonTestReasons.length; ++id) {
+ var test_reason = badReasonTestReasons[id];
+ debug("badReasonTest: " + test_reason);
+ try {
+ ws.close(normalClosure, test_reason);
+ reject("Exception not thrown for bad reason " + test_reason);
+ return;
+ } catch (e) {
+ exceptionName = e.name;
+ exceptionProto = Object.getPrototypeOf(e);
+ shouldBeTrue("exceptionProto === DOMException.prototype");
+ shouldBeEqualToString("exceptionName", syntaxErr);
+ }
+ }
+ removeAllHandlers(ws);
+ resolve();
+ });
+}
+
+// Verify that a valid reason code passed to close() does not result in an
+// exception.
+function goodReasonTest()
+{
+ return new Promise(function (resolve, reject) {
+ debug("goodReasonTest: started");
+ var ws = new WebSocket(url);
yhirano 2015/02/27 06:26:44 +setDefaultHandlers
Adam Rice 2015/02/27 09:34:28 Done.
+ ws.onclose = function (e)
+ {
+ closeEvent = e;
+ shouldBeEqualToNumber("closeEvent.code", abnormalClosure);
+ resolve();
+ };
+ ws.onerror = function()
+ {
+ testPassed("onerror was called.");
+ };
+ // 123 byte reason should not throw.
+ ws.close(normalClosure, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
+ });
+}
+
+// Verify that valid close codes and reasons are correctly send to the
+// WebSocket server.
+function codeAndReasonTest()
+{
+ const codes = [
+ 1000,
+ 3000,
+ 4000,
+ 4999
+ ];
+ const reasons = [
+ "OK, Bye!",
+ "3000",
+ "code is 4000",
+ "\u00a9 Google"
+ ];
+ return new Promise(function(resolve, reject) {
+ debug("codeAndReasonTest: started");
+ // Tests are run in series to produce deterministic output.
+ var promise = Promise.resolve();
+ for (var id = 0; id < codes.length; ++id) {
+ promise = promise.then(codeAndReasonSingleCase(codes[id], reasons[id]));
+ }
+ promise.then(resolve);
+ });
+}
+
+// (Return a function which returns a Promise to) handle a single code/reason
+// pair for the codeAndReasonTest.
+function codeAndReasonSingleCase(test_code, test_reason) {
+ return function() {
+ return new Promise(function (resolve, reject) {
+ debug("codeAndReasonTest: " + test_code + ", '" + test_reason + "'");
+ var ws = new WebSocket(url);
+ setDefaultHandlers(ws, reject);
+ ws.onopen = function ()
+ {
+ ws.close(test_code, test_reason);
+ };
+ ws.onclose = function (e)
+ {
+ closeEvent = e;
+ shouldBeTrue("closeEvent.wasClean");
+ shouldBeEqualToNumber("closeEvent.code", test_code);
+ shouldBeEqualToString("closeEvent.reason", test_reason);
+ resolve();
+ };
+ });
+ };
+}
+
+function cleanup() {
+ clearTimeout(timeout);
+ finishJSTest();
+}
+
+function onTimeout() {
+ handleRejection("Timeout");
+}
+
+function handleRejection(reason) {
+ if (reason instanceof Error) {
+ // Get a stack trace if an exception fired.
+ testFailed(reason.stack);
+ } else {
+ testFailed(reason);
+ }
+ cleanup();
+}
+
+function testClose() {
+ // Set an explicit timeout in order to keep text output on failure.
+ timeout = setTimeout(onTimeout, 5000);
+ // Tests are run in series to produce deterministic output.
+ badCodesTest()
+ .then(goodCodeTest)
+ .then(invalidUnicodeReasonTest)
+ .then(badReasonTest)
+ .then(goodReasonTest)
+ .then(codeAndReasonTest)
+ .then(cleanup)
+ .catch(handleRejection);
+}
« no previous file with comments | « LayoutTests/http/tests/websocket/close_wsh.py ('k') | LayoutTests/http/tests/websocket/workers/close.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698