diff options
Diffstat (limited to 'toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell')
10 files changed, 687 insertions, 0 deletions
diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_arithmetic.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_arithmetic.js new file mode 100644 index 0000000000..a221abc39f --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_arithmetic.js @@ -0,0 +1,48 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const Arithmetic = ChromeUtils.importESModule( + "resource://gre/modules/RustArithmetic.sys.mjs" +); + +add_task(async function () { + Assert.ok(Arithmetic.IntegerOverflow); + Assert.equal(await Arithmetic.add(2, 4), 6); + Assert.equal(await Arithmetic.add(4, 8), 12); + // For other backends we would have this test: + // await Assert.rejects( + // Arithmetic.add(18446744073709551615, 1), + // Arithmetic.IntegerOverflow, + // "add() should throw IntegerOverflow") + // + // However, this doesn't work because JS number values are actually 64-bit + // floats, and that number is greater than the maximum "safe" integer. + // + // Instead, let's test that we reject numbers that are that big + await Assert.rejects( + Arithmetic.add(Number.MAX_SAFE_INTEGER + 1, 0), + /TypeError/, + "add() should throw TypeError when an input is > MAX_SAFE_INTEGER" + ); + + Assert.equal(await Arithmetic.sub(4, 2), 2); + Assert.equal(await Arithmetic.sub(8, 4), 4); + await Assert.rejects( + Arithmetic.sub(0, 1), + Arithmetic.IntegerOverflow, + "sub() should throw IntegerOverflow" + ); + + Assert.equal(await Arithmetic.div(8, 4), 2); + // Can't test this, because we don't allow Rust panics in FF + // Assert.rejects( + // Arithmetic.div(8, 0), + // (e) => Assert.equal(e, Arithmetic.UniFFIInternalError), + // "Divide by 0 should throw UniFFIInternalError") + // + Assert.ok(await Arithmetic.equal(2, 2)); + Assert.ok(await Arithmetic.equal(4, 4)); + + Assert.ok(!(await Arithmetic.equal(2, 4))); + Assert.ok(!(await Arithmetic.equal(4, 8))); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_callbacks.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_callbacks.js new file mode 100644 index 0000000000..67f0a167a8 --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_callbacks.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { logEvenNumbers, logEvenNumbersMainThread } = ChromeUtils.importESModule( + "resource://gre/modules/RustFixtureCallbacks.sys.mjs" +); + +class Logger { + constructor() { + this.messages = []; + this.finishedPromise = new Promise((resolve, reject) => { + this.finishedResolve = resolve; + this.finishedReject = reject; + }); + } + + log(message) { + this.messages.push(message); + } + + finished() { + this.finishedResolve(true); + } + + async waitForFinish() { + // Set a timeout to avoid hanging the tests if the Rust code fails to call finished(). + do_timeout(2000, () => + this.finishedReject("Timeout waiting for finished()") + ); + return this.finishedPromise; + } +} + +add_task(async function testLogEvenNumbers() { + async function runTest(logEvenNumbersFunc) { + const logger = new Logger(); + logEvenNumbersFunc(logger, [1, 1, 2, 3, 5, 8, 13]); + await logger.waitForFinish(); + Assert.deepEqual(logger.messages, [ + "Saw even number: 2", + "Saw even number: 8", + ]); + } + + await runTest(logEvenNumbers); + await runTest(logEvenNumbersMainThread); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_custom_types.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_custom_types.js new file mode 100644 index 0000000000..cd26467494 --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_custom_types.js @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const CustomTypes = ChromeUtils.importESModule( + "resource://gre/modules/RustCustomTypes.sys.mjs" +); + +add_task(async function () { + // JS right now doesn't treat custom types as anything but it's native counterparts + let demo = await CustomTypes.getCustomTypesDemo(); + Assert.equal(demo.url, "http://example.com/"); + Assert.equal(demo.handle, 123); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_external_types.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_external_types.js new file mode 100644 index 0000000000..e2f985cde7 --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_external_types.js @@ -0,0 +1,16 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const ExternalTypes = ChromeUtils.importESModule( + "resource://gre/modules/RustExternalTypes.sys.mjs" +); + +add_task(async function () { + const line = new ExternalTypes.Line( + new ExternalTypes.Point(0, 0, "p1"), + new ExternalTypes.Point(2, 1, "p2") + ); + Assert.equal(await ExternalTypes.gradient(line), 0.5); + + Assert.equal(await ExternalTypes.gradient(null), 0.0); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_geometry.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_geometry.js new file mode 100644 index 0000000000..f06ecd46aa --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_geometry.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const Geometry = ChromeUtils.importESModule( + "resource://gre/modules/RustGeometry.sys.mjs" +); + +add_task(async function () { + const ln1 = new Geometry.Line( + new Geometry.Point(0, 0, "p1"), + new Geometry.Point(1, 2, "p2") + ); + const ln2 = new Geometry.Line( + new Geometry.Point(1, 1, "p3"), + new Geometry.Point(2, 2, "p4") + ); + const origin = new Geometry.Point(0, 0); + Assert.ok((await Geometry.intersection(ln1, ln2)).equals(origin)); + Assert.deepEqual(await Geometry.intersection(ln1, ln2), origin); + Assert.strictEqual(await Geometry.intersection(ln1, ln1), null); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_rondpoint.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_rondpoint.js new file mode 100644 index 0000000000..8c673b2e92 --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_rondpoint.js @@ -0,0 +1,311 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const Rondpoint = ChromeUtils.importESModule( + "resource://gre/modules/RustRondpoint.sys.mjs" +); + +const { + Dictionnaire, + Enumeration, + copieDictionnaire, + copieEnumeration, + copieEnumerations, + copieCarte, + EnumerationAvecDonnees, + switcheroo, + Retourneur, + DictionnaireNombresSignes, + DictionnaireNombres, + Stringifier, + Optionneur, + OptionneurDictionnaire, +} = Rondpoint; +add_task(async function () { + const dico = new Dictionnaire(Enumeration.DEUX, true, 0, 1235); + const copyDico = await copieDictionnaire(dico); + Assert.deepEqual(dico, copyDico); + + Assert.equal(await copieEnumeration(Enumeration.DEUX), Enumeration.DEUX); + Assert.deepEqual( + await copieEnumerations([Enumeration.UN, Enumeration.DEUX]), + [Enumeration.UN, Enumeration.DEUX] + ); + const obj = { + 0: new EnumerationAvecDonnees.Zero(), + 1: new EnumerationAvecDonnees.Un(1), + 2: new EnumerationAvecDonnees.Deux(2, "deux"), + }; + + Assert.deepEqual(await copieCarte(obj), obj); + + const zero = new EnumerationAvecDonnees.Zero(); + const one = new EnumerationAvecDonnees.Un(1); + const two = new EnumerationAvecDonnees.Deux(2); + Assert.notEqual(zero, one); + Assert.notEqual(one, two); + + Assert.deepEqual(zero, new EnumerationAvecDonnees.Zero()); + Assert.deepEqual(one, new EnumerationAvecDonnees.Un(1)); + Assert.notDeepEqual(one, new EnumerationAvecDonnees.Un(4)); + + Assert.ok(await switcheroo(false)); + // Test the roundtrip across the FFI. + // This shows that the values we send come back in exactly the same state as we sent them. + // i.e. it shows that lowering from JS and lifting into rust is symmetrical with + // lowering from rust and lifting into JS. + + const rt = await Retourneur.init(); + + const affirmAllerRetour = async (arr, fn, equalFn) => { + for (const member of arr) { + if (equalFn) { + equalFn(await fn(member), member); + } else { + Assert.equal(await fn(member), member); + } + } + }; + + // Booleans + await affirmAllerRetour([true, false], rt.identiqueBoolean.bind(rt)); + + // Bytes + await affirmAllerRetour([-128, 127], rt.identiqueI8.bind(rt)); + await affirmAllerRetour([0, 0xff], rt.identiqueU8.bind(rt)); + + // Shorts + await affirmAllerRetour([-32768, 32767], rt.identiqueI16.bind(rt)); + await affirmAllerRetour([0, 0xffff], rt.identiqueU16.bind(rt)); + + // Ints + await affirmAllerRetour( + [0, 1, -1, -2147483648, 2147483647], + rt.identiqueI32.bind(rt) + ); + await affirmAllerRetour([0, 0xffffffff], rt.identiqueU32.bind(rt)); + + // Longs + // NOTE: we cannot represent greater than `Number.MAX_SAFE_INTEGER` + await affirmAllerRetour( + [0, 1, -1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + rt.identiqueI64.bind(rt) + ); + await affirmAllerRetour( + [0, Number.MAX_SAFE_INTEGER], + rt.identiqueU64.bind(rt) + ); + + // Floats + const equalFloats = (a, b) => Assert.ok(Math.abs(a - b) <= Number.EPSILON); + await affirmAllerRetour( + [0.0, 0.5, 0.25, 1.5], + rt.identiqueFloat.bind(rt), + equalFloats + ); + // Some float value's precision gets messed up, an example is 3.22, 100.223, etc + // await affirmAllerRetour([0.0, 0.5, 0.25, 1.5, 100.223], rt.identiqueFloat.bind(rt), equalFloats); + + // Double (although on the JS side doubles are limited since they are also represented by Number) + await affirmAllerRetour( + [0.0, 0.5, 0.25, 1.5], + rt.identiqueDouble.bind(rt), + equalFloats + ); + + // Strings + await affirmAllerRetour( + [ + "", + "abc", + "null\u0000byte", + "été", + "ښي لاس ته لوستلو لوستل", + "😻emoji 👨👧👦multi-emoji, 🇨🇭a flag, a canal, panama", + ], + rt.identiqueString.bind(rt) + ); + + await affirmAllerRetour( + [-1, 0, 1].map(n => new DictionnaireNombresSignes(n, n, n, n)), + rt.identiqueNombresSignes.bind(rt), + (a, b) => Assert.deepEqual(a, b) + ); + + await affirmAllerRetour( + [0, 1].map(n => new DictionnaireNombres(n, n, n, n)), + rt.identiqueNombres.bind(rt), + (a, b) => Assert.deepEqual(a, b) + ); + + // Test one way across the FFI. + // + // We send one representation of a value to lib.rs, and it transforms it into another, a string. + // lib.rs sends the string back, and then we compare here in js. + // + // This shows that the values are transformed into strings the same way in both js and rust. + // i.e. if we assume that the string return works (we test this assumption elsewhere) + // we show that lowering from js and lifting into rust has values that both js and rust + // both stringify in the same way. i.e. the same values. + // + // If we roundtripping proves the symmetry of our lowering/lifting from here to rust, and lowering/lifting from rust to here, + // and this convinces us that lowering/lifting from here to rust is correct, then + // together, we've shown the correctness of the return leg. + const st = await Stringifier.init(); + + const affirmEnchaine = async (arr, fn) => { + for (const member of arr) { + Assert.equal(await fn(member), String(member)); + } + }; + + // Booleans + await affirmEnchaine([true, false], st.toStringBoolean.bind(st)); + + // Bytes + await affirmEnchaine([-128, 127], st.toStringI8.bind(st)); + await affirmEnchaine([0, 0xff], st.toStringU8.bind(st)); + + // Shorts + await affirmEnchaine([-32768, 32767], st.toStringI16.bind(st)); + await affirmEnchaine([0, 0xffff], st.toStringU16.bind(st)); + + // Ints + await affirmEnchaine( + [0, 1, -1, -2147483648, 2147483647], + st.toStringI32.bind(st) + ); + await affirmEnchaine([0, 0xffffffff], st.toStringU32.bind(st)); + + // Longs + // NOTE: we cannot represent greater than `Number.MAX_SAFE_INTEGER` + await affirmEnchaine( + [0, 1, -1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + st.toStringI64.bind(st) + ); + await affirmEnchaine([0, Number.MAX_SAFE_INTEGER], st.toStringU64.bind(st)); + + // Floats + await affirmEnchaine([0.0, 0.5, 0.25, 1.5], st.toStringFloat.bind(st)); + + // Doubles + await affirmEnchaine([0.0, 0.5, 0.25, 1.5], st.toStringDouble.bind(st)); + + // Prove to ourselves that default arguments are being used. + // Step 1: call the methods without arguments, and check against the UDL. + const op = await Optionneur.init(); + + Assert.equal(await op.sinonString(), "default"); + + Assert.ok(!(await op.sinonBoolean())); + + Assert.deepEqual(await op.sinonSequence(), []); + + Assert.equal(await op.sinonNull(), null); + Assert.equal(await op.sinonZero(), 0); + + // decimal integers + Assert.equal(await op.sinonI8Dec(), -42); + Assert.equal(await op.sinonU8Dec(), 42); + Assert.equal(await op.sinonI16Dec(), 42); + Assert.equal(await op.sinonU16Dec(), 42); + Assert.equal(await op.sinonI32Dec(), 42); + Assert.equal(await op.sinonU32Dec(), 42); + Assert.equal(await op.sinonI64Dec(), 42); + Assert.equal(await op.sinonU64Dec(), 42); + + // hexadecimal integers + Assert.equal(await op.sinonI8Hex(), -0x7f); + Assert.equal(await op.sinonU8Hex(), 0xff); + Assert.equal(await op.sinonI16Hex(), 0x7f); + Assert.equal(await op.sinonU16Hex(), 0xffff); + Assert.equal(await op.sinonI32Hex(), 0x7fffffff); + Assert.equal(await op.sinonU32Hex(), 0xffffffff); + // The following are too big to be represented by js `Number` + // Assert.equal(await op.sinonI64Hex(), 0x7fffffffffffffff); + // Assert.equal(await op.sinonU64Hex(), 0xffffffffffffffff); + + // octal integers + Assert.equal(await op.sinonU32Oct(), 0o755); + + // floats + Assert.equal(await op.sinonF32(), 42.0); + Assert.equal(await op.sinonF64(), 42.1); + + // enums + Assert.equal(await op.sinonEnum(), Enumeration.TROIS); + + // Step 2. Convince ourselves that if we pass something else, then that changes the output. + // We have shown something coming out of the sinon methods, but without eyeballing the Rust + // we can't be sure that the arguments will change the return value. + + await affirmAllerRetour(["foo", "bar"], op.sinonString.bind(op)); + await affirmAllerRetour([true, false], op.sinonBoolean.bind(op)); + await affirmAllerRetour([["a", "b"], []], op.sinonSequence.bind(op), (a, b) => + Assert.deepEqual(a, b) + ); + + // Optionals + await affirmAllerRetour(["0", "1"], op.sinonNull.bind(op)); + await affirmAllerRetour([0, 1], op.sinonZero.bind(op)); + + // integers + await affirmAllerRetour([0, 1], op.sinonU8Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI8Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU16Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI16Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU32Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI32Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU64Dec.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI64Dec.bind(op)); + + await affirmAllerRetour([0, 1], op.sinonU8Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI8Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU16Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI16Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU32Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI32Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU64Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonI64Hex.bind(op)); + await affirmAllerRetour([0, 1], op.sinonU32Oct.bind(op)); + + // Floats + await affirmAllerRetour([0.0, 1.0], op.sinonF32.bind(op)); + await affirmAllerRetour([0.0, 1.0], op.sinonF64.bind(op)); + + // enums + await affirmAllerRetour( + [Enumeration.UN, Enumeration.DEUX, Enumeration.TROIS], + op.sinonEnum.bind(op) + ); + + // Testing defaulting properties in record types. + const defaultes = new OptionneurDictionnaire(); + const explicite = new OptionneurDictionnaire( + -8, + 8, + -16, + 0x10, + -32, + 32, + -64, + 64, + 4.0, + 8.0, + true, + "default", + [], + Enumeration.DEUX, + null + ); + + Assert.deepEqual(defaultes, explicite); + + // …and makes sure they travel across and back the FFI. + + await affirmAllerRetour( + [defaultes, explicite], + rt.identiqueOptionneurDictionnaire.bind(rt), + (a, b) => Assert.deepEqual(a, b) + ); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_sprites.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_sprites.js new file mode 100644 index 0000000000..3feb2fd34d --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_sprites.js @@ -0,0 +1,28 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const Sprites = ChromeUtils.importESModule( + "resource://gre/modules/RustSprites.sys.mjs" +); + +add_task(async function () { + Assert.ok(Sprites.Sprite); + + const sempty = await Sprites.Sprite.init(null); + Assert.deepEqual(await sempty.getPosition(), new Sprites.Point(0, 0)); + + const s = await Sprites.Sprite.init(new Sprites.Point(0, 1)); + Assert.deepEqual(await s.getPosition(), new Sprites.Point(0, 1)); + + s.moveTo(new Sprites.Point(1, 2)); + Assert.deepEqual(await s.getPosition(), new Sprites.Point(1, 2)); + + s.moveBy(new Sprites.Vector(-4, 2)); + Assert.deepEqual(await s.getPosition(), new Sprites.Point(-3, 4)); + + const srel = await Sprites.Sprite.newRelativeTo( + new Sprites.Point(0, 1), + new Sprites.Vector(1, 1.5) + ); + Assert.deepEqual(await srel.getPosition(), new Sprites.Point(1, 2.5)); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_todolist.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_todolist.js new file mode 100644 index 0000000000..dac26d2be1 --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_todolist.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { TodoList, TodoEntry, getDefaultList, setDefaultList } = + ChromeUtils.importESModule("resource://gre/modules/RustTodolist.sys.mjs"); + +add_task(async function () { + const todo = await TodoList.init(); + const entry = new TodoEntry("Write bindings for strings in records"); + + await todo.addItem("Write JS bindings"); + Assert.equal(await todo.getLast(), "Write JS bindings"); + + await todo.addItem("Write tests for bindings"); + Assert.equal(await todo.getLast(), "Write tests for bindings"); + + await todo.addEntry(entry); + Assert.equal(await todo.getLast(), "Write bindings for strings in records"); + Assert.equal( + (await todo.getLastEntry()).text, + "Write bindings for strings in records" + ); + Assert.ok((await todo.getLastEntry()).equals(entry)); + + await todo.addItem( + "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣" + ); + Assert.equal( + await todo.getLast(), + "Test Ünicode hàndling without an entry can't believe I didn't test this at first 🤣" + ); + + const entry2 = new TodoEntry( + "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣" + ); + await todo.addEntry(entry2); + Assert.equal( + (await todo.getLastEntry()).text, + "Test Ünicode hàndling in an entry can't believe I didn't test this at first 🤣" + ); + + const todo2 = await TodoList.init(); + Assert.notEqual(todo, todo2); + Assert.notStrictEqual(todo, todo2); + + Assert.strictEqual(await getDefaultList(), null); + + await setDefaultList(todo); + Assert.deepEqual( + await todo.getItems(), + await (await getDefaultList()).getItems() + ); + + todo2.makeDefault(); + Assert.deepEqual( + await todo2.getItems(), + await (await getDefaultList()).getItems() + ); + + await todo.addItem("Test liveness after being demoted from default"); + Assert.equal( + await todo.getLast(), + "Test liveness after being demoted from default" + ); + + todo2.addItem("Test shared state through local vs default reference"); + Assert.equal( + await (await getDefaultList()).getLast(), + "Test shared state through local vs default reference" + ); +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_type_checking.js b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_type_checking.js new file mode 100644 index 0000000000..bfeb07c82b --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_type_checking.js @@ -0,0 +1,123 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const Arithmetic = ChromeUtils.importESModule( + "resource://gre/modules/RustArithmetic.sys.mjs" +); +const Geometry = ChromeUtils.importESModule( + "resource://gre/modules/RustGeometry.sys.mjs" +); +const TodoList = ChromeUtils.importESModule( + "resource://gre/modules/RustTodolist.sys.mjs" +); +const Rondpoint = ChromeUtils.importESModule( + "resource://gre/modules/RustRondpoint.sys.mjs" +); +const { UniFFITypeError } = ChromeUtils.importESModule( + "resource://gre/modules/UniFFI.sys.mjs" +); + +add_task(async function testFunctionArguments() { + await Assert.rejects( + Arithmetic.add(2), + UniFFITypeError, + "add() call missing argument" + ); + Assert.throws( + () => new Geometry.Point(0.0), + UniFFITypeError, + "Point constructor missing argument" + ); +}); + +add_task(async function testObjectPointers() { + const todo = await TodoList.TodoList.init(); + const stringifier = await Rondpoint.Stringifier.init(); + await todo.getEntries(); // OK + todo[TodoList.UnitTestObjs.uniffiObjectPtr] = + stringifier[Rondpoint.UnitTestObjs.uniffiObjectPtr]; + + await Assert.rejects( + todo.getEntries(), // the pointer is incorrect, should throw + /Bad pointer type/, + "getEntries() with wrong pointer type" + ); +}); + +add_task(async function testEnumTypeCheck() { + await Assert.rejects( + Rondpoint.copieEnumeration("invalid"), // Not an integer value + /e:/, // Ensure exception message includes the argument name + "copieEnumeration() with non-Enumeration value should throw" + ); + await Assert.rejects( + Rondpoint.copieEnumeration(0), // Integer, but doesn't map to a variant + /e:/, // Ensure exception message includes the argument name + "copieEnumeration() with non-Enumeration value should throw" + ); + await Assert.rejects( + Rondpoint.copieEnumeration(4), // Integer, but doesn't map to a variant + /e:/, // Ensure exception message includes the argument name + "copieEnumeration() with non-Enumeration value should throw" + ); +}); + +add_task(async function testRecordTypeCheck() { + await Assert.rejects( + Geometry.gradient(123), // Not a Line object + UniFFITypeError, + "gradient with non-Line object should throw" + ); + + await Assert.rejects( + Geometry.gradient({ + start: { + coordX: 0.0, + coordY: 0.0, + }, + // missing the end field + }), + /ln.end/, // Ensure exception message includes the argument name + "gradient with Line object with missing end field should throw" + ); +}); + +add_task(async function testOptionTypeCheck() { + const optionneur = await Rondpoint.Optionneur.init(); + await Assert.rejects( + optionneur.sinonNull(0), + UniFFITypeError, + "sinonNull with non-string should throw" + ); +}); + +add_task(async function testSequenceTypeCheck() { + const todo = await TodoList.TodoList.init(); + await Assert.rejects( + todo.addEntries("not a list"), + UniFFITypeError, + "addEntries with non-list should throw" + ); + + await Assert.rejects( + todo.addEntries(["not TodoEntry"]), + /entries\[0]/, + "addEntries with non TodoEntry item should throw" + ); +}); + +add_task(async function testMapTypeCheck() { + await Assert.rejects( + Rondpoint.copieCarte("not a map"), + UniFFITypeError, + "copieCarte with a non-map should throw" + ); + + await Assert.rejects( + Rondpoint.copieCarte({ x: 1 }), + /c\[x]/, + "copieCarte with a wrong value type should throw" + ); + + // TODO: test key types once we implement https://bugzilla.mozilla.org/show_bug.cgi?id=1809459 +}); diff --git a/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/xpcshell.ini b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..87d2b43489 --- /dev/null +++ b/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/xpcshell.ini @@ -0,0 +1,9 @@ +[test_arithmetic.js] +[test_callbacks.js] +[test_geometry.js] +[test_rondpoint.js] +[test_sprites.js] +[test_todolist.js] +[test_type_checking.js] +[test_custom_types.js] +[test_external_types.js] |