123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- 'use strict';
- const Fs = require("fs");
- const nThen = require("nthen");
- const Fs_stat = function (file, callback) {
- Fs.stat(file, function (err, ret) {
- if (err === 'ENOENT') {
- console.log("Magical ENOENT on a file which definitely does exist, good job Linus");
- setTimeout(function () {
- Fs_stat(file, callback);
- }, 1000);
- } else {
- callback(err, ret);
- }
- });
- };
- const getTests = function (file, tests, isSubnode, callback) {
- if (/\/(.git|build_.*|node_build|contrib|target)\//.test(file)) { callback(); return; }
- if (isSubnode && /\/dht\//.test(file)) { callback(); return; }
- Fs_stat(file, function (err, stat) {
- if (err) { throw err; }
- if (stat.isDirectory()) {
- nThen(function (waitFor) {
- Fs.readdir(file, waitFor(function (err, list) {
- if (err) { throw err; }
- list.forEach(function (subFile) {
- getTests(file + '/' + subFile, tests, isSubnode, waitFor());
- });
- }));
- }).nThen(function (waitFor) {
- callback();
- });
- return;
- } else if (!/_test\.c$/.test(file)) {
- // not a test
- } else {
- // get rid of the annoying ./
- const f = file.replace(/^\.\//, '');
- if (tests.indexOf(f) === -1) { tests.push(f); }
- }
- callback();
- });
- };
- const rmFuzz = function (builder, cb) {
- const inputs = builder.config.buildDir + '/fuzz_inputs';
- Fs_stat(inputs, function (err, stat) {
- if (err && err.code === 'ENOENT') {
- Fs.mkdir(inputs, function (err, ret) {
- if (err) { throw err; }
- return void cb();
- });
- return;
- } else if (err) {
- throw err;
- }
- if (!stat.isDirectory()) {
- throw new Error(inputs + ' found, and it is a file, not a directory');
- }
- Fs.readdir(inputs, function (err, list) {
- if (err) { throw err; }
- let nt = nThen;
- list.forEach(function (f) {
- nt = nt(function (w) {
- Fs.unlink(inputs + '/' + f, w(function (err) {
- if (err) { throw err; }
- }));
- }).nThen;
- });
- nt(function (w) { cb(); });
- });
- });
- };
- const mkFuzzCase = function (inFile, outPath, testId, cb) {
- Fs.readFile(inFile, 'utf8', function (err, ret) {
- if (err) { throw err; }
- ret = ret.replace(/#[^\n]*\n/g, '');
- ret = ret.replace(/[\s]*/g, '');
- const out = Buffer.from(ret, 'hex');
- const id = Buffer.alloc(4);
- id.writeInt32BE(testId, 0);
- Fs.writeFile(outPath, Buffer.concat([id, out]), function (err) {
- if (err) { throw err; }
- cb();
- });
- });
- };
- const mkFuzz = function (builder, testPath, testId, fuzzCases, cb) {
- const inputs = builder.config.buildDir + '/fuzz_inputs';
- nThen(function (w) {
- const casesPath = testPath.replace(/\.c$/, '_cases');
- Fs.readdir(casesPath, w(function (err, list) {
- if (err && err.code === 'ENOENT') {
- return void console.log("Fuzz test [" + testPath + "] has no test cases");
- }
- if (err) { throw err; }
- let nt = nThen;
- list.forEach(function (f) {
- nt = nt(function (w) {
- const fNoExt = f.replace(/\..*$/, '');
- const outPath = inputs + '/' + (testPath + fNoExt).replace(/[^a-zA-Z0-9_-]/g, '_');
- fuzzCases.push('"' + outPath + '",');
- const inFile = casesPath + '/' + f;
- mkFuzzCase(inFile, outPath, testId, w());
- }).nThen;
- });
- nt(w());
- }));
- }).nThen(function (w) {
- cb();
- });
- };
- module.exports.generate = function (builder, isSubnode, callback) {
- const tests = [];
- const fuzzCases = [];
- const prototypes = [];
- const listContent = [];
- const fuzzTests = [];
- builder.config.cjdnsTest_files = builder.config.cjdnsTest_files || [];
- nThen(function (w) {
- getTests('.', tests, isSubnode, w());
- rmFuzz(builder, w());
- }).nThen(function (w) {
- tests.forEach(function (test) {
- //console.log(test);
- const testProto = /^.*\/([^\/]+)\.c$/.exec(test)[1];
- builder.config.cjdnsTest_files.push(test);
- const cflags = (builder.fileCflags[test] = builder.fileCflags[test] || []);
- if (test.indexOf('_fuzz_test') > -1) {
- cflags.push(
- '-D', 'CJDNS_FUZZ_INIT='+testProto+'_FUZZ_INIT',
- '-D', 'CJDNS_FUZZ_MAIN='+testProto+'_FUZZ_MAIN'
- );
- prototypes.push(
- 'void* '+testProto+'_FUZZ_INIT(struct Allocator* alloc, struct Random* rand);',
- 'void '+testProto+'_FUZZ_MAIN(void* ctx, struct Message* fuzz);'
- );
- mkFuzz(builder, test, fuzzTests.length, fuzzCases, w());
- fuzzTests.push('{' +
- '.init = '+testProto+'_FUZZ_INIT, ' +
- '.name = "'+test.replace(/^.*\/|.c$/g, '')+'", ' +
- '.fuzz = '+testProto+'_FUZZ_MAIN, ' +
- '},');
- } else {
- var main = testProto + '_main';
- cflags.push(
- '-D', 'main='+main,
- '-D', main+'(...)='+main+'(int argc, char** argv);int '+main+'(int argc, char** argv)'
- );
- prototypes.push('int '+main+'(int argc, char** argv);');
- listContent.push('{ .func = '+main+', .name = "'+test.replace(/^.*\/|.c$/g, '')+'" },');
- }
- });
- }).nThen(function (w) {
- builder.config.cjdnsTest_fuzzCases = fuzzCases.join(' ');
- builder.config.cjdnsTest_tests = listContent.join(' ');
- builder.config.cjdnsTest_fuzzTests = fuzzTests.join(' ');
- builder.config.cjdnsTest_prototypes = prototypes.join(' ');
- callback();
- });
- };
|