1
0
Fork 0
firefox/toolkit/components/uniffi-bindgen-gecko-js/fixtures/tests/xpcshell/test_rondpoint.js
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

332 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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({
un: Enumeration.DEUX,
deux: true,
petitNombre: 0,
grosNombre: 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({
petitNombre: n,
courtNombre: n,
nombreSimple: n,
grosNombre: n,
})
),
rt.identiqueNombresSignes.bind(rt),
(a, b) => Assert.deepEqual(a, b)
);
await affirmAllerRetour(
[0, 1].map(
n =>
new DictionnaireNombres({
petitNombre: n,
courtNombre: n,
nombreSimple: n,
grosNombre: 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)
);
});