Skip to content

Commit

Permalink
test: move common.onGC to individual module
Browse files Browse the repository at this point in the history
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: #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>
  • Loading branch information
jasnell authored and targos committed Sep 6, 2018
1 parent c04f1f3 commit c9c8b29
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 57 deletions.
43 changes: 28 additions & 15 deletions test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>]

Expand Down Expand Up @@ -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.
Expand Down
27 changes: 0 additions & 27 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 32 additions & 0 deletions test/common/ongc.js
Original file line number Diff line number Diff line change
@@ -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;
7 changes: 3 additions & 4 deletions test/parallel/test-common-gc.js
Original file line number Diff line number Diff line change
@@ -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();
}
5 changes: 3 additions & 2 deletions test/parallel/test-gc-http-client-connaborted.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -36,7 +37,7 @@ function getall() {
}, cb).on('error', cb);

count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
})();

setImmediate(getall);
Expand Down
5 changes: 3 additions & 2 deletions test/parallel/test-gc-http-client-onerror.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -42,7 +43,7 @@ function getall() {
}, cb).on('error', onerror);

count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
})();

setImmediate(getall);
Expand Down
5 changes: 3 additions & 2 deletions test/parallel/test-gc-http-client-timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -45,7 +46,7 @@ function getall() {
});

count++;
common.onGC(req, { ongc });
onGC(req, { ongc });
})();

setImmediate(getall);
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-gc-http-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
Expand Down Expand Up @@ -34,7 +35,7 @@ function getall() {
}, cb);

count++;
common.onGC(req, { ongc });
onGC(req, { ongc });

setImmediate(getall);
}
Expand Down
5 changes: 3 additions & 2 deletions test/parallel/test-gc-net-timeout.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -44,7 +45,7 @@ function getall() {
});

count++;
common.onGC(req, { ongc });
onGC(req, { ongc });

setImmediate(getall);
}
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-net-connect-memleak.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
// Flags: --expose-gc

const common = require('../common');
const onGC = require('../common/ongc');
const assert = require('assert');
const net = require('net');

Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-tls-connect-memleak.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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,
Expand Down

0 comments on commit c9c8b29

Please sign in to comment.