Skip to content

Commit

Permalink
Handle idlharness.js expected errors as an IdlArray.assert_throw opti…
Browse files Browse the repository at this point in the history
…on (#10164)

* Handle idlharness.js expected errors as an IdlArray.assert_throw option
  • Loading branch information
lukebjerring committed Mar 28, 2018
1 parent 94ab26e commit 355c2d7
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 15 deletions.
78 changes: 63 additions & 15 deletions resources/idlharness.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,28 @@ var fround =
})();
//@}

/// IdlHarnessError ///
// Entry point
self.IdlHarnessError = function(message)
//@{
{
/**
* Message to be printed as the error's toString invocation.
*/
this.message = message;
};

IdlHarnessError.prototype = Object.create(Error.prototype);

//@}
IdlHarnessError.prototype.toString = function()
//@{
{
return this.message;
};

//@}

/// IdlArray ///
// Entry point
self.IdlArray = function()
Expand Down Expand Up @@ -217,7 +239,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)

if (options && options.only && options.except)
{
throw "The only and except options can't be used together."
throw new IdlHarnessError("The only and except options can't be used together.");
}

function should_skip(name)
Expand Down Expand Up @@ -280,7 +302,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
}
if (parsed_idl.name in this.members)
{
throw "Duplicate identifier " + parsed_idl.name;
throw new IdlHarnessError("Duplicate identifier " + parsed_idl.name);
}
switch(parsed_idl.type)
{
Expand Down Expand Up @@ -374,7 +396,7 @@ IdlArray.prototype.recursively_get_implements = function(interface_name)
ret = ret.concat(this.recursively_get_implements(ret[i]));
if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
{
throw "Circular implements statements involving " + ret[i];
throw new IdlHarnessError("Circular implements statements involving " + ret[i]);
}
}
return ret;
Expand Down Expand Up @@ -404,7 +426,7 @@ IdlArray.prototype.recursively_get_includes = function(interface_name)
ret = ret.concat(this.recursively_get_includes(ret[i]));
if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
{
throw "Circular includes statements involving " + ret[i];
throw new IdlHarnessError("Circular includes statements involving " + ret[i]);
}
}
return ret;
Expand Down Expand Up @@ -533,7 +555,7 @@ IdlArray.prototype.is_json_type = function(type)
function exposure_set(object, default_set) {
var exposed = object.extAttrs.filter(function(a) { return a.name == "Exposed" });
if (exposed.length > 1 || exposed.length < 0) {
throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed;
throw new IdlHarnessError("Unexpected Exposed extended attributes on " + memberName + ": " + exposed);
}

if (exposed.length === 0) {
Expand Down Expand Up @@ -567,7 +589,33 @@ function exposed_in(globals) {
return globals.indexOf("Worker") >= 0 ||
globals.indexOf("ServiceWorker") >= 0;
}
throw "Unexpected global object";
throw new IdlHarnessError("Unexpected global object");
}

//@}
/**
* Asserts that the given error message is thrown for the given function.
* @param {string|IdlHarnessError} error Expected Error message.
* @param {Function} idlArrayFunc Function operating on an IdlArray that should throw.
*/
IdlArray.prototype.assert_throws = function(error, idlArrayFunc)
//@{
{
try {
idlArrayFunc.call(this, this);
throw new IdlHarnessError(`${idlArrayFunc} did not throw the expected IdlHarnessError`);
} catch (e) {
if (e instanceof AssertionError) {
throw e;
}
// Assertions for behaviour of the idlharness.js engine.
if (error instanceof IdlHarnessError) {
error = error.message;
}
if (e.message !== error) {
throw new IdlHarnessError(`${idlArrayFunc} threw ${e}, not the expected IdlHarnessError`);
}
}
}

//@}
Expand All @@ -583,7 +631,7 @@ IdlArray.prototype.test = function()
if (!(parsed_idl.name in this.members)
|| !(this.members[parsed_idl.name] instanceof IdlInterface))
{
throw "Partial interface " + parsed_idl.name + " with no original interface";
throw new IdlHarnessError("Partial interface " + parsed_idl.name + " with no original interface");
}
if (parsed_idl.extAttrs)
{
Expand Down Expand Up @@ -848,7 +896,7 @@ IdlArray.prototype.assert_type_is = function(value, type)

if (!(type in this.members))
{
throw "Unrecognized type " + type;
throw new IdlHarnessError("Unrecognized type " + type);
}

if (this.members[type] instanceof IdlInterface)
Expand Down Expand Up @@ -876,7 +924,7 @@ IdlArray.prototype.assert_type_is = function(value, type)
}
else
{
throw "Type " + type + " isn't an interface or dictionary";
throw new IdlHarnessError("Type " + type + " isn't an interface or dictionary");
}
};
//@}
Expand Down Expand Up @@ -1345,13 +1393,13 @@ IdlInterface.prototype.test_self = function()
{
var aliasAttrs = this.extAttrs.filter(function(o) { return o.name === "LegacyWindowAlias"; });
if (aliasAttrs.length > 1) {
throw "Invalid IDL: multiple LegacyWindowAlias extended attributes on " + this.name;
throw new IdlHarnessError("Invalid IDL: multiple LegacyWindowAlias extended attributes on " + this.name);
}
if (this.is_callback()) {
throw "Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this.name;
throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this.name);
}
if (this.exposureSet.indexOf("Window") === -1) {
throw "Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " which is not exposed in Window";
throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " which is not exposed in Window");
}
// TODO: when testing of [NoInterfaceObject] interfaces is supported,
// check that it's not specified together with LegacyWindowAlias.
Expand All @@ -1360,7 +1408,7 @@ IdlInterface.prototype.test_self = function()

var rhs = aliasAttrs[0].rhs;
if (!rhs) {
throw "Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " without identifier";
throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " without identifier");
}
var aliases;
if (rhs.type === "identifier-list") {
Expand Down Expand Up @@ -1733,7 +1781,7 @@ IdlInterface.prototype.test_member_const = function(member)
//@{
{
if (!this.has_constants()) {
throw "Internal error: test_member_const called without any constants";
throw new IdlHarnessError("Internal error: test_member_const called without any constants");
}

test(function()
Expand Down Expand Up @@ -2289,7 +2337,7 @@ IdlInterface.prototype.test_object = function(desc)
{
if (!(current_interface.name in this.array.members))
{
throw "Interface " + current_interface.name + " not found (inherited by " + this.name + ")";
throw new IdlHarnessError("Interface " + current_interface.name + " not found (inherited by " + this.name + ")");
}
if (current_interface.prevent_multiple_testing && current_interface.already_tested)
{
Expand Down
19 changes: 19 additions & 0 deletions resources/test/tests/idlharness/basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@
test(function() {
assert_equals(typeof WebIDL2.parse("interface Foo {};"), "object");
}, 'WebIDL2 parse method should produce an AST for correct WebIDL');
test(function() {
let i = new IdlArray();
i.add_untested_idls('partial interface A {};');
i.assert_throws( new IdlHarnessError("Partial interface A with no original interface"), i.test);
}, 'assert_throws should handle IdlHarnessError');
test(function() {
let i = new IdlArray();
i.add_untested_idls('partial interface A {};');
i.assert_throws( "Partial interface A with no original interface", i.test);
}, 'assert_throws should handle IdlHarnessError from message');
test(function () {
try {
let i = new IdlArray();
i.add_untested_idls('interface A {};');
i.assert_throws( "Partial interface A with no original interface", i.test);
} catch (e) {
assert_true(e instanceof IdlHarnessError);
}
}, 'assert_throws should throw if no IdlHarnessError thrown');
</script>
</body>
</html>
Expand Down
7 changes: 7 additions & 0 deletions resources/testharness.js
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,13 @@ policies and contribution forms [3].
}
expose(assert_readonly, "assert_readonly");

/**
* Assert an Exception with the expected code is thrown.
*
* @param {object|number|string} code The expected exception code.
* @param {Function} func Function which should throw.
* @param {string} description Error description for the case that the error is not thrown.
*/
function assert_throws(code, func, description)
{
try {
Expand Down

0 comments on commit 355c2d7

Please sign in to comment.