Bug 1323324 tests. r=till

--HG--
rename : dom/promise/tests/test_promise_xrays.html => dom/promise/tests/test_promise_argument_xrays.html
This commit is contained in:
Boris Zbarsky 2016-12-19 15:38:44 -08:00
parent 94a9f0d729
commit 60309db42a
9 changed files with 366 additions and 0 deletions

View File

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/TestFunctions.h"
#include "mozilla/dom/TestFunctionsBinding.h"
namespace mozilla {
namespace dom {
@ -16,5 +17,19 @@ TestFunctions::ThrowUncatchableException(GlobalObject& aGlobal,
aRv.ThrowUncatchableException();
}
/* static */ Promise*
TestFunctions::PassThroughPromise(GlobalObject& aGlobal, Promise& aPromise)
{
return &aPromise;
}
/* static */ already_AddRefed<Promise>
TestFunctions::PassThroughCallbackPromise(GlobalObject& aGlobal,
PromiseReturner& aCallback,
ErrorResult& aRv)
{
return aCallback.Call(aRv);
}
}
}

View File

@ -14,10 +14,21 @@
namespace mozilla {
namespace dom {
class Promise;
class PromiseReturner;
class TestFunctions : public NonRefcountedDOMObject {
public:
static void
ThrowUncatchableException(GlobalObject& aGlobal, ErrorResult& aRv);
static Promise*
PassThroughPromise(GlobalObject& aGlobal, Promise& aPromise);
static already_AddRefed<Promise>
PassThroughCallbackPromise(GlobalObject& aGlobal,
PromiseReturner& aCallback,
ErrorResult& aRv);
};
} // namespace dom

View File

@ -5,3 +5,6 @@
[test_on_promise_settled_duplicates.html]
[test_promise_xrays.html]
support-files = file_promise_xrays.html
[test_promise_argument_xrays.html]
support-files = file_promise_xrays.html file_promise_argument_tests.js
skip-if = debug == false

View File

@ -0,0 +1,134 @@
/*
* This file is meant to provide common infrastructure for several consumers.
* The consumer is expected to define the following things:
*
* 1) An verifyPromiseGlobal function which does whatever test the consumer
* wants.
* 2) An isXrayArgumentTest global boolean, because some of these tests act
* differenly based on that boolean.
* 3) A function named getPromise. This function is given a global object and a
* single argument to use for getting the promise. The getPromise function
* is expected to trigger the canonical Promise.resolve for the given global
* with the given argument in some way that depends on the test, and return
* the result.
* 4) A subframe (frames[0]) which can be used as a second global for creating
* promises.
*/
var label = parent;
function passBasicPromise() {
var p1 = Promise.resolve();
verifyPromiseGlobal(p1, window, "Promise.resolve return value 1");
var p2 = getPromise(window, p1);
is(p1, p2, "Basic promise should just pass on through");
return p2;
}
function passPrimitive(global) {
var p = getPromise(global, 5);
verifyPromiseGlobal(p, global, "Promise wrapping primitive");
return p.then(function(arg) {
is(arg, 5, "Should have the arg we passed in");
});
}
function passThenable(global) {
var called = false;
var thenable = {
then: function(f) {
called = true;
f(7);
}
};
var p = getPromise(global, thenable);
verifyPromiseGlobal(p, global, "Promise wrapping thenable");
return p.then(function(arg) {
ok(called, "Thenable should have been called");
is(arg, 7, "Should have the arg our thenable passed in");
});
}
function passWrongPromiseWithMatchingConstructor() {
var p1 = Promise.resolve();
verifyPromiseGlobal(p1, window, "Promise.resolve() return value 2");
p1.constructor = frames[0].Promise;
var p2 = getPromise(frames[0], p1);
// The behavior here will depend on whether we're touching frames[0] via Xrays
// or not. If we are not, the current compartment while getting our promise
// will be that of frames[0]. If we are, it will be our window's compartment.
if (isXrayArgumentTest) {
isnot(p1, p2, "Should have wrapped the Promise in a new promise, because its constructor is not matching the current-compartment Promise constructor");
verifyPromiseGlobal(p2, window, "Promise wrapping xrayed promise with therefore non-matching constructor");
} else {
is(p1, p2, "Should have left the Promise alone because its constructor matched");
}
return p2;
}
function passCorrectPromiseWithMismatchedConstructor() {
var p1 = Promise.resolve(9);
verifyPromiseGlobal(p1, window, "Promise.resolve() return value 3");
p1.constructor = frames[0].Promise;
var p2 = getPromise(window, p1);
isnot(p1, p2,
"Should have wrapped promise in a new promise, since its .constructor was wrong");
verifyPromiseGlobal(p2, window,
"Promise wrapping passed-in promise with mismatched constructor");
return p2.then(function(arg) {
is(arg, 9, "Should have propagated along our resolution value");
});
}
function passPromiseToOtherGlobal() {
var p1 = Promise.resolve();
verifyPromiseGlobal(p1, window, "Promise.resolve() return value 4");
var p2 = getPromise(frames[0], p1);
// The behavior here will depend on whether we're touching frames[0] via Xrays
// or not. If we are not, the current compartment while getting our promise
// will be that of frames[0]. If we are, it will be our window's compartment.
if (isXrayArgumentTest) {
is(p1, p2, "Should have left the Promise alone, because its constructor matches the current compartment's constructor");
} else {
isnot(p1, p2, "Should have wrapped promise in a promise from the other global");
verifyPromiseGlobal(p2, frames[0],
"Promise wrapping passed-in basic promise");
}
return p2;
}
function passPromiseSubclass() {
class PromiseSubclass extends Promise {
constructor(func) {
super(func);
}
}
var p1 = PromiseSubclass.resolve(11);
verifyPromiseGlobal(p1, window, "PromiseSubclass.resolve() return value");
var p2 = getPromise(window, p1);
isnot(p1, p2,
"Should have wrapped promise subclass in a new promise");
verifyPromiseGlobal(p2, window,
"Promise wrapping passed-in promise subclass");
return p2.then(function(arg) {
is(arg, 11, "Should have propagated along our resolution value from subclass");
});
}
function runPromiseArgumentTests(finishFunc) {
Promise.resolve()
.then(passBasicPromise)
.then(passPrimitive.bind(undefined, window))
.then(passPrimitive.bind(undefined, frames[0]))
.then(passThenable.bind(undefined, window))
.then(passThenable.bind(undefined, frames[0]))
.then(passWrongPromiseWithMatchingConstructor)
.then(passCorrectPromiseWithMismatchedConstructor)
.then(passPromiseToOtherGlobal)
.then(passPromiseSubclass)
.then(finishFunc)
.catch(function(e) {
ok(false, `Exception thrown: ${e}@${location.pathname}:${e.lineNumber}:${e.columnNumber}`);
finishFunc();
});
}

View File

@ -16,3 +16,9 @@ support-files = file_promise_and_timeout_ordering.js
support-files = file_promise_and_timeout_ordering.js
[test_species_getter.html]
[test_webassembly_compile.html]
[test_promise_argument.html]
support-files = file_promise_argument_tests.js
skip-if = debug == false
[test_promise_callback_retval.html]
support-files = file_promise_argument_tests.js
skip-if = debug == false

View File

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1323324
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1323324</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="file_promise_argument_tests.js"></script>
<script type="application/javascript">
/** Test for Bug 1323324 **/
SimpleTest.waitForExplicitFinish();
function verifyPromiseGlobal(p, global, msg) {
// SpecialPowers.Cu.getGlobalForObject returns a SpecialPowers wrapper for
// the actual global. We want to grab the underlying object.
var globalWrapper = SpecialPowers.Cu.getGlobalForObject(p);
is(SpecialPowers.unwrap(globalWrapper), global,
msg + " should come from " + global.label);
}
const isXrayArgumentTest = false;
function getPromise(global, arg) {
return global.TestFunctions.passThroughPromise(arg);
}
addLoadEvent(function() {
frames[0].label = "child";
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]},
runPromiseArgumentTests.bind(undefined,
SimpleTest.finish));
});
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1323324">Mozilla Bug 1323324</a>
<p id="display"></p>
<div id="content" style="display: none">
<!-- A subframe so we have another global to work with -->
<iframe></iframe>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1233324
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1233324</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1233324">Mozilla Bug 1233324</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id="t" src="http://example.org/chrome/dom/promise/tests/file_promise_xrays.html"></iframe>
</div>
<pre id="test">
<script src="file_promise_argument_tests.js"></script>
<script type="application/javascript">
var win = $("t").contentWindow;
/** Test for Bug 1233324 **/
SimpleTest.waitForExplicitFinish();
function testLoadComplete() {
is(win.location.href, $("t").src, "Should have loaded the right thing");
nextTest();
}
function testHaveXray() {
is(typeof win.Promise.race, "function", "Should see a race() function");
var exception;
try {
win.Promise.wrappedJSObject.race;
} catch (e) {
exception = e;
}
is(exception, "Getting race", "Should have thrown the right exception");
is(win.wrappedJSObject.setupThrew, false, "Setup should not have thrown");
nextTest();
}
function verifyPromiseGlobal(p, _, msg) {
// SpecialPowers.Cu.getGlobalForObject returns a SpecialPowers wrapper for
// the actual global. We want to grab the underlying object.
var global = SpecialPowers.unwrap(SpecialPowers.Cu.getGlobalForObject(p));
// We expect our global to always be "window" here, because we're working over
// Xrays.
is(global, window, msg + " should come from " + window.label);
}
const isXrayArgumentTest = true;
function getPromise(global, arg) {
return global.TestFunctions.passThroughPromise(arg);
}
function testPromiseArgumentConversions() {
runPromiseArgumentTests(nextTest);
}
var tests = [
testLoadComplete,
testHaveXray,
testPromiseArgumentConversions,
];
function nextTest() {
if (tests.length == 0) {
SimpleTest.finish();
return;
}
tests.shift()();
}
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]},
nextTest);
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,49 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1323324
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1323324</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="file_promise_argument_tests.js"></script>
<script type="application/javascript">
/** Test for Bug 1323324 **/
SimpleTest.waitForExplicitFinish();
function verifyPromiseGlobal(p, global, msg) {
// SpecialPowers.Cu.getGlobalForObject returns a SpecialPowers wrapper for
// the actual global. We want to grab the underlying object.
var globalWrapper = SpecialPowers.Cu.getGlobalForObject(p);
is(SpecialPowers.unwrap(globalWrapper), global,
msg + " should come from " + global.label);
}
const isXrayArgumentTest = false;
function getPromise(global, arg) {
var func = new global.Function("x", "return x").bind(undefined, arg);
return TestFunctions.passThroughCallbackPromise(func);
}
addLoadEvent(function() {
frames[0].label = "child";
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]},
runPromiseArgumentTests.bind(undefined,
SimpleTest.finish));
});
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1323324">Mozilla Bug 1323324</a>
<p id="display"></p>
<div id="content" style="display: none">
<!-- A subframe so we have another global to work with -->
<iframe></iframe>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -5,8 +5,19 @@
*/
// A dumping ground for random testing functions
callback PromiseReturner = Promise<any>();
[Pref="dom.expose_test_interfaces"]
interface TestFunctions {
[Throws]
static void throwUncatchableException();
// Simply returns its argument. Can be used to test Promise
// argument processing behavior.
static Promise<any> passThroughPromise(Promise<any> arg);
// Returns whatever Promise the given PromiseReturner returned.
[Throws]
static Promise<any> passThroughCallbackPromise(PromiseReturner callback);
};