Skip to content

Commit

Permalink
test: make WeakReference tests robust
Browse files Browse the repository at this point in the history
Previously we assume that the objects are GC'ed after one
global.gc() returns, which is not necessarily always the case. Use
gcUntil() to run GC multiple times if they are not GC'ed in the
first time around.

PR-URL: #49053
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Rafael Gonzaga <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
  • Loading branch information
joyeecheung authored and UlisesGascon committed Sep 10, 2023
1 parent 772496c commit ca9f801
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
21 changes: 16 additions & 5 deletions test/fixtures/snapshot/weak-reference-gc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@ const { WeakReference } = internalBinding('util');
const {
setDeserializeMainFunction
} = require('v8').startupSnapshot
const assert = require('assert');

let obj = { hello: 'world' };
const ref = new WeakReference(obj);
let gcCount = 0;
let maxGC = 10;

setDeserializeMainFunction(() => {
obj = null;
function run() {
globalThis.gc();

setImmediate(() => {
assert.strictEqual(ref.get(), undefined);
gcCount++;
if (ref.get() === undefined) {
return;
} else if (gcCount < maxGC) {
run();
} else {
throw new Error(`Reference is still around after ${maxGC} GC`);
}
});
}

setDeserializeMainFunction(() => {
obj = null;
run();
});
17 changes: 13 additions & 4 deletions test/parallel/test-domain-async-id-map-leak.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const isEnumerable = Function.call.bind(Object.prototype.propertyIsEnumerable);
// See: https://github.com/nodejs/node/issues/23862

let d = domain.create();
let resourceGCed = false; let domainGCed = false; let
emitterGCed = false;
d.run(() => {
const resource = new async_hooks.AsyncResource('TestResource');
const emitter = new EventEmitter();
Expand All @@ -30,10 +32,17 @@ d.run(() => {
// emitter → resource → async id ⇒ domain → emitter.
// Make sure that all of these objects are released:

onGC(resource, { ongc: common.mustCall() });
onGC(d, { ongc: common.mustCall() });
onGC(emitter, { ongc: common.mustCall() });
onGC(resource, { ongc: common.mustCall(() => { resourceGCed = true; }) });
onGC(d, { ongc: common.mustCall(() => { domainGCed = true; }) });
onGC(emitter, { ongc: common.mustCall(() => { emitterGCed = true; }) });
});

d = null;
global.gc();

async function main() {
await common.gcUntil(
'All objects garbage collected',
() => resourceGCed && domainGCed && emitterGCed);
}

main();
12 changes: 7 additions & 5 deletions test/parallel/test-internal-util-weakreference.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Flags: --expose-internals --expose-gc
'use strict';
require('../common');
const common = require('../common');
const assert = require('assert');
const { internalBinding } = require('internal/test/binding');
const { WeakReference } = internalBinding('util');
Expand All @@ -9,9 +9,11 @@ let obj = { hello: 'world' };
const ref = new WeakReference(obj);
assert.strictEqual(ref.get(), obj);

setImmediate(() => {
async function main() {
obj = null;
global.gc();
await common.gcUntil(
'Reference is garbage collected',
() => ref.get() === undefined);
}

assert.strictEqual(ref.get(), undefined);
});
main();

0 comments on commit ca9f801

Please sign in to comment.