diff options
Diffstat (limited to '')
-rw-r--r-- | remote/cdp/test/xpcshell/test_CDPConnection.js | 25 | ||||
-rw-r--r-- | remote/cdp/test/xpcshell/test_DomainCache.js | 111 | ||||
-rw-r--r-- | remote/cdp/test/xpcshell/test_Error.js | 104 | ||||
-rw-r--r-- | remote/cdp/test/xpcshell/test_Session.js | 40 | ||||
-rw-r--r-- | remote/cdp/test/xpcshell/test_StreamRegistry.js | 153 | ||||
-rw-r--r-- | remote/cdp/test/xpcshell/xpcshell.ini | 9 |
6 files changed, 442 insertions, 0 deletions
diff --git a/remote/cdp/test/xpcshell/test_CDPConnection.js b/remote/cdp/test/xpcshell/test_CDPConnection.js new file mode 100644 index 0000000000..848155633f --- /dev/null +++ b/remote/cdp/test/xpcshell/test_CDPConnection.js @@ -0,0 +1,25 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { splitMethod } = ChromeUtils.importESModule( + "chrome://remote/content/cdp/CDPConnection.sys.mjs" +); + +add_task(function test_Connection_splitMethod() { + for (const t of [42, null, true, {}, [], undefined]) { + Assert.throws(() => splitMethod(t), /TypeError/, `${typeof t} throws`); + } + for (const s of ["", ".", "foo.", ".bar", "foo.bar.baz"]) { + Assert.throws( + () => splitMethod(s), + /Invalid method format: '.*'/, + `"${s}" throws` + ); + } + deepEqual(splitMethod("foo.bar"), { + domain: "foo", + command: "bar", + }); +}); diff --git a/remote/cdp/test/xpcshell/test_DomainCache.js b/remote/cdp/test/xpcshell/test_DomainCache.js new file mode 100644 index 0000000000..9ea53ccdd9 --- /dev/null +++ b/remote/cdp/test/xpcshell/test_DomainCache.js @@ -0,0 +1,111 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { Domain } = ChromeUtils.importESModule( + "chrome://remote/content/cdp/domains/Domain.sys.mjs" +); +const { DomainCache } = ChromeUtils.importESModule( + "chrome://remote/content/cdp/domains/DomainCache.sys.mjs" +); + +class MockSession { + onEvent() {} +} + +const noopSession = new MockSession(); + +add_task(function test_DomainCache_constructor() { + new DomainCache(noopSession, {}); +}); + +add_task(function test_DomainCache_domainSupportsMethod() { + const modules = { + Foo: class extends Domain { + bar() {} + }, + }; + const domains = new DomainCache(noopSession, modules); + + ok(domains.domainSupportsMethod("Foo", "bar")); + ok(!domains.domainSupportsMethod("Foo", "baz")); + ok(!domains.domainSupportsMethod("foo", "bar")); +}); + +add_task(function test_DomainCache_get_invalidModule() { + Assert.throws(() => { + const domains = new DomainCache(noopSession, { Foo: undefined }); + domains.get("Foo"); + }, /UnknownMethodError/); +}); + +add_task(function test_DomainCache_get_missingConstructor() { + Assert.throws(() => { + const domains = new DomainCache(noopSession, { Foo: {} }); + domains.get("Foo"); + }, /TypeError/); +}); + +add_task(function test_DomainCache_get_superClassNotDomain() { + Assert.throws(() => { + const domains = new DomainCache(noopSession, { Foo: class {} }); + domains.get("Foo"); + }, /TypeError/); +}); + +add_task(function test_DomainCache_get_constructs() { + let eventFired; + class Session { + onEvent(event) { + eventFired = event; + } + } + + let constructed = false; + class Foo extends Domain { + constructor() { + super(); + constructed = true; + } + } + + const session = new Session(); + const domains = new DomainCache(session, { Foo }); + + const foo = domains.get("Foo"); + ok(constructed); + ok(foo instanceof Foo); + + const event = {}; + foo.emit(event); + equal(event, eventFired); +}); + +add_task(function test_DomainCache_size() { + class Foo extends Domain {} + const domains = new DomainCache(noopSession, { Foo }); + + equal(domains.size, 0); + domains.get("Foo"); + equal(domains.size, 1); +}); + +add_task(function test_DomainCache_clear() { + let dtorCalled = false; + class Foo extends Domain { + destructor() { + dtorCalled = true; + } + } + + const domains = new DomainCache(noopSession, { Foo }); + + equal(domains.size, 0); + domains.get("Foo"); + equal(domains.size, 1); + + domains.clear(); + equal(domains.size, 0); + ok(dtorCalled); +}); diff --git a/remote/cdp/test/xpcshell/test_Error.js b/remote/cdp/test/xpcshell/test_Error.js new file mode 100644 index 0000000000..1be7be18ed --- /dev/null +++ b/remote/cdp/test/xpcshell/test_Error.js @@ -0,0 +1,104 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; +/* eslint-disable no-tabs */ + +const { RemoteAgentError, UnknownMethodError, UnsupportedError } = + ChromeUtils.importESModule("chrome://remote/content/cdp/Error.sys.mjs"); + +add_task(function test_RemoteAgentError_ctor() { + const e1 = new RemoteAgentError(); + equal(e1.name, "RemoteAgentError"); + equal(e1.message, ""); + equal(e1.cause, e1.message); + + const e2 = new RemoteAgentError("message"); + equal(e2.message, "message"); + equal(e2.cause, e2.message); + + const e3 = new RemoteAgentError("message", "cause"); + equal(e3.message, "message"); + equal(e3.cause, "cause"); +}); + +add_task(function test_RemoteAgentError_notify() { + // nothing much we can test, except test that it doesn't throw + new RemoteAgentError().notify(); +}); + +add_task(function test_RemoteAgentError_toString() { + const e = new RemoteAgentError("message"); + equal(e.toString(), RemoteAgentError.format(e)); + equal( + e.toString({ stack: true }), + RemoteAgentError.format(e, { stack: true }) + ); +}); + +add_task(function test_RemoteAgentError_format() { + const { format } = RemoteAgentError; + + equal(format({ name: "HippoError" }), "HippoError"); + equal(format({ name: "HorseError", message: "neigh" }), "HorseError: neigh"); + + const dog = { + name: "DogError", + message: "woof", + stack: " one\ntwo\nthree ", + }; + equal(format(dog), "DogError: woof"); + equal( + format(dog, { stack: true }), + `DogError: woof: + one + two + three` + ); + + const cat = { + name: "CatError", + message: "meow", + stack: "four\nfive\nsix", + cause: dog, + }; + equal(format(cat), "CatError: meow"); + equal( + format(cat, { stack: true }), + `CatError: meow: + four + five + six +caused by: DogError: woof: + one + two + three` + ); +}); + +add_task(function test_RemoteAgentError_fromJSON() { + const cdpErr = { + message: `TypeError: foo: + bar + baz`, + }; + const err = RemoteAgentError.fromJSON(cdpErr); + + equal(err.message, "TypeError: foo"); + equal(err.stack, "bar\nbaz"); + equal(err.cause, null); +}); + +add_task(function test_UnsupportedError() { + ok(new UnsupportedError() instanceof RemoteAgentError); +}); + +add_task(function test_UnknownMethodError() { + ok(new UnknownMethodError() instanceof RemoteAgentError); + ok(new UnknownMethodError("domain").message.endsWith("domain")); + ok( + new UnknownMethodError("domain", "command").message.endsWith( + "domain.command" + ) + ); +}); diff --git a/remote/cdp/test/xpcshell/test_Session.js b/remote/cdp/test/xpcshell/test_Session.js new file mode 100644 index 0000000000..3cd8adc7e3 --- /dev/null +++ b/remote/cdp/test/xpcshell/test_Session.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { Session } = ChromeUtils.importESModule( + "chrome://remote/content/cdp/sessions/Session.sys.mjs" +); + +const connection = { + registerSession: () => {}, + transport: { + on: () => {}, + }, +}; + +class MockTarget { + constructor() {} + + get browsingContext() { + return { id: 42 }; + } + + get mm() { + return { + addMessageListener() {}, + removeMessageListener() {}, + loadFrameScript() {}, + sendAsyncMessage() {}, + }; + } +} + +add_task(function test_Session_destructor() { + const session = new Session(connection, new MockTarget()); + session.domains.get("Browser"); + equal(session.domains.size, 1); + session.destructor(); + equal(session.domains.size, 0); +}); diff --git a/remote/cdp/test/xpcshell/test_StreamRegistry.js b/remote/cdp/test/xpcshell/test_StreamRegistry.js new file mode 100644 index 0000000000..329f33d275 --- /dev/null +++ b/remote/cdp/test/xpcshell/test_StreamRegistry.js @@ -0,0 +1,153 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { Stream, StreamRegistry } = ChromeUtils.importESModule( + "chrome://remote/content/cdp/StreamRegistry.sys.mjs" +); + +add_task(function test_constructor() { + const registry = new StreamRegistry(); + equal(registry.streams.size, 0); +}); + +add_task(async function test_destructor() { + const registry = new StreamRegistry(); + + const stream1 = await createFileStream("foo bar"); + const stream2 = await createFileStream("foo bar"); + + registry.add(stream1); + registry.add(stream2); + + equal(registry.streams.size, 2); + + await registry.destructor(); + equal(registry.streams.size, 0); + + ok(!(await IOUtils.exists(stream1.path)), "temporary file has been removed"); + ok(!(await IOUtils.exists(stream2.path)), "temporary file has been removed"); +}); + +add_task(async function test_addValidStreamType() { + const registry = new StreamRegistry(); + + const stream = await createFileStream("foo bar"); + const handle = registry.add(stream); + + equal(registry.streams.size, 1, "A single stream has been added"); + equal(typeof handle, "string", "Handle is of type string"); + ok(registry.streams.has(handle), "Handle has been found"); + + const rv = registry.streams.get(handle); + equal(rv, stream, "Expected stream found"); +}); + +add_task(async function test_addCreatesDifferentHandles() { + const registry = new StreamRegistry(); + const stream = await createFileStream("foo bar"); + + const handle1 = registry.add(stream); + equal(registry.streams.size, 1, "A single stream has been added"); + equal(typeof handle1, "string", "Handle is of type string"); + ok(registry.streams.has(handle1), "Handle has been found"); + equal(registry.streams.get(handle1), stream, "Expected stream found"); + + const handle2 = registry.add(stream); + equal(registry.streams.size, 2, "A single stream has been added"); + equal(typeof handle2, "string", "Handle is of type string"); + ok(registry.streams.has(handle2), "Handle has been found"); + equal(registry.streams.get(handle2), stream, "Expected stream found"); + + notEqual(handle1, handle2, "Different handles have been generated"); +}); + +add_task(async function test_addInvalidStreamType() { + const registry = new StreamRegistry(); + Assert.throws(() => registry.add(new Blob([])), /UnsupportedError/); +}); + +add_task(async function test_getForValidHandle() { + const registry = new StreamRegistry(); + const stream = await createFileStream("foo bar"); + const handle = registry.add(stream); + + equal(registry.streams.size, 1, "A single stream has been added"); + equal(registry.get(handle), stream, "Expected stream found"); +}); + +add_task(async function test_getForInvalidHandle() { + const registry = new StreamRegistry(); + const stream = await createFileStream("foo bar"); + registry.add(stream); + + equal(registry.streams.size, 1, "A single stream has been added"); + Assert.throws(() => registry.get("foo"), /TypeError/); +}); + +add_task(async function test_removeForValidHandle() { + const registry = new StreamRegistry(); + const stream1 = await createFileStream("foo bar"); + const stream2 = await createFileStream("foo bar"); + + const handle1 = registry.add(stream1); + const handle2 = registry.add(stream2); + + equal(registry.streams.size, 2); + + await registry.remove(handle1); + equal(registry.streams.size, 1); + equal(registry.get(handle2), stream2, "Second stream has not been closed"); + + ok( + !(await IOUtils.exists(stream1.path)), + "temporary file for first stream is removed" + ); + ok( + await IOUtils.exists(stream2.path), + "temporary file for second stream is not removed" + ); +}); + +add_task(async function test_removeForInvalidHandle() { + const registry = new StreamRegistry(); + const stream = await createFileStream("foo bar"); + registry.add(stream); + + equal(registry.streams.size, 1, "A single stream has been added"); + await Assert.rejects(registry.remove("foo"), /TypeError/); +}); + +/** + * Create a stream with the specified contents. + * + * @param {string} contents + * Contents of the file. + * @param {object} options + * @param {string=} options.path + * Path of the file. Defaults to the temporary directory. + * @param {boolean=} options.remove + * If true, automatically remove the file after the test. Defaults to true. + * + * @returns {Promise<Stream>} + */ +async function createFileStream(contents, options = {}) { + let { path = null, remove = true } = options; + + if (!path) { + path = await IOUtils.createUniqueFile( + PathUtils.tempDir, + "remote-agent.txt" + ); + } + + await IOUtils.writeUTF8(path, contents); + + const stream = new Stream(path); + if (remove) { + registerCleanupFunction(() => stream.destroy()); + } + + return stream; +} diff --git a/remote/cdp/test/xpcshell/xpcshell.ini b/remote/cdp/test/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..c1f1856fde --- /dev/null +++ b/remote/cdp/test/xpcshell/xpcshell.ini @@ -0,0 +1,9 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +[test_CDPConnection.js] +[test_DomainCache.js] +[test_Error.js] +[test_Session.js] +[test_StreamRegistry.js] |