diff options
author | 2022-12-28 00:51:22 -0800 | |
---|---|---|
committer | 2022-12-28 00:51:22 -0800 | |
commit | c0dd2841362b67fdb5ede262b19688004a4eb9a4 (patch) | |
tree | a3cd6b353c25c30d66489de61b394af7d5568fed /test/bun.js/ffi.test.js | |
parent | 504972fa5deb92f2d0510d42f11b085351915a32 (diff) | |
download | bun-c0dd2841362b67fdb5ede262b19688004a4eb9a4.tar.gz bun-c0dd2841362b67fdb5ede262b19688004a4eb9a4.tar.zst bun-c0dd2841362b67fdb5ede262b19688004a4eb9a4.zip |
Upgrade to latest Zig (#1610)
* @min and @max
* builtins and some trivial ones
* Most of them
* more
* more!
* More Progress
* wip
* Update tagged_pointer.zig
* Update http_client_async.zig
* Most of the iterable dir changes
* alright
* Remove usages of deprecated formatters
* :camera:
* fmt
* Update shimmer.zig
* wip
* wip
* wip
* progress
* more
* Latest
* stuck on error
* latest
* workaround stage2
* wip
* Update string_immutable.zig
* wip
* Migrate `Dirent` and `require("fs')` to use JSC<>Zig bindings
* Fix build errors
* Fixup most of the test failures
* Fix `make headers`
* Fix "outside package path" error
* Fixup aligned alloc
* Add missing file
* linux
* More linux fixes
* use latest peechy
* Fix transpiler test failure
* Forgot about these
* Fixup test failure
* Update node-timers.test.ts
* [node:htt] Fix `undefined is not an object` error
Fixes https://github.com/oven-sh/bun/issues/1618
* Update http.exports.js
* Make this test less flaky
* fix hashes
* Fix hex formatting and zls issues
* Download zig version
* Update Dockerfile
* Update Dockerfile
* Update uws
* Update Dockerfile
* Set llvm version
* Update README.md
* Update uws
* Update Dockerfile
* Update io_linux.zig
* Update bun.zig
* Log output
* workaround strange @cInclude error
* Make ffi tests better
* Don't use cImport
* Update c.zig
* Update c-bindings.cpp
* call setOutputDir
* Update Dockerfile
* Use a longer name
* latest
* Update serve.test.ts
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Veikka Tuominen <git@vexu.eu>
Diffstat (limited to 'test/bun.js/ffi.test.js')
-rw-r--r-- | test/bun.js/ffi.test.js | 507 |
1 files changed, 251 insertions, 256 deletions
diff --git a/test/bun.js/ffi.test.js b/test/bun.js/ffi.test.js index e3e858b1f..4adf67990 100644 --- a/test/bun.js/ffi.test.js +++ b/test/bun.js/ffi.test.js @@ -1,4 +1,4 @@ -import { expect, it } from "bun:test"; +import { afterAll, describe, expect, it } from "bun:test"; // import { CFunction, @@ -310,186 +310,191 @@ function getTypes(fast) { } function ffiRunner(fast) { - const types = getTypes(fast); - const { - symbols: { - returns_true, - returns_false, - return_a_function_ptr_to_function_that_returns_true, - returns_42_char, - returns_42_float, - returns_42_double, - returns_42_uint8_t, - returns_neg_42_int8_t, - returns_42_uint16_t, - returns_42_uint32_t, - returns_42_uint64_t, - returns_neg_42_int16_t, - returns_neg_42_int32_t, - returns_neg_42_int64_t, - identity_char, - identity_float, - identity_bool, - identity_double, - identity_int8_t, - identity_int16_t, - identity_int32_t, - identity_int64_t, - identity_uint8_t, - identity_uint16_t, - identity_uint32_t, - identity_uint64_t, - add_char, - add_float, - add_double, - add_int8_t, - add_int16_t, - add_int32_t, - add_int64_t, - add_uint8_t, - add_uint16_t, - identity_ptr, - add_uint32_t, - add_uint64_t, - is_null, - does_pointer_equal_42_as_int32_t, - ptr_should_point_to_42_as_int32_t, - cb_identity_true, - cb_identity_false, - cb_identity_42_char, - cb_identity_42_float, - cb_identity_42_double, - cb_identity_42_uint8_t, - cb_identity_neg_42_int8_t, - cb_identity_42_uint16_t, - cb_identity_42_uint32_t, - cb_identity_42_uint64_t, - cb_identity_neg_42_int16_t, - cb_identity_neg_42_int32_t, - cb_identity_neg_42_int64_t, - getDeallocatorCalledCount, - getDeallocatorCallback, - getDeallocatorBuffer, - }, - close, - } = dlopen("/tmp/bun-ffi-test.dylib", types); - - Bun.gc(true); - expect(returns_true()).toBe(true); - Bun.gc(true); - expect(returns_false()).toBe(false); - - expect(returns_42_char()).toBe(42); - if (fast) expect(returns_42_uint64_t().valueOf()).toBe(42); - else expect(returns_42_uint64_t().valueOf()).toBe(42n); - Bun.gc(true); - expect(Math.fround(returns_42_float())).toBe(Math.fround(42.41999804973602)); - expect(returns_42_double()).toBe(42.42); - expect(returns_42_uint8_t()).toBe(42); - expect(returns_neg_42_int8_t()).toBe(-42); - expect(returns_42_uint16_t()).toBe(42); - expect(returns_42_uint32_t()).toBe(42); - if (fast) expect(returns_42_uint64_t()).toBe(42); - else expect(returns_42_uint64_t()).toBe(42n); - expect(returns_neg_42_int16_t()).toBe(-42); - expect(returns_neg_42_int32_t()).toBe(-42); - expect(identity_int32_t(10)).toBe(10); - Bun.gc(true); - if (fast) expect(returns_neg_42_int64_t()).toBe(-42); - else expect(returns_neg_42_int64_t()).toBe(-42n); - - expect(identity_char(10)).toBe(10); - - expect(identity_float(10.199999809265137)).toBe(10.199999809265137); - - expect(identity_bool(true)).toBe(true); - - expect(identity_bool(false)).toBe(false); - expect(identity_double(10.100000000000364)).toBe(10.100000000000364); - - expect(identity_int8_t(10)).toBe(10); - expect(identity_int16_t(10)).toBe(10); - - if (fast) expect(identity_int64_t(10)).toBe(10); - else expect(identity_int64_t(10)).toBe(10n); - expect(identity_uint8_t(10)).toBe(10); - expect(identity_uint16_t(10)).toBe(10); - expect(identity_uint32_t(10)).toBe(10); - if (fast) expect(identity_uint64_t(10)).toBe(10); - else expect(identity_uint64_t(10)).toBe(10n); - Bun.gc(true); - var bigArray = new BigUint64Array(8); - new Uint8Array(bigArray.buffer).fill(255); - var bigIntArray = new BigInt64Array(bigArray.buffer); - expect(identity_uint64_t(bigArray[0])).toBe(bigArray[0]); - expect(identity_uint64_t(bigArray[0] - BigInt(1))).toBe( - bigArray[0] - BigInt(1), - ); - if (fast) { - expect(add_uint64_t(BigInt(-1) * bigArray[0], bigArray[0])).toBe(0); - expect( - add_uint64_t(BigInt(-1) * bigArray[0] + BigInt(10), bigArray[0]), - ).toBe(10); - } else { - expect(add_uint64_t(BigInt(-1) * bigArray[0], bigArray[0])).toBe(0n); - expect( - add_uint64_t(BigInt(-1) * bigArray[0] + BigInt(10), bigArray[0]), - ).toBe(10n); - } - if (fast) { - expect(identity_uint64_t(0)).toBe(0); - expect(identity_uint64_t(100)).toBe(100); - expect(identity_uint64_t(BigInt(100))).toBe(100); - - expect(identity_int64_t(bigIntArray[0])).toBe(-1); - expect(identity_int64_t(bigIntArray[0] - BigInt(1))).toBe(-2); - } else { - expect(identity_uint64_t(0)).toBe(0n); - expect(identity_uint64_t(100)).toBe(100n); - expect(identity_uint64_t(BigInt(100))).toBe(100n); - - expect(identity_int64_t(bigIntArray[0])).toBe(bigIntArray[0]); - expect(identity_int64_t(bigIntArray[0] - BigInt(1))).toBe( - bigIntArray[0] - BigInt(1), - ); - } - Bun.gc(true); - expect(add_char.native(1, 1)).toBe(2); - - expect(add_float(2.4, 2.8)).toBe(Math.fround(5.2)); - expect(add_double(4.2, 0.1)).toBe(4.3); - expect(add_int8_t(1, 1)).toBe(2); - expect(add_int16_t(1, 1)).toBe(2); - expect(add_int32_t(1, 1)).toBe(2); - if (fast) expect(add_int64_t(1, 1)).toBe(2); - else expect(add_int64_t(1n, 1n)).toBe(2n); - expect(add_uint8_t(1, 1)).toBe(2); - expect(add_uint16_t(1, 1)).toBe(2); - expect(add_uint32_t(1, 1)).toBe(2); - Bun.gc(true); - expect(is_null(null)).toBe(true); - const cptr = ptr_should_point_to_42_as_int32_t(); - expect(cptr != 0).toBe(true); - expect(typeof cptr === "number").toBe(true); - expect(does_pointer_equal_42_as_int32_t(cptr)).toBe(true); - const buffer = toBuffer(cptr, 0, 4); - expect(buffer.readInt32(0)).toBe(42); - expect(new DataView(toArrayBuffer(cptr, 0, 4), 0, 4).getInt32(0, true)).toBe( - 42, - ); - expect(ptr(buffer)).toBe(cptr); - expect(new CString(cptr, 0, 1).toString()).toBe("*"); - expect(identity_ptr(cptr)).toBe(cptr); - const second_ptr = ptr(new Buffer(8)); - expect(identity_ptr(second_ptr)).toBe(second_ptr); - - var myCFunction = new CFunction({ - ptr: return_a_function_ptr_to_function_that_returns_true(), - returns: "bool", - }); - expect(myCFunction()).toBe(true); + describe("FFI runner" + (fast ? " (fast int)" : ""), () => { + const types = getTypes(fast); + const { + symbols: { + returns_true, + returns_false, + return_a_function_ptr_to_function_that_returns_true, + returns_42_char, + returns_42_float, + returns_42_double, + returns_42_uint8_t, + returns_neg_42_int8_t, + returns_42_uint16_t, + returns_42_uint32_t, + returns_42_uint64_t, + returns_neg_42_int16_t, + returns_neg_42_int32_t, + returns_neg_42_int64_t, + identity_char, + identity_float, + identity_bool, + identity_double, + identity_int8_t, + identity_int16_t, + identity_int32_t, + identity_int64_t, + identity_uint8_t, + identity_uint16_t, + identity_uint32_t, + identity_uint64_t, + add_char, + add_float, + add_double, + add_int8_t, + add_int16_t, + add_int32_t, + add_int64_t, + add_uint8_t, + add_uint16_t, + identity_ptr, + add_uint32_t, + add_uint64_t, + is_null, + does_pointer_equal_42_as_int32_t, + ptr_should_point_to_42_as_int32_t, + cb_identity_true, + cb_identity_false, + cb_identity_42_char, + cb_identity_42_float, + cb_identity_42_double, + cb_identity_42_uint8_t, + cb_identity_neg_42_int8_t, + cb_identity_42_uint16_t, + cb_identity_42_uint32_t, + cb_identity_42_uint64_t, + cb_identity_neg_42_int16_t, + cb_identity_neg_42_int32_t, + cb_identity_neg_42_int64_t, + getDeallocatorCalledCount, + getDeallocatorCallback, + getDeallocatorBuffer, + }, + close, + } = dlopen("/tmp/bun-ffi-test.dylib", types); + it("primitives", () => { + Bun.gc(true); + expect(returns_true()).toBe(true); + Bun.gc(true); + expect(returns_false()).toBe(false); + + expect(returns_42_char()).toBe(42); + if (fast) expect(returns_42_uint64_t().valueOf()).toBe(42); + else expect(returns_42_uint64_t().valueOf()).toBe(42n); + Bun.gc(true); + expect(Math.fround(returns_42_float())).toBe( + Math.fround(42.41999804973602), + ); + expect(returns_42_double()).toBe(42.42); + expect(returns_42_uint8_t()).toBe(42); + expect(returns_neg_42_int8_t()).toBe(-42); + expect(returns_42_uint16_t()).toBe(42); + expect(returns_42_uint32_t()).toBe(42); + if (fast) expect(returns_42_uint64_t()).toBe(42); + else expect(returns_42_uint64_t()).toBe(42n); + expect(returns_neg_42_int16_t()).toBe(-42); + expect(returns_neg_42_int32_t()).toBe(-42); + expect(identity_int32_t(10)).toBe(10); + Bun.gc(true); + if (fast) expect(returns_neg_42_int64_t()).toBe(-42); + else expect(returns_neg_42_int64_t()).toBe(-42n); + + expect(identity_char(10)).toBe(10); + + expect(identity_float(10.199999809265137)).toBe(10.199999809265137); + + expect(identity_bool(true)).toBe(true); + + expect(identity_bool(false)).toBe(false); + expect(identity_double(10.100000000000364)).toBe(10.100000000000364); + + expect(identity_int8_t(10)).toBe(10); + expect(identity_int16_t(10)).toBe(10); + + if (fast) expect(identity_int64_t(10)).toBe(10); + else expect(identity_int64_t(10)).toBe(10n); + expect(identity_uint8_t(10)).toBe(10); + expect(identity_uint16_t(10)).toBe(10); + expect(identity_uint32_t(10)).toBe(10); + if (fast) expect(identity_uint64_t(10)).toBe(10); + else expect(identity_uint64_t(10)).toBe(10n); + Bun.gc(true); + var bigArray = new BigUint64Array(8); + new Uint8Array(bigArray.buffer).fill(255); + var bigIntArray = new BigInt64Array(bigArray.buffer); + expect(identity_uint64_t(bigArray[0])).toBe(bigArray[0]); + expect(identity_uint64_t(bigArray[0] - BigInt(1))).toBe( + bigArray[0] - BigInt(1), + ); + if (fast) { + expect(add_uint64_t(BigInt(-1) * bigArray[0], bigArray[0])).toBe(0); + expect( + add_uint64_t(BigInt(-1) * bigArray[0] + BigInt(10), bigArray[0]), + ).toBe(10); + } else { + expect(add_uint64_t(BigInt(-1) * bigArray[0], bigArray[0])).toBe(0n); + expect( + add_uint64_t(BigInt(-1) * bigArray[0] + BigInt(10), bigArray[0]), + ).toBe(10n); + } + if (fast) { + expect(identity_uint64_t(0)).toBe(0); + expect(identity_uint64_t(100)).toBe(100); + expect(identity_uint64_t(BigInt(100))).toBe(100); + + expect(identity_int64_t(bigIntArray[0])).toBe(-1); + expect(identity_int64_t(bigIntArray[0] - BigInt(1))).toBe(-2); + } else { + expect(identity_uint64_t(0)).toBe(0n); + expect(identity_uint64_t(100)).toBe(100n); + expect(identity_uint64_t(BigInt(100))).toBe(100n); + + expect(identity_int64_t(bigIntArray[0])).toBe(bigIntArray[0]); + expect(identity_int64_t(bigIntArray[0] - BigInt(1))).toBe( + bigIntArray[0] - BigInt(1), + ); + } + Bun.gc(true); + expect(add_char.native(1, 1)).toBe(2); + + expect(add_float(2.4, 2.8)).toBe(Math.fround(5.2)); + expect(add_double(4.2, 0.1)).toBe(4.3); + expect(add_int8_t(1, 1)).toBe(2); + expect(add_int16_t(1, 1)).toBe(2); + expect(add_int32_t(1, 1)).toBe(2); + if (fast) expect(add_int64_t(1, 1)).toBe(2); + else expect(add_int64_t(1n, 1n)).toBe(2n); + expect(add_uint8_t(1, 1)).toBe(2); + expect(add_uint16_t(1, 1)).toBe(2); + expect(add_uint32_t(1, 1)).toBe(2); + Bun.gc(true); + expect(is_null(null)).toBe(true); + const cptr = ptr_should_point_to_42_as_int32_t(); + expect(cptr != 0).toBe(true); + expect(typeof cptr === "number").toBe(true); + expect(does_pointer_equal_42_as_int32_t(cptr)).toBe(true); + const buffer = toBuffer(cptr, 0, 4); + expect(buffer.readInt32(0)).toBe(42); + expect( + new DataView(toArrayBuffer(cptr, 0, 4), 0, 4).getInt32(0, true), + ).toBe(42); + expect(ptr(buffer)).toBe(cptr); + expect(new CString(cptr, 0, 1).toString()).toBe("*"); + expect(identity_ptr(cptr)).toBe(cptr); + const second_ptr = ptr(new Buffer(8)); + expect(identity_ptr(second_ptr)).toBe(second_ptr); + }); + + it("CFunction", () => { + var myCFunction = new CFunction({ + ptr: return_a_function_ptr_to_function_that_returns_true(), + returns: "bool", + }); + expect(myCFunction()).toBe(true); + }); - { const typeMap = { int8_t: -8, int16_t: -16, @@ -505,25 +510,7 @@ function ffiRunner(fast) { "void*": null, }; - // Return types, 1 argument - for (let [returnName, returnValue] of Object.entries(typeMap)) { - var roundtripFunction = new CFunction({ - ptr: new JSCallback( - (input) => { - return input; - }, - { - returns: returnName, - args: [returnName], - }, - ).ptr, - returns: returnName, - args: [returnName], - }); - expect(roundtripFunction(returnValue)).toBe(returnValue); - } - - { + it("JSCallback", () => { var toClose = new JSCallback( (input) => { return input; @@ -536,65 +523,72 @@ function ffiRunner(fast) { expect(toClose.ptr > 0).toBe(true); toClose.close(); expect(toClose.ptr === null).toBe(true); - } - - // Return types, no args - for (let [name, value] of Object.entries(typeMap)) { - var roundtripFunction = new CFunction({ - ptr: new JSCallback(() => value, { - returns: name, - }).ptr, - returns: name, - }); - expect(roundtripFunction()).toBe(value); - } - - // 1 arg, threadsafe - for (let [name, value] of Object.entries(typeMap)) { - var roundtripFunction = new CFunction({ - ptr: new JSCallback( - (arg1) => { - expect(arg1).toBe(value); - }, - { + }); + + describe("callbacks", () => { + // Return types, 1 argument + for (let [returnName, returnValue] of Object.entries(typeMap)) { + it("fn(" + returnName + ") " + returnName, () => { + var roundtripFunction = new CFunction({ + ptr: new JSCallback( + (input) => { + return input; + }, + { + returns: returnName, + args: [returnName], + }, + ).ptr, + returns: returnName, + args: [returnName], + }); + expect(roundtripFunction(returnValue)).toBe(returnValue); + }); + } + // Return types, no args + for (let [name, value] of Object.entries(typeMap)) { + it("fn() " + name, () => { + var roundtripFunction = new CFunction({ + ptr: new JSCallback(() => value, { + returns: name, + }).ptr, + returns: name, + }); + expect(roundtripFunction()).toBe(value); + }); + } + }); + + describe("threadsafe callback", (done) => { + // 1 arg, threadsafe + for (let [name, value] of Object.entries(typeMap)) { + it("fn(" + name + ") " + name, async () => { + const cb = new JSCallback( + (arg1) => { + expect(arg1).toBe(value); + }, + { + args: [name], + threadsafe: true, + }, + ); + var roundtripFunction = new CFunction({ + ptr: cb.ptr, + returns: "void", args: [name], - threadsafe: true, - }, - ).ptr, - returns: "void", - args: [name], - }); - roundtripFunction(value); - } - } - - // check deallocator is called - - // for (let constructor of [toArrayBuffer, toBuffer]) { - // Bun.gc(true); - - // var bufferPtr = getDeallocatorBuffer(); - - // for (let i = 0; i < 100; i++) { - // // callback, no userData - // constructor(bufferPtr, 0, 128, getDeallocatorCallback()); - - // // callback, userData; - // constructor(bufferPtr, 0, 128, bufferPtr, getDeallocatorCallback()); - // } - - // Bun.gc(true); - // expect(getDeallocatorCalledCount() >= 190).toBe(true); - // Bun.gc(true); - // } - close(); + }); + roundtripFunction(value); + await 1; + }); + } + }); + + afterAll(() => { + close(); + }); + }); } -// TODO: There is a crash when dlopen() two times the same library in quick succession -// it("run ffi fast", () => { -// ffiRunner(true); -// }); - it("read", () => { const buffer = new BigInt64Array(16); const dataView = new DataView(buffer.buffer); @@ -629,6 +623,7 @@ it("read", () => { } }); -it("run ffi", () => { +describe("run ffi", () => { ffiRunner(false); + ffiRunner(true); }); |