mirror of
https://github.com/servo/servo
synced 2026-04-28 18:37:39 +02:00
146 lines
5.1 KiB
JavaScript
146 lines
5.1 KiB
JavaScript
(function(root){
|
|
'use strict';
|
|
// testharness doesn't know about async test queues,
|
|
// so this wrapper takes care of that
|
|
|
|
/* USAGE:
|
|
runParallelAsyncHarness({
|
|
// list of data to test, must be array of objects.
|
|
// each object must contain a "name" property to describe the test
|
|
// besides name, the object can contain whatever data you need
|
|
tests: [
|
|
{name: "name of test 1", custom: "data"},
|
|
{name: "name of test 2", custom: "data"},
|
|
// ...
|
|
],
|
|
|
|
// number of tests (tests, not test-cases!) to run concurrently
|
|
testsPerSlice: 100,
|
|
|
|
// time in milliseconds a test-run takes
|
|
duration: 1000,
|
|
|
|
// test-cases to run for for the test - there must be at least one
|
|
// each case creates its separate async_test() instance
|
|
cases: {
|
|
// test case named "test1"
|
|
test1: {
|
|
// run as a async_test.step() this callback contains your primary assertions
|
|
start: function(testCaseKey, data, options){},
|
|
// run as a async_test.step() this callback contains assertions to be run
|
|
// when the test ended, immediately before teardown
|
|
done: function(testCaseKey, data, options){}
|
|
},
|
|
// ...
|
|
}
|
|
|
|
// all callbacks are optional:
|
|
|
|
// invoked for individual test before it starts so you can setup the environment
|
|
// like DOM, CSS, adding event listeners and such
|
|
setup: function(data, options){},
|
|
|
|
// invoked after a test ended, so you can clean up the environment
|
|
// like DOM, CSS, removing event listeners and such
|
|
teardown: function(data, options){},
|
|
|
|
// invoked before a batch of tests ("slice") are run concurrently
|
|
// tests is an array of test data objects
|
|
sliceStart: function(options, tests)
|
|
|
|
// invoked after a batch of tests ("slice") were run concurrently
|
|
// tests is an array of test data objects
|
|
sliceDone: function(options, tests)
|
|
|
|
// invoked once all tests are done
|
|
done: function(options){}
|
|
})
|
|
*/
|
|
root.runParallelAsyncHarness = function(options) {
|
|
if (!options.cases) {
|
|
throw new Error("Options don't contain test cases!");
|
|
}
|
|
|
|
var noop = function(){};
|
|
|
|
// add a 100ms buffer to the test timeout, just in case
|
|
var duration = Math.ceil(options.duration + 100);
|
|
|
|
// names of individual tests
|
|
var cases = Object.keys(options.cases);
|
|
|
|
// run tests in a batch of slices
|
|
// primarily not to overload weak devices (tablets, phones, …)
|
|
// with too many tests running simultaneously
|
|
var iteration = -1;
|
|
var testPerSlice = options.testsPerSlice || 100;
|
|
var slices = Math.ceil(options.tests.length / testPerSlice);
|
|
|
|
// initialize all async test cases
|
|
// Note: satisfying testharness.js needs to know all async tests before load-event
|
|
options.tests.forEach(function(data, index) {
|
|
data.cases = {};
|
|
cases.forEach(function(name) {
|
|
data.cases[name] = async_test(data.name + " / " + name, {timeout: options.timeout || 60000});
|
|
});
|
|
});
|
|
|
|
function runLoop() {
|
|
iteration++;
|
|
if (iteration >= slices) {
|
|
// no more slice, we're done
|
|
(options.done || noop)(options);
|
|
return;
|
|
}
|
|
|
|
// grab a slice of testss and initialize them
|
|
var offset = iteration * testPerSlice;
|
|
var tests = options.tests.slice(offset, offset + testPerSlice);
|
|
tests.forEach(function(data) {
|
|
(options.setup || noop)(data, options);
|
|
|
|
});
|
|
|
|
// kick off the current slice of tests
|
|
(options.sliceStart || noop)(options, tests);
|
|
|
|
// perform individual "start" test-case
|
|
tests.forEach(function(data) {
|
|
cases.forEach(function(name) {
|
|
data.cases[name].step(function() {
|
|
(options.cases[name].start || noop)(data.cases[name], data, options);
|
|
});
|
|
});
|
|
});
|
|
|
|
// conclude test (possibly abort)
|
|
setTimeout(function() {
|
|
tests.forEach(function(data) {
|
|
// perform individual "done" test-case
|
|
cases.forEach(function(name) {
|
|
data.cases[name].step(function() {
|
|
(options.cases[name].done || noop)(data.cases[name], data, options);
|
|
});
|
|
});
|
|
// clean up after individual test
|
|
(options.teardown || noop)(data, options);
|
|
// tell harness we're done with individual test-cases
|
|
cases.forEach(function(name) {
|
|
data.cases[name].done();
|
|
});
|
|
});
|
|
|
|
// finish the test for current slice of tests
|
|
(options.sliceDone || noop)(options, tests);
|
|
|
|
// next test please, give the browser 50ms to do catch its breath
|
|
setTimeout(runLoop, 50);
|
|
}, duration);
|
|
}
|
|
|
|
// allow DOMContentLoaded before actually doing something
|
|
setTimeout(runLoop, 100);
|
|
};
|
|
|
|
})(window);
|