kopia lustrzana https://github.com/c9/core
Merge pull request +15278 from c9/sdk-tests
fix test runner in the sdkpull/402/head
commit
315b33525e
|
@ -70,7 +70,7 @@ function extractTypeAnnotations(code) {
|
|||
|
||||
exports.buildTest = function(filename, exportSymbol) {
|
||||
return function(done) {
|
||||
var code = fs.readFileSync(__dirname + "/" + filename, 'utf-8');
|
||||
var code = fs.readFileSync(__dirname + "/" + filename, 'utf-8').replace(/\r/g, "");
|
||||
var builtins1 = fs.readFileSync(__dirname + "/../builtin.jst", 'utf-8');
|
||||
var builtins2 = fs.readFileSync(__dirname + "/../builtin.custom.jst", 'utf-8');
|
||||
var builtins3 = fs.readFileSync(__dirname + "/../builtin.nodejs.jst", 'utf-8');
|
||||
|
|
|
@ -6,6 +6,5 @@
|
|||
require("c9/inline-mocha")(module);
|
||||
|
||||
describe(__filename, function() {
|
||||
setTimeout(4000);
|
||||
it("should analyze 'hints.js'", require('./framework').buildTest("hints.js"));
|
||||
});
|
|
@ -0,0 +1,218 @@
|
|||
"use strict";
|
||||
|
||||
/* global phantom */
|
||||
|
||||
var TEST_SUITE_URL = "http://localhost:8080/static/test.html?noui=true";
|
||||
|
||||
var page = require("webpage").create();
|
||||
var system = require("system");
|
||||
var pageErrors = [];
|
||||
var hadError = 0;
|
||||
|
||||
var address = system.args[1];
|
||||
var filter = system.args[2];
|
||||
var branch = system.args[3];
|
||||
|
||||
var logAll = false;
|
||||
if (!address) console.log("# No address, running against: ", TEST_SUITE_URL);
|
||||
if (filter) console.log("# Filter tests by ", filter);
|
||||
if (!address) address = TEST_SUITE_URL;
|
||||
|
||||
page.onConsoleMessage = function(msg) {
|
||||
if (!/^PHANTOMJS:/.test(msg)) {
|
||||
if (logAll) console.log(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = msg.replace(/^PHANTOMJS: /, "");
|
||||
|
||||
if (/^exit/.test(msg)) {
|
||||
showPageErrors();
|
||||
phantom.exit(hadError ? 1 : 0);
|
||||
}
|
||||
|
||||
if (/^screenshot/.test(msg)) {
|
||||
var title = "out/cferror_" + /\w*$/m.exec(msg)[0] + ".png";
|
||||
return page.render(title);
|
||||
}
|
||||
|
||||
if (/^error #/.test(msg)) {
|
||||
msg = linkifyErrorStack(msg);
|
||||
}
|
||||
|
||||
if (/^not ok/.test(msg)) {
|
||||
hadError = true;
|
||||
}
|
||||
|
||||
console.log(msg);
|
||||
};
|
||||
|
||||
function linkifyErrorStack(msg) {
|
||||
function toGithubUrl(path) {
|
||||
if (!branch) return path;
|
||||
return path.replace(/\/?([^:]+):(\d+)/g, function(_, path, line) {
|
||||
return "https://github.com/c9/newclient/blob/" + branch + "/" + path + "#L" + line;
|
||||
});
|
||||
}
|
||||
// change phantomjs stack to chrome format
|
||||
msg = msg
|
||||
.replace(/^(\s*)(?:([^@:\s]+)@|(https?:))/gm, "$1at $2 $3")
|
||||
.replace(/^/gm, "\t\t").slice(1);
|
||||
msg = msg.replace(/https?:\/\/[^/]+\/static(\/[^:]+[:\d]+)/g, function(_, path) {
|
||||
if (/^\/plugins\//.test(path)) path = path;
|
||||
else if (/^lib\/(events|path)/.test(path)) path = "plugins/c9.nodeapi" + path.slice(4);
|
||||
else if (/^\/lib\/(ace|mocha)/.test(path)) path = "/node_modules" + path.slice(4);
|
||||
else if (/^\/engine.io\/engine.io.js/.test(path)) path = "/node_modules" + path.replace(/engine.io/, "$&-client");
|
||||
else if (/^\/(vfs-socket|smith)\//.test(path)) path = "/node_modules" + path;
|
||||
else if (/^\/(kaefer)\//.test(path)) path = "/node_modules" + path.replace("kaefer", "$&/lib");
|
||||
else return _;
|
||||
|
||||
return toGithubUrl(path);
|
||||
});
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
function showError(msg, trace) {
|
||||
var msgStack = [msg];
|
||||
if (trace && trace.length) {
|
||||
trace.forEach(function(t) {
|
||||
msgStack.push((t.file || t.sourceURL) + ':' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));
|
||||
});
|
||||
}
|
||||
console.log(linkifyErrorStack(msgStack.join('\n')));
|
||||
}
|
||||
|
||||
page.onError = function(msg, trace) {
|
||||
pageErrors.push({
|
||||
msg: msg,
|
||||
trace: trace
|
||||
});
|
||||
if (logAll)
|
||||
showError(msg, trace);
|
||||
};
|
||||
|
||||
function showPageErrors() {
|
||||
var re = /--debug/;
|
||||
if (system.args.some(re.test.bind(re)))
|
||||
console.error(JSON.stringify(pageErrors, null, 2));
|
||||
}
|
||||
|
||||
phantom.onError = function(msg, trace) {
|
||||
showError(msg, trace);
|
||||
phantom.exit(1);
|
||||
};
|
||||
|
||||
page.open(address, function(status) {
|
||||
if (status !== 'success') {
|
||||
console.log('FAIL to load the address');
|
||||
phantom.exit(1);
|
||||
}
|
||||
|
||||
|
||||
page.evaluate(function(filterStr) {
|
||||
var GLOBAL_TIMEOUT = 60 * 1000;
|
||||
|
||||
function format(tpl) {
|
||||
var values = Array.prototype.slice.call(arguments, 1);
|
||||
return tpl.replace(/(%s)/g, values.shift.bind(values));
|
||||
}
|
||||
|
||||
function takeScreenshot(name) {
|
||||
log("screenshot %s", name.replace(/[^\w]/g, "_"));
|
||||
}
|
||||
|
||||
function log(msg) {
|
||||
console.log("PHANTOMJS:", format.apply(null, arguments));
|
||||
}
|
||||
|
||||
function each(things, runner, done) {
|
||||
if (!things.length) return done();
|
||||
var thing = things.shift();
|
||||
|
||||
runner(thing, function(err) {
|
||||
if (err) return done(err);
|
||||
each(things, runner, done);
|
||||
});
|
||||
}
|
||||
|
||||
function filterTests(tests, filter) {
|
||||
if (!filter) return tests;
|
||||
var re = new RegExp(filter);
|
||||
return tests.filter(re.test.bind(re));
|
||||
}
|
||||
|
||||
function fail(count, test) {
|
||||
log("not ok %s %s", count, test.title);
|
||||
log("error # %s", test.error || "test.error is missing");
|
||||
}
|
||||
|
||||
window.c9Test.onReady = function() {
|
||||
log("# starting c9 tests");
|
||||
|
||||
var count = 0;
|
||||
var failCount = 0;
|
||||
var timeout = null;
|
||||
|
||||
function runTest(name, next) {
|
||||
var subtests = 0;
|
||||
var failed = false;
|
||||
|
||||
window.mocha._onSubTest = function(test) {
|
||||
subtests++;
|
||||
if (test.state == "failed") {
|
||||
failed = true;
|
||||
takeScreenshot(name + "_" + subtests);
|
||||
}
|
||||
};
|
||||
|
||||
watchForTimeout(name);
|
||||
|
||||
window.c9Test.run(name, function(errors, out) {
|
||||
log("# %s", name);
|
||||
|
||||
out.tests.forEach(function(test, i) {
|
||||
count++;
|
||||
if (test.state == "passed") return log("ok %s %s", count, test.title);
|
||||
if (test.state == "failed") return fail(count, test);
|
||||
log("ok %s # SKIP %s", count, test.title);
|
||||
});
|
||||
|
||||
if (failed) {
|
||||
takeScreenshot(name + "_after");
|
||||
failCount++;
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
function done() {
|
||||
if (!timeout) return; // Don't call next twice, if timeout isn't set done has already been called
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
next();
|
||||
}
|
||||
|
||||
function watchForTimeout(name) {
|
||||
timeout = window.setTimeout(function() {
|
||||
count++;
|
||||
fail(count, {
|
||||
title: name,
|
||||
error: "test file " + name + " timed out after " + (GLOBAL_TIMEOUT / 1000) + "s"
|
||||
});
|
||||
failed = true;
|
||||
done();
|
||||
}, GLOBAL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
each(filterTests(window.c9Test.allFiles, filterStr), runTest, function() {
|
||||
if (!count) log("not ok %s %s", count, "test found");
|
||||
console.log("%s..%s..%s", window.c9Test.allFiles.length, count, failCount);
|
||||
log("exit");
|
||||
});
|
||||
|
||||
};
|
||||
}, filter);
|
||||
|
||||
});
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
filefinder - find files matching a specific file name pattern that are not found on a specified blacklist
|
||||
|
||||
=example=
|
||||
new filefinder("/tmp", "files", ".*_test.js", "/tmp/blacklist", function(err, res) {
|
||||
console.log(util.inspect(res));
|
||||
});
|
||||
|
||||
--dirlist--
|
||||
one_test.js
|
||||
two_test.js
|
||||
three.js
|
||||
four_test.js
|
||||
|
||||
--blacklist--
|
||||
one_test.js
|
||||
files/two_test.js
|
||||
four
|
||||
|
||||
--result--
|
||||
{ countOk: 2,
|
||||
countPatternMis: 1,
|
||||
countBl: 1,
|
||||
list: [ 'files/four_test.js', 'files/one_test.js' ] }
|
||||
|
||||
*/
|
||||
|
||||
var fs = require("fs");
|
||||
var util = require("util");
|
||||
var path = require("path");
|
||||
|
||||
|
||||
var DEBUGMODE = false;
|
||||
|
||||
|
||||
|
||||
function filefinder(basedir, subdir, fnpattern, blacklistfile, cb) {
|
||||
if (DEBUGMODE) console.log("\n\n\n\nfilefinder()");
|
||||
if (cb) cb();
|
||||
}
|
||||
|
||||
filefinder.prototype.find = function(basedir, subdir, fnpattern, blacklistfile, cb) {
|
||||
if (DEBUGMODE) console.log("\n\n\n\nfind(%s, %s, %s)", path.join(basedir, subdir), fnpattern, blacklistfile);
|
||||
this.basedir = basedir;
|
||||
this.subdir = subdir;
|
||||
this.pattern = fnpattern;
|
||||
this.blacklistfile = blacklistfile;
|
||||
|
||||
this.flist = [];
|
||||
this.countBlacklisted = 0;
|
||||
this.countPatternMis = 0;
|
||||
var _self = this;
|
||||
|
||||
_self.getBlacklist(this.blacklistfile, function(err, blacklist) {
|
||||
_self.treewalk(basedir, subdir, fnpattern, blacklist, _self.flist, function(err, res) {
|
||||
// compose results object
|
||||
var result = {
|
||||
countOk: _self.flist.length,
|
||||
countPatternMis: _self.countPatternMis,
|
||||
countBl: _self.countBlacklisted,
|
||||
list: _self.flist,
|
||||
blacklist: blacklist
|
||||
};
|
||||
cb(null, result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
filefinder.prototype.getBlacklist = function(filename, cb) {
|
||||
if (DEBUGMODE) console.log("getBlacklist()");
|
||||
var _self = this;
|
||||
_self.getFileInArray(filename, function(err, blacklist) {
|
||||
if (err) return cb(new Error("error reading blacklist file"));
|
||||
_self.arrayRemoveCrap(blacklist, function(err, blacklist) {
|
||||
if (DEBUGMODE) console.log("--blacklist--\nlength: %s\n%s\n-------------", blacklist.length, util.inspect(blacklist));
|
||||
cb(null, blacklist);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// read a text file and make each line a member of an array
|
||||
filefinder.prototype.getFileInArray = function(filename, cb) {
|
||||
if (DEBUGMODE) console.log("getFileInArray()");
|
||||
var array = [];
|
||||
fs.exists(filename, function (exists) {
|
||||
if (!exists) return cb(null, array);
|
||||
fs.readFile(filename, function(err, data) {
|
||||
if(err) return cb(err);
|
||||
array = data.toString().split("\n");
|
||||
cb(null, array);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
filefinder.prototype.arrayRemoveCrap = function(array, cb) {
|
||||
if (DEBUGMODE) console.log("arrayRemoveCrap()");
|
||||
|
||||
function removeComments(element, index, array) {
|
||||
// clean-up whitespace, comments etc.
|
||||
array[index] = array[index].replace(/\s*#.*|^\s*|\s*$/g, '');
|
||||
}
|
||||
array.forEach(removeComments);
|
||||
|
||||
array = array.filter(function(e) {
|
||||
return e !== "";
|
||||
});
|
||||
|
||||
cb(null, array);
|
||||
};
|
||||
|
||||
|
||||
filefinder.prototype.treewalk = function(basedir, subdir, fnpattern, blacklist, foundfilesarray, cb) {
|
||||
var _self = this;
|
||||
var fulldir = path.join(basedir, subdir);
|
||||
if (DEBUGMODE) console.log(">treewalk (dir: %s, fnpattern: %s)", fulldir, fnpattern);
|
||||
var results = [];
|
||||
|
||||
fs.readdir(fulldir, function(err, list) {
|
||||
if (err) return cb(err);
|
||||
var i = 0;
|
||||
|
||||
function next() {
|
||||
var file = list[i++];
|
||||
if (!file) return cb(null, foundfilesarray.length);
|
||||
var partName = path.join(subdir, file).replace(/\\/g, "/");
|
||||
var filepath = path.join(fulldir, file);
|
||||
|
||||
// get file info
|
||||
fs.stat(filepath, function(err, stat) {
|
||||
if (stat && stat.isDirectory()) {
|
||||
if (blacklist && blacklist.indexOf(partName + "/") !== -1)
|
||||
return next();
|
||||
// directory, so recurse
|
||||
_self.treewalk(basedir, partName, fnpattern, blacklist, foundfilesarray, function(err, res) {
|
||||
results = results.concat(res);
|
||||
next();
|
||||
});
|
||||
}
|
||||
else {
|
||||
// file found, matches pattern?
|
||||
if (file.match(fnpattern) === null) {
|
||||
_self.countPatternMis++;
|
||||
return next();
|
||||
}
|
||||
|
||||
// check if blacklisted
|
||||
if (!blacklist || blacklist.indexOf(partName) == -1) {
|
||||
if (DEBUGMODE) console.log("file found: %s", partName);
|
||||
foundfilesarray.push(partName);
|
||||
}
|
||||
else {
|
||||
_self.countBlacklisted++;
|
||||
if (DEBUGMODE) console.log("File blacklisted: ", partName);
|
||||
}
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
// export the class
|
||||
module.exports = new filefinder();
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
"use strict";
|
||||
|
||||
var path = require("path");
|
||||
var spawn = require("child_process").spawn;
|
||||
var phantomjs = require("phantomjs-prebuilt");
|
||||
var binPath = phantomjs.path;
|
||||
var argv = require("optimist").usage("Usage: $0 ", {
|
||||
"help": {alias: "h", description: "Display the usage", required: false},
|
||||
"branch": {description: "github branch for stacktrace", required: false},
|
||||
"filter": {description: "test pattern", required: false},
|
||||
"host": {description: "url of the test server", required: false},
|
||||
}).argv;
|
||||
|
||||
var phantomRunner = path.join(__dirname, "client-integration/run-client-integration.phantom.js");
|
||||
|
||||
var args = [phantomRunner, argv.host || "", argv.filter || "", argv.branch || ""];
|
||||
|
||||
console.log("executing: %s %s", binPath, args.join(" "));
|
||||
|
||||
var child = spawn(binPath, args);
|
||||
|
||||
|
||||
child.stdout.pipe(process.stdout);
|
||||
child.stderr.pipe(process.stderr);
|
||||
child.on("exit", function(code) {
|
||||
process.exit(code);
|
||||
});
|
Ładowanie…
Reference in New Issue