[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: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Mathias Bynens <mathias@chromium.org> Cr-Commit-Position: refs/heads/master@{#52882}
This commit is contained in:
parent
9011927acd
commit
938761ab60
@ -0,0 +1,11 @@
|
||||
// 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);
|
@ -0,0 +1,12 @@
|
||||
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
|
||||
|
@ -0,0 +1,14 @@
|
||||
// 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");
|
@ -0,0 +1,10 @@
|
||||
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})
|
11
test/message/mjsunit/fail/assert-promise-result-rejects.js
Normal file
11
test/message/mjsunit/fail/assert-promise-result-rejects.js
Normal file
@ -0,0 +1,11 @@
|
||||
// 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')});
|
12
test/message/mjsunit/fail/assert-promise-result-rejects.out
Normal file
12
test/message/mjsunit/fail/assert-promise-result-rejects.out
Normal file
@ -0,0 +1,12 @@
|
||||
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})
|
||||
|
||||
|
11
test/message/mjsunit/fail/assert-promise-result-resolves.js
Normal file
11
test/message/mjsunit/fail/assert-promise-result-resolves.js
Normal file
@ -0,0 +1,11 @@
|
||||
// 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)});
|
13
test/message/mjsunit/fail/assert-promise-result-resolves.out
Normal file
13
test/message/mjsunit/fail/assert-promise-result-resolves.out
Normal file
@ -0,0 +1,13 @@
|
||||
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})
|
||||
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
// 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)});
|
@ -0,0 +1 @@
|
||||
6254
|
@ -0,0 +1,16 @@
|
||||
// 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});
|
@ -0,0 +1,11 @@
|
||||
// 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)});
|
@ -0,0 +1 @@
|
||||
1254
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
assertPromiseResult = function(promise, success, fail) {
|
||||
// Use --allow-natives-syntax to use this function. Note that this function
|
||||
// overwrites {failWithMessage} permanently with %AbortJS.
|
||||
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);
|
||||
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
||||
|
||||
var test_promise =
|
||||
promise.then(
|
||||
result => {
|
||||
try {
|
||||
success(result);
|
||||
} catch (e) {
|
||||
failWithMessage(String(e));
|
||||
}
|
||||
},
|
||||
result => {
|
||||
fail(result);
|
||||
assertPromiseResult = function(promise, success, fail) {
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user