Skip to content

Commit

Permalink
enable unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Deepak Rajamohan committed Sep 23, 2021
1 parent 22a2f3c commit 5f3f131
Show file tree
Hide file tree
Showing 15 changed files with 452 additions and 14 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,9 @@
"dev:incremental": "node test",
"doc": "doxygen doc/Doxyfile",
"lint": "node tools/clang-format",
"lint:fix": "node tools/clang-format --fix"
"lint:fix": "node tools/clang-format --fix",
"preunit": "filter=\"$npm_config_filter\" node-gyp rebuild -C unit-test",
"unit": "filter=\"$npm_config_filter\" node unit-test/test"
},
"pre-commit": "lint",
"version": "4.1.0",
Expand Down
4 changes: 2 additions & 2 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ exports.mustNotCall = function(msg) {
};
};

exports.runTest = async function(test, buildType, buildPathRoot = process.env.REL_BUILD_PATH || '') {
exports.runTest = async function(test, buildType, buildPathRoot = process.env.BUILD_PATH || '') {
buildType = buildType || process.config.target_defaults.default_configuration || 'Release';

const bindings = [
Expand All @@ -91,7 +91,7 @@ exports.runTest = async function(test, buildType, buildPathRoot = process.env.RE
}
}

exports.runTestWithBindingPath = async function(test, buildType, buildPathRoot = process.env.REL_BUILD_PATH || '') {
exports.runTestWithBindingPath = async function(test, buildType, buildPathRoot = process.env.BUILD_PATH || '') {
buildType = buildType || process.config.target_defaults.default_configuration || 'Release';

const bindings = [
Expand Down
38 changes: 28 additions & 10 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,23 @@ if (typeof global.gc !== 'function') {

const fs = require('fs');
const path = require('path');
process.env.filter = require('../unit-test/matchModules').matchWildCards(process.env.filter);

let testModules = [];

const filterCondition = process.env.filter || '';
const filterConditionFiles = filterCondition.split(' ').length ? filterCondition.split(' ') : [filterCondition];


function checkFilterCondition(fileName, parsedFilepath) {
let result = false;

if (!filterConditionFiles.length) result = true;
if (filterConditionFiles.includes(parsedFilepath)) result = true;
if (filterConditionFiles.includes(fileName)) result = true;
return result;
}

// TODO(RaisinTen): Update this when the test filenames
// are changed into test_*.js.
function loadTestModules(currentDirectory = __dirname, pre = '') {
Expand All @@ -50,15 +64,19 @@ function loadTestModules(currentDirectory = __dirname, pre = '') {
return;
}
const absoluteFilepath = path.join(currentDirectory, file);
const parsedFilepath = path.parse(file);
const parsedPath = path.parse(currentDirectory);

if (fs.statSync(absoluteFilepath).isDirectory()) {
if (fs.existsSync(absoluteFilepath + '/index.js')) {
testModules.push(pre + file);
if (checkFilterCondition(parsedFilepath.name, parsedPath.base)) {
testModules.push(pre + file);
}
} else {
loadTestModules(absoluteFilepath, pre + file + '/');
}
} else {
const parsedFilepath = path.parse(file);
if (parsedFilepath.ext === '.js') {
if (parsedFilepath.ext === '.js' && checkFilterCondition(parsedFilepath.name, parsedPath.base)) {
testModules.push(pre + parsedFilepath.name);
}
}
Expand All @@ -69,7 +87,7 @@ loadTestModules();

process.config.target_defaults.default_configuration =
fs
.readdirSync(path.join(__dirname, 'build'))
.readdirSync(path.join(__dirname, process.env.REL_BUILD_PATH, 'build'))
.filter((item) => (item === 'Debug' || item === 'Release'))[0];

let napiVersion = Number(process.versions.napi);
Expand All @@ -87,7 +105,7 @@ if (napiVersion < 3) {
testModules.splice(testModules.indexOf('version_management'), 1);
}

if (napiVersion < 4) {
if (napiVersion < 4 && !filterConditionFiles.length) {
testModules.splice(testModules.indexOf('asyncprogressqueueworker'), 1);
testModules.splice(testModules.indexOf('asyncprogressworker'), 1);
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function_ctx'), 1);
Expand All @@ -98,30 +116,30 @@ if (napiVersion < 4) {
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function'), 1);
}

if (napiVersion < 5) {
if (napiVersion < 5 && !filterConditionFiles.length) {
testModules.splice(testModules.indexOf('date'), 1);
}

if (napiVersion < 6) {
if (napiVersion < 6 && !filterConditionFiles.length) {
testModules.splice(testModules.indexOf('addon'), 1);
testModules.splice(testModules.indexOf('addon_data'), 1);
testModules.splice(testModules.indexOf('bigint'), 1);
testModules.splice(testModules.indexOf('typedarray-bigint'), 1);
}

if (majorNodeVersion < 12) {
if (majorNodeVersion < 12 && !filterConditionFiles.length) {
testModules.splice(testModules.indexOf('objectwrap_worker_thread'), 1);
testModules.splice(testModules.indexOf('error_terminating_environment'), 1);
}

if (napiVersion < 8) {
if (napiVersion < 8 && !filterConditionFiles.length) {
testModules.splice(testModules.indexOf('object/object_freeze_seal'), 1);
}

(async function() {
console.log(`Testing with Node-API Version '${napiVersion}'.`);

console.log('Starting test suite\n');
console.log('Starting test suite\n', testModules);

// Requiring each module runs tests in the module.
for (const name of testModules) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = require('../common').runTest(test);

async function test(binding) {
const ctx = { };
const tsfn = new binding.threadsafe_function_ctx.TSFNWrap(ctx);
const tsfn = new binding.typed_threadsafe_function_ctx.TSFNWrap(ctx);
assert(tsfn.getContext() === ctx);
await tsfn.release();
}
3 changes: 3 additions & 0 deletions unit-test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
/build
/generated
27 changes: 27 additions & 0 deletions unit-test/binding-file-template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module.exports.generateFileContent = function(configs) {
const content = [];
const inits = [];
const exports = [];

for (let config of configs) {
inits.push(`Object Init${config.objectName}(Env env);`);
exports.push(`exports.Set(\"${config.propertyName}\", Init${config.objectName}(env));`);
}

content.push("#include \"napi.h\"");
content.push("using namespace Napi;");

//content.push("Object InitName(Env env);");
inits.forEach(init => content.push(init));

content.push("Object Init(Env env, Object exports) {");

//content.push("exports.Set(\"name\", InitName(env));");
exports.forEach(exp => content.push(exp));

content.push("return exports;");
content.push("}");
content.push("NODE_API_MODULE(addon, Init);");

return Promise.resolve(content.join('\r\n'));
}
64 changes: 64 additions & 0 deletions unit-test/binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
'target_defaults': {
'includes': ['common.gypi'],
'include_dirs': ['../test/common'],
'variables': {
'build_sources': [
"<!@(node -p \"require('./injectTestParams').filesToCompile()\")",
]
},
},
'targets': [
{
"target_name": "generateBindingCC",
"type": "none",
"actions": [ {
"action_name": "generateBindingCC",
"message": "Generating binding cc file",
"outputs": ["generated/binding.cc"],
"conditions": [
[ "'true'=='true'", {
"inputs": [""],
"action": [
"node",
"generate-binding-cc.js",
"<!@(node -p \"require('./injectTestParams').filesForBinding()\" )"
]
} ]
]
} ]
},
{
'target_name': 'binding',
'includes': ['../except.gypi'],
'sources': ['>@(build_sources)'],
'dependencies': [ 'generateBindingCC' ]
},
{
'target_name': 'binding_noexcept',
'includes': ['../noexcept.gypi'],
'sources': ['>@(build_sources)'],
'dependencies': [ 'generateBindingCC' ]
},
{
'target_name': 'binding_noexcept_maybe',
'includes': ['../noexcept.gypi'],
'sources': ['>@(build_sources)'],
'defines': ['NODE_ADDON_API_ENABLE_MAYBE']
},
{
'target_name': 'binding_swallowexcept',
'includes': ['../except.gypi'],
'sources': ['>@(build_sources)'],
'defines': ['NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS'],
'dependencies': [ 'generateBindingCC' ]
},
{
'target_name': 'binding_swallowexcept_noexcept',
'includes': ['../noexcept.gypi'],
'sources': ['>@(build_sources)'],
'defines': ['NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS'],
'dependencies': [ 'generateBindingCC' ]
},
],
}
21 changes: 21 additions & 0 deletions unit-test/common.gypi
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
'variables': {
'NAPI_VERSION%': "<!(node -p \"process.versions.napi\")",
'disable_deprecated': "<!(node -p \"process.env['npm_config_disable_deprecated']\")"
},
'conditions': [
['NAPI_VERSION!=""', { 'defines': ['NAPI_VERSION=<@(NAPI_VERSION)'] } ],
['disable_deprecated=="true"', {
'defines': ['NODE_ADDON_API_DISABLE_DEPRECATED']
}],
['OS=="mac"', {
'cflags+': ['-fvisibility=hidden'],
'xcode_settings': {
'OTHER_CFLAGS': ['-fvisibility=hidden']
}
}]
],
'include_dirs': ["<!(node -p \"require('../').include_dir\")", "./generated"],
'cflags': [ '-Werror', '-Wall', '-Wextra', '-Wpedantic', '-Wunused-parameter' ],
'cflags_cc': [ '-Werror', '-Wall', '-Wextra', '-Wpedantic', '-Wunused-parameter' ]
}
20 changes: 20 additions & 0 deletions unit-test/exceptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
'nouns': {
'constructor': 'constructor',
'threadsafe': 'threadSafe',
'objectwrap': 'objectWrap',
},
'exportNames': {
'AsyncWorkerPersistent': 'PersistentAsyncWorker',
},
'propertyNames': {
'async_worker_persistent': 'persistentasyncworker',
'objectwrap_constructor_exception':'objectwrapConstructorException',
},
'skipBinding': [
'global_object_delete_property',
'global_object_get_property',
'global_object_has_own_property',
'global_object_set_property',
]
};
41 changes: 41 additions & 0 deletions unit-test/generate-binding-cc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const fs = require('fs');
const path = require('path');
const listOfTestModules = require('./listOfTestModules');
const exceptions = require('./exceptions');
const generateFileContent = require('./binding-file-template').generateFileContent;

const buildDirs = listOfTestModules.dirs;
const buildFiles = listOfTestModules.files;

function generateBindingConfigurations() {
const configs = [];

const testFilesToBind = process.argv.slice(2);
console.log('test modules to bind: ', testFilesToBind);

testFilesToBind.forEach((file) => {
const configName = file.split('.cc')[0];

if (buildDirs[configName]) {
for (let file of buildDirs[configName]) {
if (exceptions.skipBinding.includes(file)) continue;
configs.push(buildFiles[file]);
}
} else if (buildFiles[configName]) {
configs.push(buildFiles[configName]);
} else {
console.log('not found', file, configName);
}
});

return Promise.resolve(configs);
}

function writeToBindingFile(content) {
const generatedFilePath = path.join(__dirname, 'generated', 'binding.cc' );
fs.writeFileSync(generatedFilePath , "" );
fs.writeFileSync(generatedFilePath, content, { flag: "a" } );
console.log('generated binding file ', generatedFilePath, new Date());
}

generateBindingConfigurations().then(generateFileContent).then(writeToBindingFile);
69 changes: 69 additions & 0 deletions unit-test/injectTestParams.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const fs = require('fs');
const listOfTestModules = require('./listOfTestModules');

const buildDirs = listOfTestModules.dirs;
const buildFiles = listOfTestModules.files;

module.exports.filesToCompile = function () {
const filterCondition = require('./matchModules').matchWildCards(process.env.filter || '');
let files_to_compile = './generated/binding.cc test_helper.h';
let conditions = filterCondition.split(' ').length ? filterCondition.split(' ') : [filterCondition];
let files = [];

for (let matchCondition of conditions) {
if (buildDirs[matchCondition.toLowerCase()]) {
for (let file of buildDirs[matchCondition.toLowerCase()] ) {
const config = buildFiles[file];
const separator = config.dir.length ? '/' : ''
files.push(config.dir + separator + file);
}
} else if (buildFiles[matchCondition.toLowerCase()]) {
const config = buildFiles[matchCondition.toLowerCase()];
const separator = config.dir.length ? '/' : ''
files.push(config.dir + separator + matchCondition.toLowerCase());
}
}

let addedFiles = '';
files.forEach((file) => {
addedFiles = `${addedFiles} ../test/${file}.cc`;
});
fs.writeFileSync(__dirname + '/generated/compilelist', `${files_to_compile} ${addedFiles}`);
return `${files_to_compile} ${addedFiles}`;
};

module.exports.filesForBinding = function () {
const filterCondition = require('./matchModules').matchWildCards(process.env.filter || '');
fs.writeFileSync(__dirname + '/generated/bindingList', filterCondition);
return filterCondition;
};


if (require.main === module) {
const assert = require('assert');

const setEnvAndCall = (fn, filterCondition) => { process.env.filter = filterCondition; return fn(); };

assert.strictEqual(setEnvAndCall(exports.filesToCompile, 'typed*ex*'), './generated/binding.cc test_helper.h ../test/typed_threadsafe_function/typed_threadsafe_function_existing_tsfn.cc');

const expectedFilesToMatch = [
'./generated/binding.cc test_helper.h ',
'../test/threadsafe_function/threadsafe_function.cc',
'../test/threadsafe_function/threadsafe_function_ctx.cc',
'../test/threadsafe_function/threadsafe_function_existing_tsfn.cc',
'../test/threadsafe_function/threadsafe_function_ptr.cc',
'../test/threadsafe_function/threadsafe_function_sum.cc',
'../test/threadsafe_function/threadsafe_function_unref.cc',
'../test/typed_threadsafe_function/typed_threadsafe_function.cc',
'../test/typed_threadsafe_function/typed_threadsafe_function_ctx.cc',
'../test/typed_threadsafe_function/typed_threadsafe_function_existing_tsfn.cc',
'../test/typed_threadsafe_function/typed_threadsafe_function_ptr.cc',
'../test/typed_threadsafe_function/typed_threadsafe_function_sum.cc',
'../test/typed_threadsafe_function/typed_threadsafe_function_unref.cc'
]
assert.strictEqual(setEnvAndCall(exports.filesToCompile, 'threadsafe_function typed_threadsafe_function'), expectedFilesToMatch.join(' '));

assert.strictEqual(setEnvAndCall(exports.filesToCompile, 'objectwrap'), './generated/binding.cc test_helper.h ../test/objectwrap.cc');

console.log('ALL tests passed')
}
Loading

0 comments on commit 5f3f131

Please sign in to comment.