Merge pull request +15278 from c9/sdk-tests

fix test runner in the sdk
pull/402/head
Harutyun Amirjanyan 2017-02-17 12:32:06 +04:00 zatwierdzone przez GitHub
commit 315b33525e
5 zmienionych plików z 412 dodań i 2 usunięć

Wyświetl plik

@ -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');

Wyświetl plik

@ -6,6 +6,5 @@
require("c9/inline-mocha")(module);
describe(__filename, function() {
setTimeout(4000);
it("should analyze 'hints.js'", require('./framework').buildTest("hints.js"));
});

Wyświetl plik

@ -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);
});

Wyświetl plik

@ -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();

Wyświetl plik

@ -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);
});