diff options
Diffstat (limited to 'dom/bindings/parser/tests/test_interface.py')
-rw-r--r-- | dom/bindings/parser/tests/test_interface.py | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/dom/bindings/parser/tests/test_interface.py b/dom/bindings/parser/tests/test_interface.py new file mode 100644 index 0000000000..c078a593bb --- /dev/null +++ b/dom/bindings/parser/tests/test_interface.py @@ -0,0 +1,459 @@ +import WebIDL + + +def WebIDLTest(parser, harness): + parser.parse("interface Foo { };") + results = parser.finish() + harness.ok(True, "Empty interface parsed without error.") + harness.check(len(results), 1, "Should be one production") + harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface") + iface = results[0] + harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName") + harness.check(iface.identifier.name, "Foo", "Interface has the right name") + harness.check(iface.parent, None, "Interface has no parent") + + parser.parse("interface Bar : Foo { };") + results = parser.finish() + harness.ok(True, "Empty interface parsed without error.") + harness.check(len(results), 2, "Should be two productions") + harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface") + iface = results[1] + harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName") + harness.check(iface.identifier.name, "Bar", "Interface has the right name") + harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), "Interface has a parent") + + parser = parser.reset() + parser.parse( + """ + interface QNameBase { + attribute long foo; + }; + + interface QNameDerived : QNameBase { + attribute long long foo; + attribute byte bar; + }; + """ + ) + results = parser.finish() + harness.check(len(results), 2, "Should be two productions") + harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface") + harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface") + harness.check(results[1].parent, results[0], "Inheritance chain is right") + harness.check(len(results[0].members), 1, "Expect 1 productions") + harness.check(len(results[1].members), 2, "Expect 2 productions") + base = results[0] + derived = results[1] + harness.check( + base.members[0].identifier.QName(), + "::QNameBase::foo", + "Member has the right QName", + ) + harness.check( + derived.members[0].identifier.QName(), + "::QNameDerived::foo", + "Member has the right QName", + ) + harness.check( + derived.members[1].identifier.QName(), + "::QNameDerived::bar", + "Member has the right QName", + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + interface A : B {}; + interface B : A {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + + harness.ok(threw, "Should not allow cycles in interface inheritance chains") + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + interface A : C {}; + interface C : B {}; + interface B : A {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + + harness.ok( + threw, "Should not allow indirect cycles in interface inheritance chains" + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + interface A; + interface B : A {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + + harness.ok( + threw, + "Should not allow inheriting from an interface that is only forward declared", + ) + + parser = parser.reset() + parser.parse( + """ + interface A { + constructor(); + constructor(long arg); + readonly attribute boolean x; + undefined foo(); + }; + partial interface A { + readonly attribute boolean y; + undefined foo(long arg); + }; + """ + ) + results = parser.finish() + harness.check(len(results), 2, "Should have two results with partial interface") + iface = results[0] + harness.check( + len(iface.members), 3, "Should have three members with partial interface" + ) + harness.check( + iface.members[0].identifier.name, + "x", + "First member should be x with partial interface", + ) + harness.check( + iface.members[1].identifier.name, + "foo", + "Second member should be foo with partial interface", + ) + harness.check( + len(iface.members[1].signatures()), + 2, + "Should have two foo signatures with partial interface", + ) + harness.check( + iface.members[2].identifier.name, + "y", + "Third member should be y with partial interface", + ) + harness.check( + len(iface.ctor().signatures()), + 2, + "Should have two constructors with partial interface", + ) + + parser = parser.reset() + parser.parse( + """ + partial interface A { + readonly attribute boolean y; + undefined foo(long arg); + }; + interface A { + constructor(); + constructor(long arg); + readonly attribute boolean x; + undefined foo(); + }; + """ + ) + results = parser.finish() + harness.check( + len(results), 2, "Should have two results with reversed partial interface" + ) + iface = results[1] + harness.check( + len(iface.members), + 3, + "Should have three members with reversed partial interface", + ) + harness.check( + iface.members[0].identifier.name, + "x", + "First member should be x with reversed partial interface", + ) + harness.check( + iface.members[1].identifier.name, + "foo", + "Second member should be foo with reversed partial interface", + ) + harness.check( + len(iface.members[1].signatures()), + 2, + "Should have two foo signatures with reversed partial interface", + ) + harness.check( + iface.members[2].identifier.name, + "y", + "Third member should be y with reversed partial interface", + ) + harness.check( + len(iface.ctor().signatures()), + 2, + "Should have two constructors with reversed partial interface", + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + interface A { + readonly attribute boolean x; + }; + interface A { + readonly attribute boolean y; + }; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok(threw, "Should not allow two non-partial interfaces with the same name") + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + partial interface A { + readonly attribute boolean x; + }; + partial interface A { + readonly attribute boolean y; + }; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok(threw, "Must have a non-partial interface for a given name") + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + dictionary A { + boolean x; + }; + partial interface A { + readonly attribute boolean y; + }; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, + "Should not allow a name collision between partial interface " + "and other object", + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + dictionary A { + boolean x; + }; + interface A { + readonly attribute boolean y; + }; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, "Should not allow a name collision between interface " "and other object" + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + dictionary A { + boolean x; + }; + interface A; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, + "Should not allow a name collision between external interface " + "and other object", + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + interface A { + readonly attribute boolean x; + }; + interface A; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, + "Should not allow a name collision between external interface " "and interface", + ) + + parser = parser.reset() + parser.parse( + """ + interface A; + interface A; + """ + ) + results = parser.finish() + harness.ok( + len(results) == 1 and isinstance(results[0], WebIDL.IDLExternalInterface), + "Should allow name collisions between external interface " "declarations", + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + [SomeRandomAnnotation] + interface A { + readonly attribute boolean y; + }; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok(threw, "Should not allow unknown extended attributes on interfaces") + + parser = parser.reset() + parser.parse( + """ + [Global, Exposed=Window] interface Window {}; + [Exposed=Window, LegacyWindowAlias=A] + interface B {}; + [Exposed=Window, LegacyWindowAlias=(C, D)] + interface E {}; + """ + ) + results = parser.finish() + harness.check( + results[1].legacyWindowAliases, ["A"], "Should support a single identifier" + ) + harness.check( + results[2].legacyWindowAliases, ["C", "D"], "Should support an identifier list" + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + [LegacyWindowAlias] + interface A {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok(threw, "Should not allow [LegacyWindowAlias] with no value") + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + [Exposed=Worker, LegacyWindowAlias=B] + interface A {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok(threw, "Should not allow [LegacyWindowAlias] without Window exposure") + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + [Global, Exposed=Window] interface Window {}; + [Exposed=Window] + interface A {}; + [Exposed=Window, LegacyWindowAlias=A] + interface B {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers" + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + [Global, Exposed=Window] interface Window {}; + [Exposed=Window, LegacyWindowAlias=A] + interface B {}; + [Exposed=Window] + interface A {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers" + ) + + parser = parser.reset() + threw = False + try: + parser.parse( + """ + [Global, Exposed=Window] interface Window {}; + [Exposed=Window, LegacyWindowAlias=A] + interface B {}; + [Exposed=Window, LegacyWindowAlias=A] + interface C {}; + """ + ) + results = parser.finish() + except Exception: + threw = True + harness.ok( + threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers" + ) |