8c3c1b6c0f
The original implementation of 'testAsync' in mjsunit.js required to put the call to '%AbortJS' into an 'eval' statement. The reason is that this call requires the flag --allow-natives-syntax to be set, but the flag is not set in all mjsunit tests. With the use of 'eval' compilation errors can be avoided. The problem with this approach was that the fuzzer started to produce test cases which include the line 'eval("%AbortJS(message)");', and this line crashes intentionally. Different to the line '%Abort(message)', however, the 'eval' statement cannot be filtered so easily in the fuzzer. Therefore I pulled the implementation of 'testAsync' into a separate file to avoid the 'eval'. Additional changes: I use '===' now instead of 'deepEquals' in AsyncAssertion.equals because 'deepEquals' is not available outside mjsunit.js. Using '===' seems more appropriate anyways because for all tests but one it is sufficient, and it is more precise than deepEquals. R=gsathya@chromium.org Bug: chromium:774841 Change-Id: I47270aa63ff5a1d6aa76a771f9276eaaf579c5ac Reviewed-on: https://chromium-review.googlesource.com/1156598 Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Commit-Queue: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#54833}
118 lines
3.4 KiB
JavaScript
118 lines
3.4 KiB
JavaScript
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --allow-natives-syntax
|
|
|
|
// Used for async tests. See definition below for more documentation.
|
|
var testAsync;
|
|
|
|
(function () { // Scope for utility functions.
|
|
/**
|
|
* This is to be used through the testAsync helper function defined
|
|
* below.
|
|
*
|
|
* This requires the --allow-natives-syntax flag to allow calling
|
|
* runtime functions.
|
|
*
|
|
* There must be at least one assertion in an async test. A test
|
|
* with no assertions will fail.
|
|
*
|
|
* @example
|
|
* testAsync(assert => {
|
|
* assert.plan(1) // There should be one assertion in this test.
|
|
* Promise.resolve(1)
|
|
* .then(val => assert.equals(1, val),
|
|
* assert.unreachable);
|
|
* })
|
|
*/
|
|
class AsyncAssertion {
|
|
constructor(test, name) {
|
|
this.expectedAsserts_ = -1;
|
|
this.actualAsserts_ = 0;
|
|
this.test_ = test;
|
|
this.name_ = name || '';
|
|
}
|
|
|
|
/**
|
|
* Sets the number of expected asserts in the test. The test fails
|
|
* if the number of asserts computed after running the test is not
|
|
* equal to this specified value.
|
|
* @param {number} expectedAsserts
|
|
*/
|
|
plan(expectedAsserts) {
|
|
this.expectedAsserts_ = expectedAsserts;
|
|
}
|
|
|
|
fail(expectedText, found) {
|
|
let message = formatFailureText(expectedText, found);
|
|
message += "\nin test:" + this.name_
|
|
message += "\n" + Function.prototype.toString.apply(this.test_);
|
|
%AbortJS(message);
|
|
}
|
|
|
|
equals(expected, found, name_opt) {
|
|
this.actualAsserts_++;
|
|
if (expected !== found) {
|
|
this.fail(prettyPrinted(expected), found, name_opt);
|
|
}
|
|
}
|
|
|
|
unreachable() {
|
|
let message = "Failure: unreachable in test: " + this.name_;
|
|
message += "\n" + Function.prototype.toString.apply(this.test_);
|
|
%AbortJS(message);
|
|
}
|
|
|
|
unexpectedRejection(details) {
|
|
return (error) => {
|
|
let message =
|
|
"Failure: unexpected Promise rejection in test: " + this.name_;
|
|
if (details) message += "\n @" + details;
|
|
if (error instanceof Error) {
|
|
message += "\n" + String(error.stack);
|
|
} else {
|
|
message += "\n" + String(error);
|
|
}
|
|
message += "\n\n" + Function.prototype.toString.apply(this.test_);
|
|
%AbortJS(message);
|
|
};
|
|
}
|
|
|
|
drainMicrotasks() {
|
|
%RunMicrotasks();
|
|
}
|
|
|
|
done_() {
|
|
if (this.expectedAsserts_ === -1) {
|
|
let message = "Please call t.plan(count) to initialize test harness " +
|
|
"with correct assert count (Note: count > 0)";
|
|
%AbortJS(message);
|
|
}
|
|
|
|
if (this.expectedAsserts_ !== this.actualAsserts_) {
|
|
let message = "Expected asserts: " + this.expectedAsserts_;
|
|
message += ", Actual asserts: " + this.actualAsserts_;
|
|
message += "\nin test: " + this.name_;
|
|
message += "\n" + Function.prototype.toString.apply(this.test_);
|
|
%AbortJS(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** This is used to test async functions and promises.
|
|
* @param {testCallback} test - test function
|
|
* @param {string} [name] - optional name of the test
|
|
*
|
|
*
|
|
* @callback testCallback
|
|
* @param {AsyncAssertion} assert
|
|
*/
|
|
testAsync = function(test, name) {
|
|
let assert = new AsyncAssertion(test, name);
|
|
test(assert);
|
|
%RunMicrotasks();
|
|
assert.done_();
|
|
}
|
|
})();
|