michael@0: import WebIDL michael@0: michael@0: def WebIDLTest(parser, harness): michael@0: parser.parse("interface Foo { };") michael@0: results = parser.finish() michael@0: harness.ok(True, "Empty interface parsed without error.") michael@0: harness.check(len(results), 1, "Should be one production") michael@0: harness.ok(isinstance(results[0], WebIDL.IDLInterface), michael@0: "Should be an IDLInterface") michael@0: iface = results[0] michael@0: harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName") michael@0: harness.check(iface.identifier.name, "Foo", "Interface has the right name") michael@0: harness.check(iface.parent, None, "Interface has no parent") michael@0: michael@0: parser.parse("interface Bar : Foo { };") michael@0: results = parser.finish() michael@0: harness.ok(True, "Empty interface parsed without error.") michael@0: harness.check(len(results), 2, "Should be two productions") michael@0: harness.ok(isinstance(results[1], WebIDL.IDLInterface), michael@0: "Should be an IDLInterface") michael@0: iface = results[1] michael@0: harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName") michael@0: harness.check(iface.identifier.name, "Bar", "Interface has the right name") michael@0: harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), michael@0: "Interface has a parent") michael@0: michael@0: parser = parser.reset() michael@0: parser.parse(""" michael@0: interface QNameBase { michael@0: attribute long foo; michael@0: }; michael@0: michael@0: interface QNameDerived : QNameBase { michael@0: attribute long long foo; michael@0: attribute byte bar; michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: harness.check(len(results), 2, "Should be two productions") michael@0: harness.ok(isinstance(results[0], WebIDL.IDLInterface), michael@0: "Should be an IDLInterface") michael@0: harness.ok(isinstance(results[1], WebIDL.IDLInterface), michael@0: "Should be an IDLInterface") michael@0: harness.check(results[1].parent, results[0], "Inheritance chain is right") michael@0: harness.check(len(results[0].members), 1, "Expect 1 productions") michael@0: harness.check(len(results[1].members), 2, "Expect 2 productions") michael@0: base = results[0] michael@0: derived = results[1] michael@0: harness.check(base.members[0].identifier.QName(), "::QNameBase::foo", michael@0: "Member has the right QName") michael@0: harness.check(derived.members[0].identifier.QName(), "::QNameDerived::foo", michael@0: "Member has the right QName") michael@0: harness.check(derived.members[1].identifier.QName(), "::QNameDerived::bar", michael@0: "Member has the right QName") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A : B {}; michael@0: interface B : A {}; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow cycles in interface inheritance chains") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A : C {}; michael@0: interface C : B {}; michael@0: interface B : A {}; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow indirect cycles in interface inheritance chains") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A {}; michael@0: interface B {}; michael@0: A implements B; michael@0: B implements A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow cycles via implements") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A {}; michael@0: interface C {}; michael@0: interface B {}; michael@0: A implements C; michael@0: C implements B; michael@0: B implements A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow indirect cycles via implements") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A : B {}; michael@0: interface B {}; michael@0: B implements A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow inheriting from an interface that implements us") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A : B {}; michael@0: interface B {}; michael@0: interface C {}; michael@0: B implements C; michael@0: C implements A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow inheriting from an interface that indirectly implements us") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A : B {}; michael@0: interface B : C {}; michael@0: interface C {}; michael@0: C implements A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow indirectly inheriting from an interface that implements us") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A : B {}; michael@0: interface B : C {}; michael@0: interface C {}; michael@0: interface D {}; michael@0: C implements D; michael@0: D implements A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow indirectly inheriting from an interface that indirectly implements us") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A; michael@0: interface B : A {}; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: michael@0: harness.ok(threw, "Should not allow inheriting from an interface that is only forward declared") michael@0: michael@0: parser = parser.reset() michael@0: parser.parse(""" michael@0: [Constructor(long arg)] michael@0: interface A { michael@0: readonly attribute boolean x; michael@0: void foo(); michael@0: }; michael@0: [Constructor] michael@0: partial interface A { michael@0: readonly attribute boolean y; michael@0: void foo(long arg); michael@0: }; michael@0: """); michael@0: results = parser.finish(); michael@0: harness.check(len(results), 1, michael@0: "Should have one result with partial interface") michael@0: iface = results[0] michael@0: harness.check(len(iface.members), 3, michael@0: "Should have three members with partial interface") michael@0: harness.check(iface.members[0].identifier.name, "x", michael@0: "First member should be x with partial interface") michael@0: harness.check(iface.members[1].identifier.name, "foo", michael@0: "Second member should be foo with partial interface") michael@0: harness.check(len(iface.members[1].signatures()), 2, michael@0: "Should have two foo signatures with partial interface") michael@0: harness.check(iface.members[2].identifier.name, "y", michael@0: "Third member should be y with partial interface") michael@0: harness.check(len(iface.ctor().signatures()), 2, michael@0: "Should have two constructors with partial interface") michael@0: michael@0: parser = parser.reset() michael@0: parser.parse(""" michael@0: [Constructor] michael@0: partial interface A { michael@0: readonly attribute boolean y; michael@0: void foo(long arg); michael@0: }; michael@0: [Constructor(long arg)] michael@0: interface A { michael@0: readonly attribute boolean x; michael@0: void foo(); michael@0: }; michael@0: """); michael@0: results = parser.finish(); michael@0: harness.check(len(results), 1, michael@0: "Should have one result with reversed partial interface") michael@0: iface = results[0] michael@0: harness.check(len(iface.members), 3, michael@0: "Should have three members with reversed partial interface") michael@0: harness.check(iface.members[0].identifier.name, "x", michael@0: "First member should be x with reversed partial interface") michael@0: harness.check(iface.members[1].identifier.name, "foo", michael@0: "Second member should be foo with reversed partial interface") michael@0: harness.check(len(iface.members[1].signatures()), 2, michael@0: "Should have two foo signatures with reversed partial interface") michael@0: harness.check(iface.members[2].identifier.name, "y", michael@0: "Third member should be y with reversed partial interface") michael@0: harness.check(len(iface.ctor().signatures()), 2, michael@0: "Should have two constructors with reversed partial interface") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A { michael@0: readonly attribute boolean x; michael@0: }; michael@0: interface A { michael@0: readonly attribute boolean y; michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow two non-partial interfaces with the same name") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: partial interface A { michael@0: readonly attribute boolean x; michael@0: }; michael@0: partial interface A { michael@0: readonly attribute boolean y; michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Must have a non-partial interface for a given name") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: dictionary A { michael@0: boolean x; michael@0: }; michael@0: partial interface A { michael@0: readonly attribute boolean y; michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow a name collision between partial interface " michael@0: "and other object") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: dictionary A { michael@0: boolean x; michael@0: }; michael@0: interface A { michael@0: readonly attribute boolean y; michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow a name collision between interface " michael@0: "and other object") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: dictionary A { michael@0: boolean x; michael@0: }; michael@0: interface A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow a name collision between external interface " michael@0: "and other object") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface A { michael@0: readonly attribute boolean x; michael@0: }; michael@0: interface A; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow a name collision between external interface " michael@0: "and interface") michael@0: michael@0: parser = parser.reset() michael@0: parser.parse(""" michael@0: interface A; michael@0: interface A; michael@0: """) michael@0: results = parser.finish() michael@0: harness.ok(len(results) == 1 and michael@0: isinstance(results[0], WebIDL.IDLExternalInterface), michael@0: "Should allow name collisions between external interface " michael@0: "declarations") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: [SomeRandomAnnotation] michael@0: interface A { michael@0: readonly attribute boolean y; michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow unknown extended attributes on interfaces") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: interface B {}; michael@0: [ArrayClass] michael@0: interface A : B { michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(threw, michael@0: "Should not allow [ArrayClass] on interfaces with parents") michael@0: michael@0: parser = parser.reset() michael@0: threw = False michael@0: try: michael@0: parser.parse(""" michael@0: [ArrayClass] michael@0: interface A { michael@0: }; michael@0: """) michael@0: results = parser.finish() michael@0: except: michael@0: threw = True michael@0: harness.ok(not threw, michael@0: "Should allow [ArrayClass] on interfaces without parents")