summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/infrastructure/channels
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--testing/web-platform/tests/infrastructure/channels/child_message.html13
-rw-r--r--testing/web-platform/tests/infrastructure/channels/child_script.html10
-rw-r--r--testing/web-platform/tests/infrastructure/channels/serialize-data.js37
-rw-r--r--testing/web-platform/tests/infrastructure/channels/serialize_child.html173
-rw-r--r--testing/web-platform/tests/infrastructure/channels/test_call.html22
-rw-r--r--testing/web-platform/tests/infrastructure/channels/test_postMessage.html23
-rw-r--r--testing/web-platform/tests/infrastructure/channels/test_serialize.html38
7 files changed, 316 insertions, 0 deletions
diff --git a/testing/web-platform/tests/infrastructure/channels/child_message.html b/testing/web-platform/tests/infrastructure/channels/child_message.html
new file mode 100644
index 0000000000..6baf47b193
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/child_message.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<script src="/resources/channel.sub.js"></script>
+<script>
+function handleMessage(msg) {
+ // We expect the message to be a SendChannel
+ respChannel = msg;
+ respChannel.send("PASS");
+}
+
+let channel = global_channel();
+channel.addMessageHandler(handleMessage);
+channel.connect();
+</script>
diff --git a/testing/web-platform/tests/infrastructure/channels/child_script.html b/testing/web-platform/tests/infrastructure/channels/child_script.html
new file mode 100644
index 0000000000..1c10379bde
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/child_script.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<script src="/resources/channel.sub.js"></script>
+<div id="test">FAIL</div>
+<script>
+(async function() {
+ await new Promise(resolve => onload = resolve);
+ document.getElementById("test").textContent = "PASS";
+ await start_global_channel();
+})()
+</script>
diff --git a/testing/web-platform/tests/infrastructure/channels/serialize-data.js b/testing/web-platform/tests/infrastructure/channels/serialize-data.js
new file mode 100644
index 0000000000..5c423ee160
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/serialize-data.js
@@ -0,0 +1,37 @@
+let cyclicArray = [1];
+cyclicArray.push(cyclicArray);
+
+let cyclicObject = {key1: "data"};
+cyclicObject.key2 = cyclicObject;
+
+let cyclicSet = new Set([1]);
+cyclicSet.add(cyclicSet);
+
+let cyclicMap = new Map([["key1", 1]]);
+cyclicMap.set("key2", cyclicMap);
+
+const objects = {
+ "null": {input: null},
+ "undefined": {input: undefined},
+ "int": {input: 1},
+ "Infinity": {input: Infinity},
+ "-Infinity": {input: -Infinity},
+ "NaN": {input: NaN},
+ "string": {input: "foo"},
+ "true": {input: true},
+ "false": {input: false},
+ "bigint": {input: 1n},
+ "RegExp": {input: /abc/g},
+ "Date": {input: new Date('December 17, 1995 03:24:00')},
+ "Error": {"input": new Error("message")},
+ "TypeError": {"input": new TypeError("TypeError message")},
+ "array": {input: [1,"foo"], output: [1, "foo"]},
+ "nested array": {input: [1,[2]]},
+ "set": {input: new Set([1, "foo", null])},
+ "object": {input: {key1: 1, key2: false}},
+ "nested object": {input: {key1: 1, key2: false}},
+ "map": {input: new Map([[1, 1], ["key2", false]])},
+ "cyclic array": {input: cyclicArray},
+ "cyclic object": {input: cyclicObject},
+ "cyclic map": {input: cyclicMap},
+};
diff --git a/testing/web-platform/tests/infrastructure/channels/serialize_child.html b/testing/web-platform/tests/infrastructure/channels/serialize_child.html
new file mode 100644
index 0000000000..6ad3accfee
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/serialize_child.html
@@ -0,0 +1,173 @@
+<!doctype html>
+<script src="/resources/channel.sub.js"></script>
+<script src="serialize-data.js"></script>
+<script>
+
+let lastData;
+
+// Hack: these will be converted into testharness AssertionError instances in the test
+// This means they will be treated identically to asserts raised by `assert_` in the harness
+// In the long term we want to be able to use parts of testharness.js directly in remote
+// contexts and automatically send the results over a channel.
+function AssertionError(message) {
+ this.message = message;
+}
+AssertionError.prototype = Object.create(Error.prototype);
+
+function compareResult(name, actual) {
+ let obj = objects[name];
+ // If there's an output property use that, otherwise assume the output is equal to the input
+ let expected = obj.hasOwnProperty("output") ? obj.output : obj.input;
+ seen = new Set();
+ try {
+ compareValue(actual, expected, seen);
+ } catch(e) {
+ throw new AssertionError(e.message);
+ }
+ return true;
+}
+
+function compareValue(actualValue, expectedValue, seen) {
+ let seenActual;
+ if (typeof actualValue != typeof expectedValue) {
+ throw new Error(`Types differ, expected ${typeof expectedValue}, got ${typeof actualValue}`);
+ }
+ if (["undefined", "string", "boolean", "number", "bigint"].includes(typeof expectedValue) ||
+ actualValue === null) {
+ if (!Object.is(actualValue, expectedValue)) {
+ throw new Error(`Expected ${typeof expected} ${expected}, got ${actual}`);
+ }
+ return;
+ }
+
+ if (expectedValue.constructor && actualValue.constructor && expectedValue.constructor.name !== actualValue.constructor.name) {
+ throw new Error(`Constructors differ, expected ${expectedValue.constructor.name}, got ${actualValue.constructor.name}`);
+ }
+ if (expectedValue.constructor && expectedValue.constructor.name === "SendChannel") {
+ if (expectedValue.uuid !== actualValue.uuid) {
+ throw new Error(`SendChannels differ, expected uuid ${expectedValue.uuid}, got ${actualValue.uuid}`);
+ }
+ }
+ else if (expectedValue.constructor && expectedValue.constructor.name === "RegExp") {
+ if (expectedValue.source !== actualValue.source ||
+ expectedValue.flags !== actualValue.flags) {
+ throw new Error(`RegExps differ, expected ${expectedValue}, got ${actualValue}`);
+ }
+ } else if (expectedValue.constructor && expectedValue.constructor.name == "Date") {
+ if (expectedValue.valueOf() !== actualValue.valueOf()) {
+ throw new Error(`Dates differ, expected ${expectedValue.valueOf()} (${expectedValue.toDateString()}), `
+ `got ${actualValue.valueOf()} (${actualValue.toDateString()})`);
+ }
+ } else if (expectedValue instanceof Error) {
+ if (expectedValue.message !== actualValue.message ||
+ expectedValue.lineNumber !== actualValue.lineNumber ||
+ expectedValue.columnNumber !== actualValue.columnNumber ||
+ expectedValue.fileName !== actualValue.fileName) {
+ throw new Error(`Errors differ, expected ${expectedValue}, got ${actualValue}`);
+ }
+ } else if (Array.isArray(expectedValue)) {
+ seenActual = seen.has(actualValue);
+ seenExpected = seen.has(expectedValue)
+ if (seenActual && seenExpected) {
+ return;
+ } else if (seenExpected && !seenActual) {
+ throw new Error(`Expected cyclic array`);
+ } else if (!seenExpected && seenActual) {
+ throw new Error(`Got unexpected cyclic array`);
+ }
+ seen.add(actualValue);
+ seen.add(expectedValue);
+
+ if (actualValue.length !== expectedValue.length) {
+ throw new Error(`Array lengths differ, expected ${expectedValue.length}, got ${actualValue.length}`);
+ }
+ for (let i=0; i<actualValue.length; i++) {
+ compareValue(actualValue[i], expectedValue[i], seen);
+ }
+ } else if (expectedValue.constructor && expectedValue.constructor.name === "Set") {
+ seenActual = seen.has(actualValue);
+ seenExpected = seen.has(expectedValue)
+ if (seenActual && seenExpected) {
+ return;
+ } else if (seenExpected && !seenActual) {
+ throw new Error(`Expected cyclic set`);
+ } else if (!seenExpected && seenActual) {
+ throw new Error(`Got unexpected cyclic set`);
+ }
+ seen.add(actualValue);
+ seen.add(expectedValue);
+
+
+ if (actualValue.size !== expectedValue.size) {
+ throw new Error(`Set sizes differ, expected ${expectedValue.size}, got ${actualValue.size}`);
+ }
+ // For an arbitary set it's complex to check if two sets are equivalent, since
+ // we'd need to compare every object in one set with every object in the
+ // other set, so we end up with quadratic complexity. Instead, just support sets
+ // containing primitives and rely on the other tests for correct handling of
+ // objects.
+ for (let entry of expectedValue) {
+ if (["undefined", "string", "boolean", "number", "bigint"].includes(typeof entry) || entry === null) {
+ if(!actualValue.has(entry)) {
+ throw new Error(`Set missing entry, expected ${entry}`);
+ }
+ } else {
+ throw new Error(`Can't compare non-primitive value ${entry} inside sets`);
+ }
+ }
+ } else if (expectedValue.constructor && expectedValue.constructor.name === "Map") {
+ seenActual = seen.has(actualValue);
+ seenExpected = seen.has(expectedValue)
+ if (seenActual && seenExpected) {
+ return;
+ } else if (seenExpected && !seenActual) {
+ throw new Error(`Expected cyclic map`);
+ } else if (!seenExpected && seenActual) {
+ throw new Error(`Got unexpected cyclic map`);
+ }
+ seen.add(actualValue);
+ seen.add(expectedValue);
+
+ if (actualValue.size !== expectedValue.size) {
+ throw new Error(`Map sizes differ, expected ${expectedValue.size}, got ${actualValue.size}`);
+ }
+ // So for a set we can't really check if the values are the same
+ // except where they're primitives
+ for (let [key, value] of expectedValue.entries()) {
+ if(!actualValue.has(key)) {
+ throw new Error(`Map missing key, expected key ${key} with value ${value}`);
+ }
+ compareValue(actualValue.get(key), value, seen);
+ }
+ } else {
+ seenActual = seen.has(actualValue);
+ seenExpected = seen.has(expectedValue)
+ if (seenActual && seenExpected) {
+ return;
+ } else if (seenExpected && !seenActual) {
+ throw new Error(`Expected cyclic object`);
+ } else if (!seenExpected && seenActual) {
+ throw new Error(`Got unexpected cyclic object`);
+ }
+ seen.add(actualValue);
+ seen.add(expectedValue);
+
+
+ // Compare as a general Object
+ let expectedEntries = Object.entries(expectedValue);
+ if (Object.keys(actualValue).length !== expectedEntries.length) {
+ throw new Error(`Object keys differ, expected [${Object.keys(expectedValue).join(",")}], got [${Object.keys(actualValue).join(",")}]`);
+ }
+ // So for a set we can't really check if the values are the same
+ // except where they're primitives
+ for (let [name, entry] of expectedEntries) {
+ if(!actualValue.hasOwnProperty(name)) {
+ throw new Error(`Object missing key ${name}`);
+ }
+ compareValue(actualValue[name], entry, seen);
+ }
+ }
+}
+
+ctx = start_global_channel();
+</script>
diff --git a/testing/web-platform/tests/infrastructure/channels/test_call.html b/testing/web-platform/tests/infrastructure/channels/test_call.html
new file mode 100644
index 0000000000..49beaea4ff
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/test_call.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>call method</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/channel.sub.js"></script>
+
+<script>
+setup({single_test: true})
+onload = async () => {
+ let remote = await new RemoteGlobal();
+
+ let url = `child_script.html?uuid=${remote.uuid}`;
+ win = window.open(url, "_blank", "noopener");
+
+ let result = await remote.call(async (elemId) => {
+ return document.getElementById(elemId).textContent;
+ }, ["test"]);
+ assert_equals(result.trim(), "PASS");
+ done();
+}
+</script>
diff --git a/testing/web-platform/tests/infrastructure/channels/test_postMessage.html b/testing/web-platform/tests/infrastructure/channels/test_postMessage.html
new file mode 100644
index 0000000000..473c8630a6
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/test_postMessage.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>postMessage method</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/channel.sub.js"></script>
+
+<script>
+setup({single_test: true});
+(async () => {
+ let remote = await new RemoteGlobal();
+
+ let url = `child_message.html?uuid=${remote.uuid}`;
+ win = window.open(url, "_blank", "noopener");
+
+ let [recvChannel, sendChannel] = channel();
+ await remote.postMessage(sendChannel);
+ await recvChannel.connect();
+ let message = await recvChannel.nextMessage();
+ assert_equals(message, "PASS");
+ done();
+})();
+</script>
diff --git a/testing/web-platform/tests/infrastructure/channels/test_serialize.html b/testing/web-platform/tests/infrastructure/channels/test_serialize.html
new file mode 100644
index 0000000000..88a9ce5221
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/channels/test_serialize.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>object serialization</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/channel.sub.js"></script>
+<script src="serialize-data.js"></script>
+
+<script>
+setup(() => {
+ remote = new RemoteGlobal();
+
+ let url = `serialize_child.html?uuid=${remote.uuid}`;
+ win = window.open(url);
+});
+
+for (let [name, obj] of Object.entries(objects)) {
+ promise_test(async t => {
+ let result = await remote.call(
+ (name, inputValue) => compareResult(name, inputValue),
+ name,
+ obj.input);
+ assert_true(result);
+ }, `Serialize ${name}`);
+}
+
+promise_test(async t => {
+ let remoteValue = RemoteObject.from(document.head);
+ let result = await remote.call(inputValue => {
+ if (!inputValue instanceof RemoteObject) {
+ throw new AssertionError(`Expected RemoteObject`);
+ }
+ return inputValue;
+ }, remoteValue);
+ assert_equals(result, document.head);
+}, "Serialize RemoteObject");
+
+</script>