Browse Source

runtests changes for api testcase running; pretty raw still

pull/1/head
Sami Vaarala 11 years ago
parent
commit
8a749df423
  1. 200
      runtests/runtests.js

200
runtests/runtests.js

@ -1,5 +1,7 @@
/*
* Test case runner.
* Test case runner. Supports both Ecmascript tests and Duktape API
* C tests. Duktape API C tests are compiled on-the-fly against a
* dynamic or static library.
*
* Error handling is currently not correct throughout.
*/
@ -25,8 +27,8 @@ var TIMEOUT_NORMAL = 120 * 1000;
var tmpCount = 0;
var tmpUniq = process.pid || Math.floor(Math.random() * 1e6);
function mkTempName() {
return '/tmp/runtests-' + tmpUniq + '-' + (++tmpCount);
function mkTempName(ext) {
return '/tmp/runtests-' + tmpUniq + '-' + (++tmpCount) + (ext !== undefined ? ext : '');
}
function safeUnlinkSync(filePath) {
@ -111,8 +113,10 @@ function executeTest(options, callback) {
var cmd, cmdline;
var execopts;
var tempInput, tempVgxml, tempVgout;
var tempSource, tempExe;
var timeout;
// testcase execution done
function execDone(error, stdout, stderr) {
var res;
@ -120,8 +124,8 @@ function executeTest(options, callback) {
testcase: options.testcase,
engine: options.engine,
error: error,
stdout: stdout,
stderr: stderr,
stdout: stdout || '',
stderr: stderr || '',
cmdline: cmdline,
execopts: execopts
};
@ -132,6 +136,8 @@ function executeTest(options, callback) {
safeUnlinkSync(tempInput);
safeUnlinkSync(tempVgxml);
safeUnlinkSync(tempVgout);
safeUnlinkSync(tempSource);
safeUnlinkSync(tempExe);
if (res.valgrind_xml &&
res.valgrind_xml.substring(0, 5) === '<?xml' &&
@ -160,50 +166,109 @@ function executeTest(options, callback) {
}
}
if (options.engine.jsPrefix) {
// doesn't work
// tempInput = temp.path({ prefix: 'runtests-', suffix: '.js'})
tempInput = mkTempName();
// testcase compilation done (only relevant for API tests), ready to execute
function compileDone(error, stdout, stderr) {
/* FIXME: use child_process.spawn(); we don't currently escape command
* line parameters which is risky.
*/
if (error) {
console.log(error);
execDone(error);
return;
}
if (options.engine.jsPrefix) {
// doesn't work
// tempInput = temp.path({ prefix: 'runtests-', suffix: '.js'})
tempInput = mkTempName();
try {
fs.writeFileSync(tempInput, options.engine.jsPrefix + fs.readFileSync(options.testPath));
} catch (e) {
console.log(e);
callback(e);
return;
}
}
cmd = [];
if (options.valgrind) {
tempVgxml = mkTempName();
tempVgout = mkTempName();
cmd = cmd.concat([ 'valgrind', '--tool=memcheck', '--xml=yes',
'--xml-file=' + tempVgxml,
'--log-file=' + tempVgout,
'--child-silent-after-fork=yes', '-q' ]);
}
if (tempExe) {
cmd.push(tempExe);
} else {
cmd.push(options.engine.fullPath);
if (options.valgrind && options.engine.name === 'duk') {
cmd.push('-m'); // higher memory limit
}
cmd.push(tempInput || options.testPath);
}
cmdline = cmd.join(' ');
if (options.testcase.meta.slow) {
timeout = options.valgrind ? TIMEOUT_SLOW_VALGRIND : TIMEOUT_SLOW;
} else {
timeout = options.valgrind ? TIMEOUT_NORMAL_VALGRIND : TIMEOUT_NORMAL;
}
execopts = {
maxBuffer: 128 * 1024 * 1024,
timeout: timeout,
stdio: 'pipe'
};
//console.log(cmdline);
child = child_process.exec(cmdline, execopts, execDone);
}
function compileApiTest() {
tempSource = mkTempName('.c');
try {
fs.writeFileSync(tempInput, options.engine.jsPrefix + fs.readFileSync(options.testPath));
fs.writeFileSync(tempSource, options.engine.cPrefix + fs.readFileSync(options.testPath));
} catch (e) {
console.log(e);
callback(e);
return;
}
}
tempExe = mkTempName();
// FIXME: listing specific options here is awkward, must match Makefile
cmd = [ 'gcc', '-o', tempExe,
'-L.',
'-Idist/src-combined',
'-Wl,-rpath,.',
'-pedantic', '-ansi', '-std=c99', '-Wall', '-fstrict-aliasing', '-D__POSIX_C_SOURCE=200809L', '-D_GNU_SOURCE', '-D_XOPEN_SOURCE', '-Os', '-fomit-frame-pointer',
'-g', '-ggdb',
'-Werror',
//'-m32',
'-DDUK_PROFILE=400',
'runtests/api_testcase_main.c',
tempSource,
'-lduktape400',
//'-lduktape401',
'-lm' ];
cmdline = cmd.join(' ');
execopts = {
maxBuffer: 128 * 1024 * 1024,
timeout: timeout,
stdio: 'pipe'
};
/* FIXME: use child_process.spawn(); we don't currently escape command
* line parameters which is risky.
*/
cmd = [];
if (options.valgrind) {
tempVgxml = mkTempName();
tempVgout = mkTempName();
cmd = cmd.concat([ 'valgrind', '--tool=memcheck', '--xml=yes',
'--xml-file=' + tempVgxml,
'--log-file=' + tempVgout,
'--child-silent-after-fork=yes', '-q' ]);
console.log(options.testPath, cmdline);
child = child_process.exec(cmdline, execopts, compileDone);
}
cmd.push(options.engine.fullPath);
if (options.valgrind && options.engine.name === 'duk') {
cmd.push('-m'); // higher memory limit
}
cmd.push(tempInput || options.testPath);
cmdline = cmd.join(' ');
if (options.testcase.meta.slow) {
timeout = options.valgrind ? TIMEOUT_SLOW_VALGRIND : TIMEOUT_SLOW;
if (options.engine.name === 'api') {
compileApiTest();
} else {
timeout = options.valgrind ? TIMEOUT_NORMAL_VALGRIND : TIMEOUT_NORMAL;
compileDone(null, null, null);
}
execopts = {
maxBuffer: 128 * 1024 * 1024,
timeout: timeout,
stdio: 'pipe'
};
child = child_process.exec(cmdline, execopts, execDone);
}
/*
@ -233,9 +298,36 @@ var RHINO_HEADER =
var SMJS_HEADER =
"this.__engine__ = 'smjs'; ";
var API_TEST_HEADER =
"#include <stdio.h>\n" +
"#include <stdlib.h>\n" +
"#include <string.h>\n" +
"#include <math.h>\n" +
"#include <limits.h> /* INT_MIN, INT_MAX */\n" +
"#include \"duktape.h\"\n" +
"\n" +
"#define TEST_SAFE_CALL(func) do { \\\n" +
"\t\tint _rc; \\\n" +
"\t\tprintf(\"*** %s (duk_safe_call)\\n\", #func); \\\n" +
"\t\t_rc = duk_safe_call(ctx, (func), 0, 1, DUK_INVALID_INDEX); \\\n" +
"\t\tprintf(\"==> rc=%d, result='%s'\\n\", _rc, duk_to_string(ctx, -1)); \\\n" +
"\t\tduk_pop(ctx); \\\n" +
"\t} while (0)\n" +
"\n" +
"#define TEST_PCALL(func) do { \\\n" +
"\t\tint _rc; \\\n" +
"\t\tprintf(\"*** %s (duk_pcall)\\n\", #func); \\\n" +
"\t\tduk_push_c_function(ctx, (func), 0); \\\n" +
"\t\t_rc = duk_pcall(ctx, 0, DUK_INVALID_INDEX); \\\n" +
"\t\tprintf(\"==> rc=%d, result='%s'\\n\", _rc, duk_to_string(ctx, -1)); \\\n" +
"\t\tduk_pop(ctx); \\\n" +
"\t} while (0)\n" +
"\n" +
"#line 1\n";
function findTestCasesSync(argList) {
var found = {};
var pat = /^([a-zA-Z0-9_-]+).js$/;
var pat = /^([a-zA-Z0-9_-]+).(js|c)$/;
var testcases = [];
argList.forEach(function checkArg(arg) {
@ -352,15 +444,26 @@ function testRunnerMain() {
results[testcase.name] = {}; // create in test case order
engines.forEach(function testWithEngine(engine) {
if (path.extname(fullPath) === '.c') {
tasks.push({
engine: engine,
engine: engine_api,
filename: filename,
testPath: fullPath,
testcase: testcase,
valgrind: argv.valgrind && (engine.name === 'duk')
valgrind: argv.valgrind
});
});
} else {
engines.forEach(function testWithEngine(engine) {
tasks.push({
engine: engine,
filename: filename,
testPath: fullPath,
testcase: testcase,
valgrind: argv.valgrind && (engine.name === 'duk')
});
});
}
});
if (tasks.length === 0) {
@ -390,7 +493,7 @@ function testRunnerMain() {
resultKey: 'diff_expect'
});
}
if (en !== 'duk') {
if (en !== 'duk' || en === 'api') {
return;
}
@ -440,6 +543,10 @@ function testRunnerMain() {
var vgerrors;
var need = false;
if (en !== 'duk' && en !== 'api') {
return;
}
vgerrors = getValgrindErrorSummary(res.valgrind_root);
parts.push(res.testcase.name);
@ -474,7 +581,7 @@ function testRunnerMain() {
if (need) {
lines.push(parts);
}
}, 'duk');
}, null);
lines.forEach(function printLine(line) {
var tmp = (' ' + line[0]);
@ -538,9 +645,12 @@ function testRunnerMain() {
fullPath: argv['cmd-smjs'] || 'smjs',
jsPrefix: SMJS_HEADER });
}
engine_api = { name: 'api',
cPrefix: API_TEST_HEADER };
testcases = findTestCasesSync(argv._);
testcases.sort();
//console.log(testcases);
queue1 = async.queue(function (task, callback) {
executeTest(task, function testDone(err, val) {

Loading…
Cancel
Save