Skip to content

Commit bb91879

Browse files
committed
test: Make N-API weak-ref GC tests asynchronous
One of the N-API weak-reference test cases already had to be made asynchronous to handle different behavior in a newer V8 version: #12864 When porting N-API to Node-ChakraCore, we found more of the test cases needed similar treatment: nodejs/node-chakracore#246 So to make thes tests more robust (and avoid having differences in the test code for Node-ChakraCore), I am refactoring the tests in this file to insert a `setImmedate()` callback before every call to `gc()` and assertions about the effects of the GC. PR-URL: #13121 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
1 parent 43e4efd commit bb91879

File tree

1 file changed

+99
-69
lines changed
  • test/addons-napi/test_reference

1 file changed

+99
-69
lines changed

test/addons-napi/test_reference/test.js

+99-69
Original file line numberDiff line numberDiff line change
@@ -11,80 +11,110 @@ const test_reference = require(`./build/${common.buildType}/test_reference`);
1111
// of a finalizer callback increments the finalizeCount property.
1212
assert.strictEqual(test_reference.finalizeCount, 0);
1313

14-
{
15-
// External value without a finalizer
16-
let value = test_reference.createExternal();
17-
assert.strictEqual(test_reference.finalizeCount, 0);
18-
assert.strictEqual(typeof value, 'object');
19-
test_reference.checkExternal(value);
20-
value = null;
21-
global.gc();
22-
assert.strictEqual(test_reference.finalizeCount, 0);
14+
// Run each test function in sequence,
15+
// with an async delay and GC call between each.
16+
function runTests(i, title, tests) {
17+
if (tests[i]) {
18+
if (typeof tests[i] === 'string') {
19+
title = tests[i];
20+
runTests(i + 1, title, tests);
21+
} else {
22+
try {
23+
tests[i]();
24+
} catch (e) {
25+
console.error('Test failed: ' + title);
26+
throw e;
27+
}
28+
setImmediate(() => {
29+
global.gc();
30+
runTests(i + 1, title, tests);
31+
});
32+
}
33+
}
2334
}
35+
runTests(0, undefined, [
2436

25-
{
26-
// External value with a finalizer
27-
let value = test_reference.createExternalWithFinalize();
28-
assert.strictEqual(test_reference.finalizeCount, 0);
29-
assert.strictEqual(typeof value, 'object');
30-
test_reference.checkExternal(value);
31-
value = null;
32-
global.gc();
33-
assert.strictEqual(test_reference.finalizeCount, 1);
34-
}
35-
36-
{
37-
// Strong reference
38-
let value = test_reference.createExternalWithFinalize();
39-
assert.strictEqual(test_reference.finalizeCount, 0);
40-
test_reference.createReference(value, 1);
41-
assert.strictEqual(test_reference.referenceValue, value);
42-
value = null;
43-
global.gc(); // Value should NOT be GC'd because there is a strong ref
44-
assert.strictEqual(test_reference.finalizeCount, 0);
45-
test_reference.deleteReference();
46-
global.gc(); // Value should be GC'd because the strong ref was deleted
47-
assert.strictEqual(test_reference.finalizeCount, 1);
48-
}
49-
50-
{
51-
// Strong reference, increment then decrement to weak reference
52-
let value = test_reference.createExternalWithFinalize();
53-
assert.strictEqual(test_reference.finalizeCount, 0);
54-
test_reference.createReference(value, 1);
55-
value = null;
56-
global.gc(); // Value should NOT be GC'd because there is a strong ref
57-
assert.strictEqual(test_reference.finalizeCount, 0);
37+
'External value without a finalizer',
38+
() => {
39+
const value = test_reference.createExternal();
40+
assert.strictEqual(test_reference.finalizeCount, 0);
41+
assert.strictEqual(typeof value, 'object');
42+
test_reference.checkExternal(value);
43+
},
44+
() => {
45+
assert.strictEqual(test_reference.finalizeCount, 0);
46+
},
5847

59-
assert.strictEqual(test_reference.incrementRefcount(), 2);
60-
global.gc(); // Value should NOT be GC'd because there is a strong ref
61-
assert.strictEqual(test_reference.finalizeCount, 0);
62-
63-
assert.strictEqual(test_reference.decrementRefcount(), 1);
64-
global.gc(); // Value should NOT be GC'd because there is a strong ref
65-
assert.strictEqual(test_reference.finalizeCount, 0);
48+
'External value with a finalizer',
49+
() => {
50+
const value = test_reference.createExternalWithFinalize();
51+
assert.strictEqual(test_reference.finalizeCount, 0);
52+
assert.strictEqual(typeof value, 'object');
53+
test_reference.checkExternal(value);
54+
},
55+
() => {
56+
assert.strictEqual(test_reference.finalizeCount, 1);
57+
},
6658

67-
assert.strictEqual(test_reference.decrementRefcount(), 0);
68-
global.gc(); // Value should be GC'd because the ref is now weak!
69-
assert.strictEqual(test_reference.finalizeCount, 1);
59+
'Weak reference',
60+
() => {
61+
const value = test_reference.createExternalWithFinalize();
62+
assert.strictEqual(test_reference.finalizeCount, 0);
63+
test_reference.createReference(value, 0);
64+
assert.strictEqual(test_reference.referenceValue, value);
65+
},
66+
() => {
67+
// Value should be GC'd because there is only a weak ref
68+
assert.strictEqual(test_reference.referenceValue, undefined);
69+
assert.strictEqual(test_reference.finalizeCount, 1);
70+
test_reference.deleteReference();
71+
},
7072

71-
test_reference.deleteReference();
72-
global.gc(); // Value was already GC'd
73-
assert.strictEqual(test_reference.finalizeCount, 1);
74-
}
73+
'Strong reference',
74+
() => {
75+
const value = test_reference.createExternalWithFinalize();
76+
assert.strictEqual(test_reference.finalizeCount, 0);
77+
test_reference.createReference(value, 1);
78+
assert.strictEqual(test_reference.referenceValue, value);
79+
},
80+
() => {
81+
// Value should NOT be GC'd because there is a strong ref
82+
assert.strictEqual(test_reference.finalizeCount, 0);
83+
test_reference.deleteReference();
84+
},
85+
() => {
86+
// Value should be GC'd because the strong ref was deleted
87+
assert.strictEqual(test_reference.finalizeCount, 1);
88+
},
7589

76-
{
77-
// Weak reference
78-
let value = test_reference.createExternalWithFinalize();
79-
assert.strictEqual(test_reference.finalizeCount, 0);
80-
test_reference.createReference(value, 0);
81-
assert.strictEqual(test_reference.referenceValue, value);
82-
value = null;
83-
setImmediate(common.mustCall(() => {
84-
// This test only works if gc() is called from an immediate callback.
85-
global.gc(); // Value should be GC'd because there is only a weak ref
86-
assert.strictEqual(test_reference.referenceValue, undefined);
90+
'Strong reference, increment then decrement to weak reference',
91+
() => {
92+
const value = test_reference.createExternalWithFinalize();
93+
assert.strictEqual(test_reference.finalizeCount, 0);
94+
test_reference.createReference(value, 1);
95+
},
96+
() => {
97+
// Value should NOT be GC'd because there is a strong ref
98+
assert.strictEqual(test_reference.finalizeCount, 0);
99+
assert.strictEqual(test_reference.incrementRefcount(), 2);
100+
},
101+
() => {
102+
// Value should NOT be GC'd because there is a strong ref
103+
assert.strictEqual(test_reference.finalizeCount, 0);
104+
assert.strictEqual(test_reference.decrementRefcount(), 1);
105+
},
106+
() => {
107+
// Value should NOT be GC'd because there is a strong ref
108+
assert.strictEqual(test_reference.finalizeCount, 0);
109+
assert.strictEqual(test_reference.decrementRefcount(), 0);
110+
},
111+
() => {
112+
// Value should be GC'd because the ref is now weak!
87113
assert.strictEqual(test_reference.finalizeCount, 1);
88114
test_reference.deleteReference();
89-
}));
90-
}
115+
},
116+
() => {
117+
// Value was already GC'd
118+
assert.strictEqual(test_reference.finalizeCount, 1);
119+
},
120+
]);

0 commit comments

Comments
 (0)