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; ...@@ -135,7 +135,15 @@ var assertContains;
// Assert that a string matches a given regex. // Assert that a string matches a given regex.
var assertMatches; 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 assertPromiseResult;
var promiseTestChain; var promiseTestChain;
...@@ -555,35 +563,47 @@ var prettyPrinted; ...@@ -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) { assertPromiseResult = function(promise, success, fail) {
// Use --allow-natives-syntax to use this function. Note that this function const stack = (new Error()).stack;
// overwrites {failWithMessage} permanently with %AbortJS.
var test_promise = promise.then(
// We have to patch mjsunit because normal assertion failures just throw result => {
// exceptions which are swallowed in a then clause. try {
// We use eval here to avoid parsing issues with the natives syntax. if (--promiseTestCount == 0) testRunner.notifyDone();
if (!success) success = () => {}; if (success) success(result);
} catch (e) {
failWithMessage = (msg) => eval("%AbortJS(msg)"); // Use setTimeout to throw the error again to get out of the promise
if (!fail) { // chain.
fail = result => failWithMessage("assertPromiseResult failed: " + result); setTimeout(_ => {
} throw concatenateErrors(stack, e);
}, 0);
var test_promise = }
promise.then( },
result => { result => {
try { try {
success(result); if (--promiseTestCount == 0) testRunner.notifyDone();
} catch (e) { if (!fail) throw result;
failWithMessage(String(e));
}
},
result => {
fail(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(); 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