Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a0be95e

Browse filesBrowse files
tannalRafaelGSS
authored andcommitted
test: merge ongc and gcutil into gc.js
PR-URL: #54355 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent e071651 commit a0be95e
Copy full SHA for a0be95e
Expand file treeCollapse file tree

32 files changed

+122
-101
lines changed
Open diff view settings
Collapse file

‎test/addons/cppgc-object/test.js‎

Copy file name to clipboardExpand all lines: test/addons/cppgc-object/test.js
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Flags: --expose-gc
44

55
const common = require('../../common');
6-
6+
const { gcUntil } = require('../../common/gc');
77
// Verify that addons can create GarbageCollected objects and
88
// have them traced properly.
99

@@ -35,7 +35,7 @@ setTimeout(async function() {
3535
for (let i = 0; i < count; ++i) {
3636
array[i] = new CppGCed();
3737
}
38-
await common.gcUntil(
38+
await gcUntil(
3939
'All old CppGCed are destroyed',
4040
() => states[kDestructCount] === count,
4141
);
@@ -44,7 +44,7 @@ setTimeout(async function() {
4444
array = null;
4545
globalThis.gc();
4646

47-
await common.gcUntil(
47+
await gcUntil(
4848
'All old CppGCed are destroyed',
4949
() => states[kDestructCount] === count * 2,
5050
);
Collapse file

‎test/async-hooks/test-async-local-storage-gcable.js‎

Copy file name to clipboardExpand all lines: test/async-hooks/test-async-local-storage-gcable.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
const common = require('../common');
88
const { AsyncLocalStorage } = require('async_hooks');
9-
const onGC = require('../common/ongc');
9+
const { onGC } = require('../common/gc');
1010

1111
let asyncLocalStorage = new AsyncLocalStorage();
1212

Collapse file

‎test/common/README.md‎

Copy file name to clipboardExpand all lines: test/common/README.md
+1-1Lines changed: 1 addition & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ module exports a single `onGC()` function.
982982

983983
```js
984984
require('../common');
985-
const onGC = require('../common/ongc');
985+
const { onGC } = require('../common/gc');
986986

987987
onGC({}, { ongc() { console.log('collected'); } });
988988
```
Collapse file

‎test/common/gc.js‎

Copy file name to clipboardExpand all lines: test/common/gc.js
+67-2Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,72 @@
11
'use strict';
22

33
const wait = require('timers/promises').setTimeout;
4+
const assert = require('assert');
5+
const common = require('../common');
6+
const gcTrackerMap = new WeakMap();
7+
const gcTrackerTag = 'NODE_TEST_COMMON_GC_TRACKER';
48

5-
// TODO(joyeecheung): merge ongc.js and gcUntil from common/index.js
6-
// into this.
9+
/**
10+
* Installs a garbage collection listener for the specified object.
11+
* Uses async_hooks for GC tracking, which may affect test functionality.
12+
* A full setImmediate() invocation passes between a global.gc() call and the listener being invoked.
13+
* @param {object} obj - The target object to track for garbage collection.
14+
* @param {object} gcListener - The listener object containing the ongc callback.
15+
* @param {Function} gcListener.ongc - The function to call when the target object is garbage collected.
16+
*/
17+
function onGC(obj, gcListener) {
18+
const async_hooks = require('async_hooks');
19+
20+
const onGcAsyncHook = async_hooks.createHook({
21+
init: common.mustCallAtLeast(function(id, type) {
22+
if (this.trackedId === undefined) {
23+
assert.strictEqual(type, gcTrackerTag);
24+
this.trackedId = id;
25+
}
26+
}),
27+
destroy(id) {
28+
assert.notStrictEqual(this.trackedId, -1);
29+
if (id === this.trackedId) {
30+
this.gcListener.ongc();
31+
onGcAsyncHook.disable();
32+
}
33+
},
34+
}).enable();
35+
onGcAsyncHook.gcListener = gcListener;
36+
37+
gcTrackerMap.set(obj, new async_hooks.AsyncResource(gcTrackerTag));
38+
obj = null;
39+
}
40+
41+
/**
42+
* Repeatedly triggers garbage collection until a specified condition is met or a maximum number of attempts is reached.
43+
* @param {string|Function} [name] - Optional name, used in the rejection message if the condition is not met.
44+
* @param {Function} condition - A function that returns true when the desired condition is met.
45+
* @returns {Promise} A promise that resolves when the condition is met, or rejects after 10 failed attempts.
46+
*/
47+
function gcUntil(name, condition) {
48+
if (typeof name === 'function') {
49+
condition = name;
50+
name = undefined;
51+
}
52+
return new Promise((resolve, reject) => {
53+
let count = 0;
54+
function gcAndCheck() {
55+
setImmediate(() => {
56+
count++;
57+
global.gc();
58+
if (condition()) {
59+
resolve();
60+
} else if (count < 10) {
61+
gcAndCheck();
62+
} else {
63+
reject(name === undefined ? undefined : 'Test ' + name + ' failed');
64+
}
65+
});
66+
}
67+
gcAndCheck();
68+
});
69+
}
770

871
// This function can be used to check if an object factor leaks or not,
972
// but it needs to be used with care:
@@ -124,4 +187,6 @@ module.exports = {
124187
checkIfCollectable,
125188
runAndBreathe,
126189
checkIfCollectableByCounting,
190+
onGC,
191+
gcUntil,
127192
};
Collapse file

‎test/common/index.js‎

Copy file name to clipboardExpand all lines: test/common/index.js
-25Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -851,30 +851,6 @@ function skipIfDumbTerminal() {
851851
}
852852
}
853853

854-
function gcUntil(name, condition) {
855-
if (typeof name === 'function') {
856-
condition = name;
857-
name = undefined;
858-
}
859-
return new Promise((resolve, reject) => {
860-
let count = 0;
861-
function gcAndCheck() {
862-
setImmediate(() => {
863-
count++;
864-
global.gc();
865-
if (condition()) {
866-
resolve();
867-
} else if (count < 10) {
868-
gcAndCheck();
869-
} else {
870-
reject(name === undefined ? undefined : 'Test ' + name + ' failed');
871-
}
872-
});
873-
}
874-
gcAndCheck();
875-
});
876-
}
877-
878854
function requireNoPackageJSONAbove(dir = __dirname) {
879855
let possiblePackage = path.join(dir, '..', 'package.json');
880856
let lastPackage = null;
@@ -985,7 +961,6 @@ const common = {
985961
expectsError,
986962
expectRequiredModule,
987963
expectWarning,
988-
gcUntil,
989964
getArrayBufferViews,
990965
getBufferSources,
991966
getCallSite,
Collapse file

‎test/common/ongc.js‎

Copy file name to clipboardExpand all lines: test/common/ongc.js
-32Lines changed: 0 additions & 32 deletions
This file was deleted.
Collapse file

‎test/js-native-api/6_object_wrap/test-object-wrap-ref.js‎

Copy file name to clipboardExpand all lines: test/js-native-api/6_object_wrap/test-object-wrap-ref.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
'use strict';
44
const common = require('../../common');
55
const addon = require(`./build/${common.buildType}/6_object_wrap`);
6+
const { gcUntil } = require('../../common/gc');
67

78
(function scope() {
89
addon.objectWrapDanglingReference({});
910
})();
1011

11-
common.gcUntil('object-wrap-ref', () => {
12+
gcUntil('object-wrap-ref', () => {
1213
return addon.objectWrapDanglingReferenceTest();
1314
});
Collapse file

‎test/js-native-api/7_factory_wrap/test.js‎

Copy file name to clipboardExpand all lines: test/js-native-api/7_factory_wrap/test.js
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
const common = require('../../common');
55
const assert = require('assert');
66
const test = require(`./build/${common.buildType}/7_factory_wrap`);
7+
const { gcUntil } = require('../../common/gc');
78

89
assert.strictEqual(test.finalizeCount, 0);
910
async function runGCTests() {
@@ -13,14 +14,14 @@ async function runGCTests() {
1314
assert.strictEqual(obj.plusOne(), 12);
1415
assert.strictEqual(obj.plusOne(), 13);
1516
})();
16-
await common.gcUntil('test 1', () => (test.finalizeCount === 1));
17+
await gcUntil('test 1', () => (test.finalizeCount === 1));
1718

1819
(() => {
1920
const obj2 = test.createObject(20);
2021
assert.strictEqual(obj2.plusOne(), 21);
2122
assert.strictEqual(obj2.plusOne(), 22);
2223
assert.strictEqual(obj2.plusOne(), 23);
2324
})();
24-
await common.gcUntil('test 2', () => (test.finalizeCount === 2));
25+
await gcUntil('test 2', () => (test.finalizeCount === 2));
2526
}
2627
runGCTests();
Collapse file

‎test/js-native-api/8_passing_wrapped/test.js‎

Copy file name to clipboardExpand all lines: test/js-native-api/8_passing_wrapped/test.js
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
const common = require('../../common');
55
const assert = require('assert');
66
const addon = require(`./build/${common.buildType}/8_passing_wrapped`);
7+
const { gcUntil } = require('../../common/gc');
78

89
async function runTest() {
910
let obj1 = addon.createObject(10);
@@ -14,7 +15,7 @@ async function runTest() {
1415
// Make sure the native destructor gets called.
1516
obj1 = null;
1617
obj2 = null;
17-
await common.gcUntil('8_passing_wrapped',
18-
() => (addon.finalizeCount() === 2));
18+
await gcUntil('8_passing_wrapped',
19+
() => (addon.finalizeCount() === 2));
1920
}
2021
runTest();
Collapse file

‎test/js-native-api/test_finalizer/test.js‎

Copy file name to clipboardExpand all lines: test/js-native-api/test_finalizer/test.js
+6-4Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ const common = require('../../common');
55
const test_finalizer = require(`./build/${common.buildType}/test_finalizer`);
66
const assert = require('assert');
77

8+
const { gcUntil } = require('../../common/gc');
9+
810
// The goal of this test is to show that we can run "pure" finalizers in the
9-
// current JS loop tick. Thus, we do not use common.gcUntil function works
11+
// current JS loop tick. Thus, we do not use gcUntil function works
1012
// asynchronously using micro tasks.
1113
// We use IIFE for the obj scope instead of {} to be compatible with
1214
// non-V8 JS engines that do not support scoped variables.
@@ -25,7 +27,7 @@ for (let i = 0; i < 10; ++i) {
2527
assert.strictEqual(test_finalizer.getFinalizerCallCount(), 1);
2628

2729
// The finalizer that access JS cannot run synchronously. They are run in the
28-
// next JS loop tick. Thus, we must use common.gcUntil.
30+
// next JS loop tick. Thus, we must use gcUntil.
2931
async function runAsyncTests() {
3032
// We do not use common.mustCall() because we want to see the finalizer
3133
// called in response to GC and not as a part of env destruction.
@@ -36,8 +38,8 @@ async function runAsyncTests() {
3638
const obj = {};
3739
test_finalizer.addFinalizerWithJS(obj, () => { js_is_called = true; });
3840
})();
39-
await common.gcUntil('ensure JS finalizer called',
40-
() => (test_finalizer.getFinalizerCallCount() === 2));
41+
await gcUntil('ensure JS finalizer called',
42+
() => (test_finalizer.getFinalizerCallCount() === 2));
4143
assert(js_is_called);
4244
}
4345
runAsyncTests();

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.