Commit 938761ab authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[mjsunit] Cleanup assertPromiseResult and add tests

assertPromiseResult caused tests to timeout when the result of the
promise was unexpected, e.g. rejected instead of the expected
fulfillment. This CL cleans up the implementation of
assertPromiseResult, adds better stack traces, and adds tests for all
the important cases I can think of.

R=mathias@chromium.org
CC=clemensh@chromium.org

Bug: v8:7570
Change-Id: I6ecb94fd3e5151502edf73c3bcdeb518b80fc81c
Reviewed-on: https://chromium-review.googlesource.com/1032786
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMathias Bynens <mathias@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52882}
parent 9011927a
// 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.
load("test/mjsunit/mjsunit.js");
let promise = new Promise(function(resolve, reject) {
throw new Error("Error in creation");
});
assertPromiseResult(promise);
test/mjsunit/mjsunit.js:{NUMBER}: Error: Error in creation
throw concatenateErrors(stack, e);
^
Error
at assertPromiseResult (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
at *%(basename)s:11:1
Error: Error in creation
at *%(basename)s:8:9
at new Promise (<anonymous>)
at *%(basename)s:7:15
// 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.
load("test/mjsunit/mjsunit.js");
let reject_handler;
let promise = new Promise(function(resolve, reject) {
reject_handler = reject;
});
assertPromiseResult(promise);
reject_handler("Reject with callback");
test/mjsunit/mjsunit.js:{NUMBER}: Error: Reject with callback
throw concatenateErrors(stack, e);
^
Error
at assertPromiseResult (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
at *%(basename)s:12:1
Error: Reject with callback
at concatenateErrors (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
at _ (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
// 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.
load("test/mjsunit/mjsunit.js");
let obj = {f: 1254};
assertPromiseResult(
Promise.reject(obj), (o) => {print(o.f)},
_ => {throw new Error('Error in reject handler')});
test/mjsunit/mjsunit.js:{NUMBER}: Error: Error in reject handler
throw concatenateErrors(stack, e);
^
Error
at assertPromiseResult (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
at *%(basename)s:9:1
Error: Error in reject handler
at _ *%(basename)s:11:17)
at promise.then.result (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
// 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.
load("test/mjsunit/mjsunit.js");
let obj = {f: 1254};
assertPromiseResult(
Promise.resolve(obj), _ => {throw new Error('Error in resolve handler')},
(o) => {print(o.f)});
test/mjsunit/mjsunit.js:{NUMBER}: Error: Error in resolve handler
throw concatenateErrors(stack, e);
^
Error
at assertPromiseResult (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
at *%(basename)s:9:1
Error: Error in resolve handler
at _ *%(basename)s:10:39)
at promise.then.result (test/mjsunit/mjsunit.js:{NUMBER}:{NUMBER})
// 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: --no-stress-opt
load("test/mjsunit/mjsunit.js");
let obj = {f: 6254};
assertPromiseResult(
Promise.reject(obj), assertUnreachable, (o) => {print(o.f)});
// 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: --no-stress-opt
load("test/mjsunit/mjsunit.js");
let resolve_handler;
let promise = new Promise(function(resolve, reject) {
resolve_handler = resolve;
});
assertPromiseResult(promise);
resolve_handler({f: 3463});
// 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: --no-stress-opt
load("test/mjsunit/mjsunit.js");
let obj = {f: 1254};
assertPromiseResult(Promise.resolve(obj), (o) => {print(o.f)});
......@@ -135,7 +135,15 @@ var assertContains;
// Assert that a string matches a given regex.
var assertMatches;
// Assert the result of a promise.
// Assert that a promise resolves or rejects.
// Parameters:
// {promise} - the promise
// {success} - optional - a callback which is called with the result of the
// resolving promise.
// {fail} - optional - a callback which is called with the result of the
// rejecting promise. If the promise is rejected but no {fail}
// callback is set, the error is propagated out of the promise
// chain.
var assertPromiseResult;
var promiseTestChain;
......@@ -555,35 +563,47 @@ var prettyPrinted;
}
};
function concatenateErrors(stack, exception) {
// If the exception does not contain a stack trace, wrap it in a new Error.
if (!exception.stack) exception = new Error(exception);
// If the exception already provides a special stack trace, we do not modify
// it.
if (typeof exception.stack !== 'string') {
return exception;
}
exception.stack = stack + '\n\n' + exception.stack;
return exception;
}
assertPromiseResult = function(promise, success, fail) {
// Use --allow-natives-syntax to use this function. Note that this function
// overwrites {failWithMessage} permanently with %AbortJS.
// We have to patch mjsunit because normal assertion failures just throw
// exceptions which are swallowed in a then clause.
// We use eval here to avoid parsing issues with the natives syntax.
if (!success) success = () => {};
failWithMessage = (msg) => eval("%AbortJS(msg)");
if (!fail) {
fail = result => failWithMessage("assertPromiseResult failed: " + result);
}
var test_promise =
promise.then(
result => {
try {
success(result);
} catch (e) {
failWithMessage(String(e));
}
},
result => {
const stack = (new Error()).stack;
var test_promise = promise.then(
result => {
try {
if (--promiseTestCount == 0) testRunner.notifyDone();
if (success) success(result);
} catch (e) {
// Use setTimeout to throw the error again to get out of the promise
// chain.
setTimeout(_ => {
throw concatenateErrors(stack, e);
}, 0);
}
},
result => {
try {
if (--promiseTestCount == 0) testRunner.notifyDone();
if (!fail) throw result;
fail(result);
} catch (e) {
// Use setTimeout to throw the error again to get out of the promise
// chain.
setTimeout(_ => {
throw concatenateErrors(stack, e);
}, 0);
}
)
.then((x)=> {
if (--promiseTestCount == 0) testRunner.notifyDone();
});
if (!promiseTestChain) promiseTestChain = Promise.resolve();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment