blob: 359701b84ac109ac1fa6893514a87b0301c61421 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/base/raf.html">
<link rel="import" href="/tracing/base/event_target.html">
<script>
'use strict';
tr.exportTo('tr.b.unittest', function() {
var realTvOnAnimationFrameError;
var realGlobalOnError;
var realGlobalHistoryPushState;
function installGlobalTestHooks(runner) {
realTvOnAnimationFrameError = tr.b.onAnimationFrameError;
tr.b.onAnimationFrameError = function(error) {
runner.results.addErrorForCurrentTest(error);
}
if (tr.isExported('global.onerror')) {
realGlobalOnError = global.onerror;
global.onerror = function(errorMsg, url, lineNumber) {
runner.results.addErrorForCurrentTest(
errorMsg + ' at ' + url + ':' + lineNumber);
if (realGlobalOnError)
return realGlobalOnError(errorMsg, url, lineNumber);
return false;
}
}
if (tr.isExported('global.history')) {
realGlobalHistoryPushState = global.history.pushState;
global.history.pushState = function() {
};
}
tr.b.unittest.addHTMLOutputForCurrentTest = function(element) {
runner.results.addHTMLOutputForCurrentTest(element);
}
if (tr.isExported('global.sessionStorage')) {
global.sessionStorage.clear();
}
var e = new tr.b.Event('tr-unittest-will-run');
TestRunner.dispatchEvent(e);
}
function uninstallGlobalTestHooks() {
if (tr.isExported('global.onerror')) {
global.onerror = realGlobalOnError;
realGlobalOnError = undefined;
}
tr.b.onAnimationFrameError = realTvOnAnimationFrameError;
realTvOnAnimationFrameError = undefined;
if (tr.isExported('global.history')) {
global.history.pushState = realGlobalHistoryPushState;
realGlobalHistoryPushState = undefined;
}
tr.b.unittest.addHTMLOutputForCurrentTest = undefined;
}
function TestRunner(results, testCases) {
this.results_ = results;
this.testCases_ = testCases;
this.pendingTestCases_ = [];
this.runOneTestCaseScheduled_ = false;
this.runCompletedPromise = undefined;
this.runCompletedResolver_ = undefined;
this.currentTestCase_ = undefined;
}
TestRunner.prototype = {
__proto__: Object.prototype,
beginRunning: function() {
if (this.pendingTestCases_.length)
throw new Error('Tests still running!');
this.runCompletedPromise = new Promise(function(resolve, reject) {
this.runCompletedResolver_ = {
resolve: resolve,
reject: reject
};
}.bind(this));
this.pendingTestCases_ = this.testCases_.slice(0);
this.scheduleRunOneTestCase_();
return this.runCompletedPromise;
},
beginToStopRunning: function() {
if (!this.runCompletedResolver_)
throw new Error('Still running');
this.pendingTestCases_ = [];
return this.runCompletedPromise;
},
get testCases() {
return this.testCases_;
},
get results() {
return this.results_;
},
scheduleRunOneTestCase_: function() {
if (this.runOneTestCaseScheduled_)
return;
this.runOneTestCaseScheduled_ = true;
tr.b.requestIdleCallback(this.runOneTestCase_, this);
},
runOneTestCase_: function() {
this.runOneTestCaseScheduled_ = false;
if (this.pendingTestCases_.length == 0) {
this.didFinishRunningAllTests_();
return;
}
this.currentTestCase_ = this.pendingTestCases_.splice(0, 1)[0];
this.results_.willRunTest(this.currentTestCase_);
if (!this.setUpCurrentTestCase_()) {
this.results_.didCurrentTestEnd();
this.currentTestCase_ = undefined;
this.scheduleRunOneTestCase_();
return;
}
this.runCurrentTestCase_().then(
function pass(result) {
try {
this.tearDownCurrentTestCase_(true);
if (result)
this.results_.setReturnValueFromCurrentTest(result);
this.results_.didCurrentTestEnd();
this.currentTestCase_ = undefined;
this.scheduleRunOneTestCase_();
} catch (e) {
this.hadInternalError_(e);
throw e;
}
}.bind(this),
function fail(error) {
try {
this.results_.addErrorForCurrentTest(error);
this.tearDownCurrentTestCase_(false);
this.results_.didCurrentTestEnd();
this.currentTestCase_ = undefined;
this.scheduleRunOneTestCase_();
} catch (e) {
this.hadInternalError_(e);
throw e;
}
}.bind(this));
},
setUpCurrentTestCase_: function() {
// Try setting it up. Return true if succeeded.
installGlobalTestHooks(this);
try {
this.currentTestCase_.setUp();
} catch (error) {
this.results_.addErrorForCurrentTest(error);
return false;
}
return true;
},
runCurrentTestCase_: function() {
return new Promise(function(resolve, reject) {
try {
var maybePromise = this.currentTestCase_.run();
} catch (error) {
reject(error);
return;
}
if (maybePromise !== undefined && maybePromise.then) {
maybePromise.then(
function(result) {
resolve(result);
},
function(error) {
reject(error);
});
} else {
resolve(maybePromise);
}
}.bind(this));
},
hadInternalError_: function(outerE) {
try {
this.results.didRunTests();
} catch (e) {
console.log('Had another error during hadInternalError_!');
console.log(e.stack);
}
this.runCompletedResolver_.reject(outerE);
this.runCompletedResolver_ = undefined;
},
tearDownCurrentTestCase_: function() {
try {
this.currentTestCase_.tearDown();
} catch (error) {
this.results_.addErrorForCurrentTest(error);
}
uninstallGlobalTestHooks();
},
didFinishRunningAllTests_: function() {
this.results.didRunTests();
this.runCompletedResolver_.resolve();
this.runCompletedResolver_ = undefined;
}
};
tr.b.EventTarget.decorate(TestRunner);
return {
TestRunner: TestRunner
};
});
</script>