diff options
Diffstat (limited to 'toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js')
-rw-r--r-- | toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js b/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js new file mode 100644 index 0000000000..1490498684 --- /dev/null +++ b/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js @@ -0,0 +1,196 @@ +try { + // We might be running without privileges, in which case it's up to the + // harness to give us the 'ctypes' object. + var { ctypes } = ChromeUtils.importESModule( + "resource://gre/modules/ctypes.sys.mjs" + ); +} catch (e) {} + +var acquire, dispose, null_dispose, compare, dispose_64; + +function run_test() { + let library = open_ctypes_test_lib(); + + let start = library.declare( + "test_finalizer_start", + ctypes.default_abi, + ctypes.void_t, + ctypes.size_t + ); + let stop = library.declare( + "test_finalizer_stop", + ctypes.default_abi, + ctypes.void_t + ); + let tester = new ResourceTester(start, stop); + acquire = library.declare( + "test_finalizer_acq_size_t", + ctypes.default_abi, + ctypes.size_t, + ctypes.size_t + ); + dispose = library.declare( + "test_finalizer_rel_size_t", + ctypes.default_abi, + ctypes.void_t, + ctypes.size_t + ); + compare = library.declare( + "test_finalizer_cmp_size_t", + ctypes.default_abi, + ctypes.bool, + ctypes.size_t, + ctypes.size_t + ); + + dispose_64 = library.declare( + "test_finalizer_rel_int64_t", + ctypes.default_abi, + ctypes.void_t, + ctypes.int64_t + ); + + let type_afun = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ + ctypes.size_t, + ]).ptr; + + let null_dispose_maker = library.declare( + "test_finalizer_rel_null_function", + ctypes.default_abi, + type_afun + ); + null_dispose = null_dispose_maker(); + + tester.launch(10, test_double_dispose); + tester.launch(10, test_finalize_bad_construction); + tester.launch(10, test_null_dispose); + tester.launch(10, test_pass_disposed); + tester.launch(10, test_wrong_type); +} + +/** + * Testing construction of finalizers with wrong arguments. + */ +function test_finalize_bad_construction() { + // First argument does not match second + must_throw(function () { + ctypes.CDataFinalizer({}, dispose); + }); + must_throw(function () { + ctypes.CDataFinalizer(dispose, dispose); + }); + + // Not enough arguments + must_throw(function () { + ctypes.CDataFinalizer(dispose); + }, "TypeError: CDataFinalizer constructor takes two arguments"); + + // Too many arguments + must_throw(function () { + ctypes.CDataFinalizer(dispose, dispose, dispose); + }, "TypeError: CDataFinalizer constructor takes two arguments"); + + // Second argument is null + must_throw(function () { + ctypes.CDataFinalizer(dispose, null); + }, "TypeError: expected _a CData object_ of a function pointer type, got null"); + + // Second argument is undefined + must_throw(function () { + let a; + ctypes.CDataFinalizer(dispose, a); + }, "TypeError: expected _a CData object_ of a function pointer type, got undefined"); +} + +/** + * Test that forget/dispose can only take place once. + */ +function test_double_dispose() { + function test_one_combination(i, a, b) { + let v = ctypes.CDataFinalizer(acquire(i), dispose); + a(v); + must_throw(function () { + b(v); + }); + } + + let call_dispose = function (v) { + v.dispose(); + }; + let call_forget = function (v) { + v.forget(); + }; + + test_one_combination(0, call_dispose, call_dispose); + test_one_combination(1, call_dispose, call_forget); + test_one_combination(2, call_forget, call_dispose); + test_one_combination(3, call_forget, call_forget); +} + +/** + * Test that nothing (too) bad happens when the finalizer is NULL + */ +function test_null_dispose() { + let exception; + + exception = false; + try { + ctypes.CDataFinalizer(acquire(0), null_dispose); + } catch (x) { + exception = true; + } + Assert.ok(exception); +} + +/** + * Test that conversion of a disposed/forgotten CDataFinalizer to a C + * value fails nicely. + */ +function test_pass_disposed() { + let exception, v; + + exception = false; + v = ctypes.CDataFinalizer(acquire(0), dispose); + Assert.ok(compare(v, 0)); + v.forget(); + + try { + compare(v, 0); + } catch (x) { + exception = true; + } + Assert.ok(exception); + + exception = false; + v = ctypes.CDataFinalizer(acquire(0), dispose); + Assert.ok(compare(v, 0)); + v.dispose(); + + try { + compare(v, 0); + } catch (x) { + exception = true; + } + Assert.ok(exception); + + exception = false; + try { + ctypes.int32_t(ctypes.CDataFinalizer(v, dispose)); + } catch (x) { + exception = true; + } + Assert.ok(exception); +} + +function test_wrong_type() { + let int32_v = ctypes.int32_t(99); + let exception; + try { + ctypes.CDataFinalizer(int32_v, dispose_64); + } catch (x) { + exception = x; + } + + Assert.ok(!!exception); + Assert.equal(exception.constructor.name, "TypeError"); +} |