test: move common.onGC to individual module

Incrementally making `require('../common')` less of a monolith.
Move the `common.onGC()` utility to a separate standalone module
that is only imported when it's actually needed.

PR-URL: https://github.com/nodejs/node/pull/22446
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Weijia Wang <starkwang@126.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
James M Snell 2018-08-21 13:38:59 -07:00
parent 3579ec4171
commit d495e40bf7
No known key found for this signature in database
GPG Key ID: 7341B15C070877AC
11 changed files with 81 additions and 57 deletions

View File

@ -296,21 +296,6 @@ otherwise.
### noWarnCode
See `common.expectWarning()` for usage.
### onGC(target, listener)
* `target` [&lt;Object>]
* `listener` [&lt;Object>]
* `ongc` [&lt;Function>]
Installs a GC listener for the collection of `target`.
This uses `async_hooks` for GC tracking. This means that it enables
`async_hooks` tracking, which may affect the test functionality. It also
means that between a `global.gc()` call and the listener being invoked
a full `setImmediate()` invocation passes.
`listener` is an object to make it easier to use a closure; the target object
should not be in scope when `listener.ongc()` is created.
### opensslCli
* [&lt;boolean>]
@ -759,6 +744,34 @@ via `NODE_TEST_*` environment variables. For example, to configure
`internet.addresses.INET_HOST`, set the environment
variable `NODE_TEST_INET_HOST` to a specified host.
## ongc Module
The `ongc` module allows a garbage collection listener to be installed. The
module exports a single `onGC()` function.
```js
require('../common');
const onGC = require('../common/ongc');
onGC({}, { ongc() { console.log('collected'); } });
```
### onGC(target, listener)
* `target` [&lt;Object>]
* `listener` [&lt;Object>]
* `ongc` [&lt;Function>]
Installs a GC listener for the collection of `target`.
This uses `async_hooks` for GC tracking. This means that it enables
`async_hooks` tracking, which may affect the test functionality. It also
means that between a `global.gc()` call and the listener being invoked
a full `setImmediate()` invocation passes.
`listener` is an object to make it easier to use a closure; the target object
should not be in scope when `listener.ongc()` is created.
## tmpdir Module
The `tmpdir` module supports the use of a temporary directory for testing.

View File

@ -805,30 +805,3 @@ exports.isCPPSymbolsNotMapped = exports.isWindows ||
exports.isAIX ||
exports.isLinuxPPCBE ||
exports.isFreeBSD;
const gcTrackerMap = new WeakMap();
const gcTrackerTag = 'NODE_TEST_COMMON_GC_TRACKER';
exports.onGC = function(obj, gcListener) {
const async_hooks = require('async_hooks');
const onGcAsyncHook = async_hooks.createHook({
init: exports.mustCallAtLeast(function(id, type, trigger, resource) {
if (this.trackedId === undefined) {
assert.strictEqual(type, gcTrackerTag);
this.trackedId = id;
}
}),
destroy(id) {
assert.notStrictEqual(this.trackedId, -1);
if (id === this.trackedId) {
this.gcListener.ongc();
onGcAsyncHook.disable();
}
}
}).enable();
onGcAsyncHook.gcListener = gcListener;
gcTrackerMap.set(obj, new async_hooks.AsyncResource(gcTrackerTag));
obj = null;
};

32
test/common/ongc.js Normal file
View File

@ -0,0 +1,32 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const gcTrackerMap = new WeakMap();
const gcTrackerTag = 'NODE_TEST_COMMON_GC_TRACKER';
function onGC(obj, gcListener) {
const async_hooks = require('async_hooks');
const onGcAsyncHook = async_hooks.createHook({
init: common.mustCallAtLeast(function(id, type) {
if (this.trackedId === undefined) {
assert.strictEqual(type, gcTrackerTag);
this.trackedId = id;
}
}),
destroy(id) {
assert.notStrictEqual(this.trackedId, -1);
if (id === this.trackedId) {
this.gcListener.ongc();
onGcAsyncHook.disable();
}
}
}).enable();
onGcAsyncHook.gcListener = gcListener;
gcTrackerMap.set(obj, new async_hooks.AsyncResource(gcTrackerTag));
obj = null;
}
module.exports = onGC;

View File

@ -1,15 +1,14 @@
'use strict';
// Flags: --expose-gc
const common = require('../common');
const onGC = require('../common/ongc');
{
const gcListener = { ongc: common.mustCall() };
common.onGC({}, gcListener);
onGC({}, { ongc: common.mustCall() });
global.gc();
}
{
const gcListener = { ongc: common.mustNotCall() };
common.onGC(process, gcListener);
onGC(process, { ongc: common.mustNotCall() });
global.gc();
}

View File

@ -3,7 +3,8 @@
// just like test-gc-http-client.js,
// but aborting every connection that comes in.
const common = require('../common');
require('../common');
const onGC = require('../common/ongc');
function serverHandler(req, res) {
res.connection.destroy();
@ -36,7 +37,7 @@ function getall() {
}, cb).on('error', cb);
count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
})();
setImmediate(getall);

View File

@ -3,7 +3,8 @@
// just like test-gc-http-client.js,
// but with an on('error') handler that does nothing.
const common = require('../common');
require('../common');
const onGC = require('../common/ongc');
function serverHandler(req, res) {
req.resume();
@ -42,7 +43,7 @@ function getall() {
}, cb).on('error', onerror);
count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
})();
setImmediate(getall);

View File

@ -3,7 +3,8 @@
// just like test-gc-http-client.js,
// but with a timeout set
const common = require('../common');
require('../common');
const onGC = require('../common/ongc');
function serverHandler(req, res) {
setTimeout(function() {
@ -45,7 +46,7 @@ function getall() {
});
count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
})();
setImmediate(getall);

View File

@ -3,6 +3,7 @@
// just a simple http server and client.
const common = require('../common');
const onGC = require('../common/ongc');
function serverHandler(req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
@ -34,7 +35,7 @@ function getall() {
}, cb);
count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
setImmediate(getall);
}

View File

@ -3,7 +3,8 @@
// just like test-gc-http-client-timeout.js,
// but using a net server/client instead
const common = require('../common');
require('../common');
const onGC = require('../common/ongc');
function serverHandler(sock) {
sock.setTimeout(120000);
@ -44,7 +45,7 @@ function getall() {
});
count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
setImmediate(getall);
}

View File

@ -23,6 +23,7 @@
// Flags: --expose-gc
const common = require('../common');
const onGC = require('../common/ongc');
const assert = require('assert');
const net = require('net');
@ -36,7 +37,7 @@ const gcListener = { ongc() { collected = true; } };
{
const gcObject = {};
common.onGC(gcObject, gcListener);
onGC(gcObject, gcListener);
const sock = net.createConnection(
server.address().port,

View File

@ -26,6 +26,7 @@ const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const onGC = require('../common/ongc');
const assert = require('assert');
const tls = require('tls');
const fixtures = require('../common/fixtures');
@ -43,7 +44,7 @@ const gcListener = { ongc() { collected = true; } };
{
const gcObject = {};
common.onGC(gcObject, gcListener);
onGC(gcObject, gcListener);
const sock = tls.connect(
server.address().port,