Skip to content

Instantly share code, notes, and snippets.

@ChALkeR

ChALkeR/errtest.js

Last active Jun 22, 2018
Embed
What would you like to do?
// Flags: --expose-internals
// Note: this script reads Node.js sources and docs, and expects to be run on
// the very same Node.js version as the source and doc tree is.
const errors = require('internal/errors').codes;
const assert = require('assert');
const fs = require('fs');
const natives = process.binding('natives');
// --report prints only the list of failed checks and does not assert
const report = process.argv[2] === '--report';
const results = [];
function check(ok, type, name, reason) {
if (report) {
if (!ok) results.push(`${type}: ${name} - ${reason}`);
} else {
assert.ok(ok, `${type}: ${name} - ${reason}`);
}
}
const set = {
all: new Set(),
js: new Set(),
doc: new Set(),
cpp: new Set(),
noargs: new Set(),
// `set.manual` contains errors manually created from js and not defined in
// internals/errors. That is not scanned now, update this list if required.
manual: new Set(['ERR_HTTP2_ERROR', 'ERR_UNKNOWN_BUILTIN_MODULE'])
};
// File containing error definitions
const jsdata = natives['internal/errors'];
// File containing error documentation
const docdata = fs.readFileSync('doc/api/errors.md', 'utf-8');
// File containing cpp-side errors
const cppdata = fs.readFileSync('src/node_errors.h', 'utf-8');
function addSource(source, type) {
const re = /(.)?(ERR_[A-Z0-9_]+)(..)?/g;
let match;
while (match = re.exec(source)) {
if (match[1] === '_') continue; // does not start with ERR_
set.all.add(match[2]);
set[type].add(match[2]);
if (type === 'js' && match[3] === '()') {
// Is directly called without arguments from js, we will try that
set.noargs.add(match[2]);
}
}
}
// Scan all JS natives
for (const file of Object.keys(natives)) addSource(natives[file], 'js');
// Add all errors from doc/api/errors and src/node_errors
addSource(docdata, 'doc');
addSource(cppdata, 'cpp');
// Check that we have all js errors
for (const name of set.js) {
if (set.manual.has(name)) continue;
const defined = jsdata.includes(`E('${name}',`);
check(defined, 'js', name, 'missing JS implementation (source)');
if (defined) {
check(errors[name], 'js', name, 'missing JS implementation (runtime)');
}
}
// Check that we have can initialize errors called without args
for (const name of set.noargs) {
if (!errors[name]) continue; // Already catched that above
let ok = true;
try {
new errors[name]();
} catch (e) {
ok = false;
}
check(ok, 'init', name, 'failed 0 args init, but is called with "()"');
}
// Check that we have all documented errors
for (const name of set.doc) {
const ok = set.manual.has(name) ||
jsdata.includes(`E('${name}',`) ||
cppdata.includes(`V(${name}, `);
check(ok, 'impl', name, 'documented, missing implementation');
}
// Check error documentation for all errors
for (const name of set.all) {
const ok = docdata.includes(`### ${name}\n`);
check(ok, 'doc', name, 'missing documentation');
}
if (report) {
console.log('Report mode');
console.log(results.join('\n'));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment