From 7190df53b47e15b6f54598f367ba82745c5efad7 Mon Sep 17 00:00:00 2001 From: Deepak Rajamohan Date: Thu, 23 Sep 2021 19:18:20 -0700 Subject: [PATCH] enable unit tests --- unit-test/binding-file-template.js | 22 +++++------ unit-test/exceptions.js | 24 ++++++------ unit-test/generate-binding-cc.js | 45 ++++++++++++++++----- unit-test/injectTestParams.js | 45 ++++++++++++++++----- unit-test/listOfTestModules.js | 39 ++++++++++-------- unit-test/matchModules.js | 63 +++++++++++++++++------------- unit-test/spawnTask.js | 6 +-- unit-test/test.js | 10 ++--- 8 files changed, 160 insertions(+), 94 deletions(-) diff --git a/unit-test/binding-file-template.js b/unit-test/binding-file-template.js index eebcfa642..341779857 100644 --- a/unit-test/binding-file-template.js +++ b/unit-test/binding-file-template.js @@ -1,27 +1,27 @@ -module.exports.generateFileContent = function(configs) { +module.exports.generateFileContent = function (bindingConfigurations) { const content = []; const inits = []; const exports = []; - for (let config of configs) { + for (const config of bindingConfigurations) { 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('#include "napi.h"'); + content.push('using namespace Napi;'); - //content.push("Object InitName(Env env);"); + // content.push("Object InitName(Env env);"); inits.forEach(init => content.push(init)); - content.push("Object Init(Env env, Object exports) {"); + content.push('Object Init(Env env, Object exports) {'); - //content.push("exports.Set(\"name\", InitName(env));"); + // 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);"); + content.push('return exports;'); + content.push('}'); + content.push('NODE_API_MODULE(addon, Init);'); return Promise.resolve(content.join('\r\n')); -} +}; diff --git a/unit-test/exceptions.js b/unit-test/exceptions.js index 8dd788c5c..1e807f42e 100644 --- a/unit-test/exceptions.js +++ b/unit-test/exceptions.js @@ -1,20 +1,20 @@ module.exports = { - 'nouns': { - 'constructor': 'constructor', - 'threadsafe': 'threadSafe', - 'objectwrap': 'objectWrap', + nouns: { + constructor: 'constructor', + threadsafe: 'threadSafe', + objectwrap: 'objectWrap' }, - 'exportNames': { - 'AsyncWorkerPersistent': 'PersistentAsyncWorker', + exportNames: { + AsyncWorkerPersistent: 'PersistentAsyncWorker' }, - 'propertyNames': { - 'async_worker_persistent': 'persistentasyncworker', - 'objectwrap_constructor_exception':'objectwrapConstructorException', + propertyNames: { + async_worker_persistent: 'persistentasyncworker', + objectwrap_constructor_exception: 'objectwrapConstructorException' }, - 'skipBinding': [ + skipBinding: [ 'global_object_delete_property', 'global_object_get_property', 'global_object_has_own_property', - 'global_object_set_property', + 'global_object_set_property' ] -}; \ No newline at end of file +}; diff --git a/unit-test/generate-binding-cc.js b/unit-test/generate-binding-cc.js index 7cde10d51..fc1538777 100644 --- a/unit-test/generate-binding-cc.js +++ b/unit-test/generate-binding-cc.js @@ -7,17 +7,17 @@ const generateFileContent = require('./binding-file-template').generateFileConte const buildDirs = listOfTestModules.dirs; const buildFiles = listOfTestModules.files; -function generateBindingConfigurations() { - const configs = []; - +function generateBindingConfigurations () { const testFilesToBind = process.argv.slice(2); console.log('test modules to bind: ', testFilesToBind); + const configs = []; + testFilesToBind.forEach((file) => { const configName = file.split('.cc')[0]; if (buildDirs[configName]) { - for (let file of buildDirs[configName]) { + for (const file of buildDirs[configName]) { if (exceptions.skipBinding.includes(file)) continue; configs.push(buildFiles[file]); } @@ -31,11 +31,38 @@ function generateBindingConfigurations() { 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()); +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); + +/** + * + * Test cases + * @fires only when run directly from terminal + * + * + * + */ +if (require.main === module) { + const assert = require('assert'); + + const setArgsAndCall = (fn, filterCondition) => { process.argv = [null, null, ...filterCondition.split(' ')]; return fn(); }; + const assertPromise = (promise, expectedVal) => promise.then((val) => assert.deepEqual(val, expectedVal)).catch(console.log); + + const expectedVal = [{ + dir: '', + objectName: 'AsyncProgressWorker', + propertyName: 'async_progress_worker' + }, + { + dir: '', + objectName: 'PersistentAsyncWorker', + propertyName: 'persistentasyncworker' + }]; + assertPromise(setArgsAndCall(generateBindingConfigurations, 'async_progress_worker async_worker_persistent'), expectedVal); +} diff --git a/unit-test/injectTestParams.js b/unit-test/injectTestParams.js index 3e1a36263..e61eab5af 100644 --- a/unit-test/injectTestParams.js +++ b/unit-test/injectTestParams.js @@ -4,22 +4,33 @@ const listOfTestModules = require('./listOfTestModules'); const buildDirs = listOfTestModules.dirs; const buildFiles = listOfTestModules.files; +/** + * + * @returns : list of files to compile by node-gyp + * @param : none + * @requires : picks `filter` parameter from process.env + * This function is used as an utility method to inject a list of files to compile into binding.gyp + * + * + */ module.exports.filesToCompile = function () { + !fs.existsSync('./generated/') && fs.mkdirSync('./generated/', { recursive: true }); + 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 = []; + const files_to_compile = './generated/binding.cc test_helper.h'; + const conditions = filterCondition.split(' ').length ? filterCondition.split(' ') : [filterCondition]; + const files = []; - for (let matchCondition of conditions) { + for (const matchCondition of conditions) { if (buildDirs[matchCondition.toLowerCase()]) { - for (let file of buildDirs[matchCondition.toLowerCase()] ) { + for (const file of buildDirs[matchCondition.toLowerCase()]) { const config = buildFiles[file]; - const separator = config.dir.length ? '/' : '' + 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 ? '/' : '' + const separator = config.dir.length ? '/' : ''; files.push(config.dir + separator + matchCondition.toLowerCase()); } } @@ -32,13 +43,27 @@ module.exports.filesToCompile = function () { return `${files_to_compile} ${addedFiles}`; }; +/** + * @returns list of test files to bind exported init functions + * @param : none + * @requires : picks `filter` parameter from process.env + * This function is used as an utility method by the generateBindingCC step in binding.gyp + * + */ module.exports.filesForBinding = function () { const filterCondition = require('./matchModules').matchWildCards(process.env.filter || ''); fs.writeFileSync(__dirname + '/generated/bindingList', filterCondition); return filterCondition; }; - +/** + * + * Test cases + * @fires only when run directly from terminal + * + * + * + */ if (require.main === module) { const assert = require('assert'); @@ -60,10 +85,10 @@ if (require.main === module) { '../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') + console.log('ALL tests passed'); } diff --git a/unit-test/listOfTestModules.js b/unit-test/listOfTestModules.js index 20b712224..788aea81a 100644 --- a/unit-test/listOfTestModules.js +++ b/unit-test/listOfTestModules.js @@ -5,7 +5,7 @@ const exceptions = require('./exceptions'); const buildFiles = {}; const buidDirs = {}; -function getExportObjectName(fileName) { +function getExportObjectName (fileName) { fileName = fileName.split('_').map(token => exceptions.nouns[token] ? exceptions.nouns[token] : token).join('_'); const str = fileName.replace(/(\_\w)/g, (k) => k[1].toUpperCase()); const exportObjectName = str.charAt(0).toUpperCase() + str.substring(1); @@ -15,14 +15,14 @@ function getExportObjectName(fileName) { return exportObjectName; } -function getExportPropertyName(fileName) { +function getExportPropertyName (fileName) { if (exceptions.propertyNames[fileName.toLowerCase()]) { return exceptions.propertyNames[fileName.toLowerCase()]; } return fileName; } -function listOfTestModules(currentDirectory = __dirname + '/../test', pre = '') { +function listOfTestModules (currentDirectory = __dirname + '/../test', pre = '') { fs.readdirSync(currentDirectory).forEach((file) => { if (file === 'binding.cc' || file === 'binding.gyp' || @@ -31,17 +31,17 @@ function listOfTestModules(currentDirectory = __dirname + '/../test', pre = '') file === 'thunking_manual.cc' || file === 'addon_build' || file[0] === '.') { - return; + return; } const absoluteFilepath = path.join(currentDirectory, file); const fileName = file.toLowerCase().replace('.cc', ''); if (fs.statSync(absoluteFilepath).isDirectory()) { - buidDirs[fileName] = [] + buidDirs[fileName] = []; listOfTestModules(absoluteFilepath, pre + file + '/'); } else { if (!file.toLowerCase().endsWith('.cc')) return; if (currentDirectory.trim().split('/test/').length > 1) { - buidDirs[currentDirectory.split('/test/')[1].toLowerCase()].push(fileName) + buidDirs[currentDirectory.split('/test/')[1].toLowerCase()].push(fileName); } const relativePath = (currentDirectory.split(`${fileName}.cc`)[0]).split('/test/')[1] || ''; buildFiles[fileName] = { dir: relativePath, propertyName: getExportPropertyName(fileName), objectName: getExportObjectName(fileName) }; @@ -55,16 +55,23 @@ module.exports = { files: buildFiles }; - +/** + * + * Test cases + * @fires only when run directly from terminal + * + * + * + */ if (require.main === module) { - const assert = require('assert') - assert.strictEqual(getExportObjectName('objectwrap_constructor_exception'), 'ObjectWrapConstructorException') - assert.strictEqual(getExportObjectName('typed_threadsafe_function'), 'TypedThreadSafeFunction') - assert.strictEqual(getExportObjectName('objectwrap_removewrap'), 'ObjectWrapRemovewrap') - assert.strictEqual(getExportObjectName('function_reference'), 'FunctionReference') - assert.strictEqual(getExportObjectName('async_worker'), 'AsyncWorker') - assert.strictEqual(getExportObjectName('async_progress_worker'), 'AsyncProgressWorker') - assert.strictEqual(getExportObjectName('async_worker_persistent'), 'PersistentAsyncWorker') + const assert = require('assert'); + assert.strictEqual(getExportObjectName('objectwrap_constructor_exception'), 'ObjectWrapConstructorException'); + assert.strictEqual(getExportObjectName('typed_threadsafe_function'), 'TypedThreadSafeFunction'); + assert.strictEqual(getExportObjectName('objectwrap_removewrap'), 'ObjectWrapRemovewrap'); + assert.strictEqual(getExportObjectName('function_reference'), 'FunctionReference'); + assert.strictEqual(getExportObjectName('async_worker'), 'AsyncWorker'); + assert.strictEqual(getExportObjectName('async_progress_worker'), 'AsyncProgressWorker'); + assert.strictEqual(getExportObjectName('async_worker_persistent'), 'PersistentAsyncWorker'); - console.log('ALL tests passed') + console.log('ALL tests passed'); } diff --git a/unit-test/matchModules.js b/unit-test/matchModules.js index 8ce531cba..935370d92 100644 --- a/unit-test/matchModules.js +++ b/unit-test/matchModules.js @@ -2,28 +2,27 @@ const listOfTestModules = require('./listOfTestModules'); const buildDirs = listOfTestModules.dirs; const buildFiles = listOfTestModules.files; -function isWildcard(filter) { +function isWildcard (filter) { if (filter.includes('*')) return true; return false; } -function filterBy(wildcard, item) { - return new RegExp('^' + wildcard.replace(/\*/g, '.*') + '$').test(item) +function filterBy (wildcard, item) { + return new RegExp('^' + wildcard.replace(/\*/g, '.*') + '$').test(item); } -function matchWildCards(filterCondition) { - let conditions = filterCondition.split(' ').length ? filterCondition.split(' ') : [filterCondition]; - let matches = []; +function matchWildCards (filterCondition) { + const conditions = filterCondition.split(' ').length ? filterCondition.split(' ') : [filterCondition]; + const matches = []; - for (let filter of conditions) { + for (const filter of conditions) { if (isWildcard(filter)) { const matchedDirs = Object.keys(buildDirs).filter(e => filterBy(filter, e)); if (matchedDirs.length) { matches.push(matchedDirs.join(' ')); } else { const matchedModules = Object.keys(buildFiles).filter(e => filterBy(filter, e)); - if (matchedModules.length) - matches.push(matchedModules.join(' ')); + if (matchedModules.length) { matches.push(matchedModules.join(' ')); } } } else { matches.push(filter); @@ -35,24 +34,32 @@ function matchWildCards(filterCondition) { module.exports.matchWildCards = matchWildCards; +/** + * + * Test cases + * @fires only when run directly from terminal + * + * + * + */ if (require.main === module) { - const assert = require('assert') - - assert.strictEqual(matchWildCards('typed*ex'), 'typed*ex') - assert.strictEqual(matchWildCards('typed*ex*'), 'typed_threadsafe_function_existing_tsfn') - assert.strictEqual(matchWildCards('async*'), 'async_context async_progress_queue_worker async_progress_worker async_worker async_worker_persistent') - assert.strictEqual(matchWildCards('typed*func'), 'typed*func') - assert.strictEqual(matchWildCards('typed*func*'), 'typed_threadsafe_function') - assert.strictEqual(matchWildCards('typed*function'), 'typed_threadsafe_function') - assert.strictEqual(matchWildCards('object*inh'), 'object*inh') - assert.strictEqual(matchWildCards('object*inh*'), 'objectwrap_multiple_inheritance') - assert.strictEqual(matchWildCards('*remove*'), 'objectwrap_removewrap') - assert.strictEqual(matchWildCards('*function'), 'threadsafe_function typed_threadsafe_function') - assert.strictEqual(matchWildCards('**function'), 'threadsafe_function typed_threadsafe_function') - assert.strictEqual(matchWildCards('a*w*p*'), 'async_worker_persistent') - assert.strictEqual(matchWildCards('fun*ref'), 'fun*ref') - assert.strictEqual(matchWildCards('fun*ref*'), 'function_reference') - assert.strictEqual(matchWildCards('*reference'), 'function_reference object_reference reference') - - console.log('ALL tests passed') + const assert = require('assert'); + + assert.strictEqual(matchWildCards('typed*ex'), 'typed*ex'); + assert.strictEqual(matchWildCards('typed*ex*'), 'typed_threadsafe_function_existing_tsfn'); + assert.strictEqual(matchWildCards('async*'), 'async_context async_progress_queue_worker async_progress_worker async_worker async_worker_persistent'); + assert.strictEqual(matchWildCards('typed*func'), 'typed*func'); + assert.strictEqual(matchWildCards('typed*func*'), 'typed_threadsafe_function'); + assert.strictEqual(matchWildCards('typed*function'), 'typed_threadsafe_function'); + assert.strictEqual(matchWildCards('object*inh'), 'object*inh'); + assert.strictEqual(matchWildCards('object*inh*'), 'objectwrap_multiple_inheritance'); + assert.strictEqual(matchWildCards('*remove*'), 'objectwrap_removewrap'); + assert.strictEqual(matchWildCards('*function'), 'threadsafe_function typed_threadsafe_function'); + assert.strictEqual(matchWildCards('**function'), 'threadsafe_function typed_threadsafe_function'); + assert.strictEqual(matchWildCards('a*w*p*'), 'async_worker_persistent'); + assert.strictEqual(matchWildCards('fun*ref'), 'fun*ref'); + assert.strictEqual(matchWildCards('fun*ref*'), 'function_reference'); + assert.strictEqual(matchWildCards('*reference'), 'function_reference object_reference reference'); + + console.log('ALL tests passed'); } diff --git a/unit-test/spawnTask.js b/unit-test/spawnTask.js index b14776481..20695fbe6 100644 --- a/unit-test/spawnTask.js +++ b/unit-test/spawnTask.js @@ -1,7 +1,7 @@ -const { spawn } = require("child_process"); +const { spawn } = require('child_process'); module.exports.runChildProcess = async function (command, options) { - const childProcess = spawn("node", [command], options); + const childProcess = spawn('node', [command], options); childProcess.stdout.on('data', data => { console.log(`${data}`); @@ -20,4 +20,4 @@ module.exports.runChildProcess = async function (command, options) { resolve(); }); }); -} +}; diff --git a/unit-test/test.js b/unit-test/test.js index 5d5667f04..9fa49174e 100644 --- a/unit-test/test.js +++ b/unit-test/test.js @@ -2,21 +2,21 @@ const path = require('path'); const runChildProcess = require('./spawnTask').runChildProcess; -const executeTests = async function() { +const executeTests = async function () { try { const workingDir = path.join(__dirname, '../'); const relativeBuildPath = path.join('../', 'unit-test'); const buildPath = path.join(__dirname, './unit-test'); - const envVars = { ...process.env, REL_BUILD_PATH: relativeBuildPath, BUILD_PATH: buildPath}; + const envVars = { ...process.env, REL_BUILD_PATH: relativeBuildPath, BUILD_PATH: buildPath }; console.log('Starting to run tests in ', buildPath, new Date()); - await runChildProcess('test', {cwd: workingDir, env: envVars}); + await runChildProcess('test', { cwd: workingDir, env: envVars }); console.log('Completed running tests', new Date()); - } catch(e) { + } catch (e) { console.log('Error occured running tests', new Date()); } -} +}; executeTests();