test: split FFI call and callback coverage · nodejs/node@017ff85 · GitHub
Skip to content

Commit 017ff85

Browse files
panvaaduh95
authored andcommitted
test: split FFI call and callback coverage
Isolate each callback abort scenario so timeouts identify the failing case. Consolidate callback GC coverage in the weakref test and disable core dumps for intentional aborts on POSIX. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: #66287 Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it>
1 parent aaaca48 commit 017ff85

10 files changed

Lines changed: 217 additions & 246 deletions
Lines changed: 45 additions & 0 deletions

‎test/ffi/ffi.status‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ prefix ffi
44

55
[$system==solaris] # Also applies to SmartOS
66
# Bundled libffi callbacks crash on SmartOS.
7-
test-ffi-calls: SKIP
7+
test-ffi-callback*: SKIP
88
test-ffi-shared-buffer: SKIP
99
test-ffi-weakref-calls: SKIP
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
const common = require('../common');
3+
common.skipIfFFIMissing();
4+
const { test } = require('node:test');
5+
const { assertAborts } = require('./ffi-callback-test-common');
6+
7+
test('ffi aborts on cross-thread callback invocation', () => {
8+
const workerSource = `
9+
const { workerData } = require('node:worker_threads');
10+
const ffi = require('node:ffi');
11+
const { fixtureSymbols, libraryPath } = require(${JSON.stringify(require.resolve('./ffi-test-common'))});
12+
const { functions } = ffi.dlopen(libraryPath, fixtureSymbols);
13+
functions.call_int_callback(workerData, 21);
14+
`;
15+
assertAborts(
16+
`'use strict';
17+
const { Worker } = require('node:worker_threads');
18+
const ffi = require('node:ffi');
19+
const { fixtureSymbols, libraryPath } = require(${JSON.stringify(require.resolve('./ffi-test-common'))});
20+
const { lib } = ffi.dlopen(libraryPath, fixtureSymbols);
21+
const callback = lib.registerCallback(
22+
{ arguments: ['i32'], return: 'i32' },
23+
(value) => value * 2,
24+
);
25+
new Worker(${JSON.stringify(workerSource)}, { eval: true, workerData: callback });`,
26+
/Callbacks can only be invoked on the system thread they were created on/,
27+
);
28+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
const common = require('../common');
3+
common.skipIfFFIMissing();
4+
const { test } = require('node:test');
5+
const { assertCallbackAborts } = require('./ffi-callback-test-common');
6+
7+
test('ffi aborts on fractional callback return values', () => {
8+
assertCallbackAborts('return 1.5;', /Callback returned invalid value for declared FFI type/);
9+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
const common = require('../common');
3+
common.skipIfFFIMissing();
4+
const { test } = require('node:test');
5+
const { assertCallbackAborts } = require('./ffi-callback-test-common');
6+
7+
test('ffi aborts on out-of-range callback return values', () => {
8+
assertCallbackAborts('return 2 ** 40;', /Callback returned invalid value for declared FFI type/);
9+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
const common = require('../common');
3+
common.skipIfFFIMissing();
4+
const { test } = require('node:test');
5+
const { assertCallbackAborts } = require('./ffi-callback-test-common');
6+
7+
test('ffi aborts when a callback returns a promise', () => {
8+
assertCallbackAborts('return Promise.resolve(1);', /Callbacks cannot return promises/);
9+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
const common = require('../common');
3+
common.skipIfFFIMissing();
4+
const { test } = require('node:test');
5+
const { assertCallbackAborts } = require('./ffi-callback-test-common');
6+
7+
test('ffi aborts when a callback throws', () => {
8+
assertCallbackAborts('throw new Error("boom");', /Callbacks cannot throw an exception/);
9+
});

‎test/ffi/test-ffi-callbacks.js‎

Lines changed: 84 additions & 0 deletions

0 commit comments

Comments
 (0)