Skip to content

Commit

Permalink
Make tests work on all Node versions
Browse files Browse the repository at this point in the history
 - Make GC tests (arraybuffer, buffer) async, to account for different
   GC behavior with different versions of V8 and ChakraCore,
   similar to nodejs/node#13121
 - In test/index.js, use the --napi-modules and --expose-gc
   command-line flags automatically
  • Loading branch information
jasongin committed May 20, 2017
1 parent 16fc9a5 commit 3a6964e
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 72 deletions.
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
],
"dependencies": {},
"description": "Node.js API (N-API)",
"devDependencies": {
"node-gyp": "^3.6.0"
},
"devDependencies": {},
"directories": {},
"homepage": "https://github.com/nodejs/node-addon-api",
"license": "MIT",
Expand All @@ -31,7 +29,7 @@
},
"scripts": {
"pretest": "node-gyp rebuild -C test",
"test": "node --expose-gc test"
"test": "node test"
},
"version": "0.2.0"
"version": "0.2.1"
}
4 changes: 4 additions & 0 deletions test/arraybuffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ Value CreateExternalBuffer(const CallbackInfo& info) {
}

Value CreateExternalBufferWithFinalize(const CallbackInfo& info) {
finalizeCount = 0;

uint8_t* data = new uint8_t[testLength];

ArrayBuffer buffer = ArrayBuffer::New(
Expand All @@ -74,6 +76,8 @@ Value CreateExternalBufferWithFinalize(const CallbackInfo& info) {
}

Value CreateExternalBufferWithFinalizeHint(const CallbackInfo& info) {
finalizeCount = 0;

uint8_t* data = new uint8_t[testLength];

char* hint = nullptr;
Expand Down
61 changes: 39 additions & 22 deletions test/arraybuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,47 @@
const buildType = process.config.target_defaults.default_configuration;
const binding = require(`./build/${buildType}/binding.node`);
const assert = require('assert');
const testUtil = require('./testUtil');

let test = binding.arraybuffer.createBuffer();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
testUtil.runGCTests([
'Internal ArrayBuffer',
() => {
const test = binding.arraybuffer.createBuffer();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);

let test2 = test.slice(0);
binding.arraybuffer.checkBuffer(test2);
const test2 = test.slice(0);
binding.arraybuffer.checkBuffer(test2);
},

test = binding.arraybuffer.createExternalBuffer();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
'External ArrayBuffer',
() => {
const test = binding.arraybuffer.createExternalBuffer();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
},

test = binding.arraybuffer.createExternalBufferWithFinalize();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
assert.strictEqual(0, binding.arraybuffer.getFinalizeCount());
test = null;
global.gc();
assert.strictEqual(1, binding.arraybuffer.getFinalizeCount());
'External ArrayBuffer with finalizer',
() => {
const test = binding.arraybuffer.createExternalBufferWithFinalize();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
assert.strictEqual(0, binding.arraybuffer.getFinalizeCount());
},
() => {
global.gc();
assert.strictEqual(1, binding.arraybuffer.getFinalizeCount());
},

test = binding.arraybuffer.createExternalBufferWithFinalizeHint();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
assert.strictEqual(1, binding.arraybuffer.getFinalizeCount());
test = null;
global.gc();
assert.strictEqual(2, binding.arraybuffer.getFinalizeCount());
'External ArrayBuffer with finalizer hint',
() => {
const test = binding.arraybuffer.createExternalBufferWithFinalizeHint();
binding.arraybuffer.checkBuffer(test);
assert.ok(test instanceof ArrayBuffer);
assert.strictEqual(0, binding.arraybuffer.getFinalizeCount());
},
() => {
global.gc();
assert.strictEqual(1, binding.arraybuffer.getFinalizeCount());
},
]);
4 changes: 4 additions & 0 deletions test/buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ Value CreateExternalBuffer(const CallbackInfo& info) {
}

Value CreateExternalBufferWithFinalize(const CallbackInfo& info) {
finalizeCount = 0;

uint16_t* data = new uint16_t[testLength];

Buffer<uint16_t> buffer = Buffer<uint16_t>::New(
Expand All @@ -79,6 +81,8 @@ Value CreateExternalBufferWithFinalize(const CallbackInfo& info) {
}

Value CreateExternalBufferWithFinalizeHint(const CallbackInfo& info) {
finalizeCount = 0;

uint16_t* data = new uint16_t[testLength];

char* hint = nullptr;
Expand Down
72 changes: 46 additions & 26 deletions test/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,55 @@
const buildType = process.config.target_defaults.default_configuration;
const binding = require(`./build/${buildType}/binding.node`);
const assert = require('assert');
const testUtil = require('./testUtil');

let test = binding.buffer.createBuffer();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
testUtil.runGCTests([
'Internal Buffer',
() => {
const test = binding.buffer.createBuffer();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);

let test2 = Buffer.alloc(test.length);
test.copy(test2);
binding.buffer.checkBuffer(test2);
const test2 = Buffer.alloc(test.length);
test.copy(test2);
binding.buffer.checkBuffer(test2);
},

test = binding.buffer.createBufferCopy();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
'Buffer copy',
() => {
const test = binding.buffer.createBufferCopy();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
},

test = binding.buffer.createExternalBuffer();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
'External Buffer',
() => {
const test = binding.buffer.createExternalBuffer();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
},

test = binding.buffer.createExternalBufferWithFinalize();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
assert.strictEqual(0, binding.buffer.getFinalizeCount());
test = null;
global.gc();
assert.strictEqual(1, binding.buffer.getFinalizeCount());
'External Buffer with finalizer',
() => {
const test = binding.buffer.createExternalBufferWithFinalize();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
assert.strictEqual(0, binding.buffer.getFinalizeCount());
},
() => {
global.gc();
assert.strictEqual(1, binding.buffer.getFinalizeCount());
},

test = binding.buffer.createExternalBufferWithFinalizeHint();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
assert.strictEqual(1, binding.buffer.getFinalizeCount());
test = null;
global.gc();
assert.strictEqual(2, binding.buffer.getFinalizeCount());
'External Buffer with finalizer hint',
() => {
const test = binding.buffer.createExternalBufferWithFinalizeHint();
binding.buffer.checkBuffer(test);
assert.ok(test instanceof Buffer);
assert.strictEqual(0, binding.buffer.getFinalizeCount());
},
() => {
global.gc();
assert.strictEqual(1, binding.buffer.getFinalizeCount());
},
]);
42 changes: 23 additions & 19 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
'use strict';

if (typeof global.gc !== 'function') {
throw new Error('Tests require --expose-gc flag.')
}

let testModules = [
'arraybuffer',
'asyncworker',
'buffer',
'error',
'external',
'function',
'name',
'arraybuffer',
'asyncworker',
'buffer',
'error',
'external',
'function',
'name',
];

testModules.forEach(name => {
try {
require('./' + name);
}
catch (e) {
console.error(e);
}
});
if (typeof global.gc === 'function') {
// Requiring each module runs tests in the module.
testModules.forEach(name => {
require('./' + name);
});
} else {
// Make it easier to run with the correct (version-dependent) command-line args.
const args = [ '--expose-gc', __filename ];
if (require('../index').isNodeApiBuiltin) {
args.splice(0, 0, '--napi-modules');
}
const child = require('child_process').spawnSync(process.argv[0], args, {
stdio: 'inherit',
});
process.exitCode = child.status;
}
29 changes: 29 additions & 0 deletions test/testUtil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Run each test function in sequence,
// with an async delay and GC call between each.
function runGCTests(tests, i, title) {
if (!i) {
i = 0;
}

if (tests[i]) {
if (typeof tests[i] === 'string') {
title = tests[i];
runGCTests(tests, i + 1, title);
} else {
try {
tests[i]();
} catch (e) {
console.error('Test failed: ' + title);
throw e;
}
setImmediate(() => {
global.gc();
runGCTests(tests, i + 1, title);
});
}
}
}

module.exports = {
runGCTests,
};

0 comments on commit 3a6964e

Please sign in to comment.