1import WebIDL
2
3def WebIDLTest(parser, harness):
4    def checkArgument(argument, QName, name, type, optional, variadic):
5        harness.ok(isinstance(argument, WebIDL.IDLArgument),
6                   "Should be an IDLArgument")
7        harness.check(argument.identifier.QName(), QName, "Argument has the right QName")
8        harness.check(argument.identifier.name, name, "Argument has the right name")
9        harness.check(str(argument.type), type, "Argument has the right return type")
10        harness.check(argument.optional, optional, "Argument has the right optional value")
11        harness.check(argument.variadic, variadic, "Argument has the right variadic value")
12
13    def checkMethod(method, QName, name, signatures,
14                    static=True, getter=False, setter=False,
15                    deleter=False, legacycaller=False, stringifier=False,
16                    chromeOnly=False, htmlConstructor=False):
17        harness.ok(isinstance(method, WebIDL.IDLMethod),
18                   "Should be an IDLMethod")
19        harness.ok(method.isMethod(), "Method is a method")
20        harness.ok(not method.isAttr(), "Method is not an attr")
21        harness.ok(not method.isConst(), "Method is not a const")
22        harness.check(method.identifier.QName(), QName, "Method has the right QName")
23        harness.check(method.identifier.name, name, "Method has the right name")
24        harness.check(method.isStatic(), static, "Method has the correct static value")
25        harness.check(method.isGetter(), getter, "Method has the correct getter value")
26        harness.check(method.isSetter(), setter, "Method has the correct setter value")
27        harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
28        harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
29        harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
30        harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
31        harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
32        harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
33
34        sigpairs = zip(method.signatures(), signatures)
35        for (gotSignature, expectedSignature) in sigpairs:
36            (gotRetType, gotArgs) = gotSignature
37            (expectedRetType, expectedArgs) = expectedSignature
38
39            harness.check(str(gotRetType), expectedRetType,
40                          "Method has the expected return type.")
41
42            for i in range(0, len(gotArgs)):
43                (QName, name, type, optional, variadic) = expectedArgs[i]
44                checkArgument(gotArgs[i], QName, name, type, optional, variadic)
45
46    parser.parse("""
47        [Constructor]
48        interface TestConstructorNoArgs {
49        };
50
51        [Constructor(DOMString name)]
52        interface TestConstructorWithArgs {
53        };
54
55        [Constructor(object foo), Constructor(boolean bar)]
56        interface TestConstructorOverloads {
57        };
58    """)
59    results = parser.finish()
60    harness.check(len(results), 3, "Should be three productions")
61    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
62               "Should be an IDLInterface")
63    harness.ok(isinstance(results[1], WebIDL.IDLInterface),
64               "Should be an IDLInterface")
65    harness.ok(isinstance(results[2], WebIDL.IDLInterface),
66               "Should be an IDLInterface")
67
68    checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor",
69                "constructor", [("TestConstructorNoArgs (Wrapper)", [])])
70    checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor",
71                "constructor",
72                [("TestConstructorWithArgs (Wrapper)",
73                 [("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])])
74    checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor",
75                "constructor",
76                [("TestConstructorOverloads (Wrapper)",
77                 [("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]),
78                 ("TestConstructorOverloads (Wrapper)",
79                 [("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])])
80
81    parser = parser.reset()
82    parser.parse("""
83        [ChromeConstructor()]
84        interface TestChromeConstructor {
85        };
86    """)
87    results = parser.finish()
88    harness.check(len(results), 1, "Should be one production")
89    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
90               "Should be an IDLInterface")
91
92    checkMethod(results[0].ctor(), "::TestChromeConstructor::constructor",
93                "constructor", [("TestChromeConstructor (Wrapper)", [])],
94                chromeOnly=True)
95
96    parser = parser.reset()
97    parser.parse("""
98        [HTMLConstructor]
99        interface TestHTMLConstructor {
100        };
101    """)
102    results = parser.finish()
103    harness.check(len(results), 1, "Should be one production")
104    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
105               "Should be an IDLInterface")
106
107    checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor",
108                "constructor", [("TestHTMLConstructor (Wrapper)", [])],
109                htmlConstructor=True)
110
111    parser = parser.reset()
112    threw = False
113    try:
114        parser.parse("""
115        [Constructor(),
116         ChromeConstructor(DOMString a)]
117        interface TestChromeConstructor {
118        };
119        """)
120        results = parser.finish()
121    except:
122        threw = True
123
124    harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")
125
126    # Test HTMLConstructor with argument
127    parser = parser.reset()
128    threw = False
129    try:
130        parser.parse("""
131            [HTMLConstructor(DOMString a)]
132            interface TestHTMLConstructorWithArgs {
133            };
134        """)
135        results = parser.finish()
136    except:
137        threw = True
138
139    harness.ok(threw, "HTMLConstructor should take no argument")
140
141    # Test HTMLConstructor on a callback interface
142    parser = parser.reset()
143    threw = False
144    try:
145        parser.parse("""
146            [HTMLConstructor]
147            callback interface TestHTMLConstructorOnCallbackInterface {
148            };
149        """)
150        results = parser.finish()
151    except:
152        threw = True
153
154    harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
155
156    # Test HTMLConstructor and Constructor
157    parser = parser.reset()
158    threw = False
159    try:
160        parser.parse("""
161            [Constructor,
162             HTMLConstructor]
163            interface TestHTMLConstructorAndConstructor {
164            };
165        """)
166        results = parser.finish()
167    except:
168        threw = True
169
170    harness.ok(threw, "Can't have both a Constructor and a HTMLConstructor")
171
172    parser = parser.reset()
173    threw = False
174    try:
175        parser.parse("""
176            [HTMLConstructor,
177             Constructor]
178            interface TestHTMLConstructorAndConstructor {
179            };
180        """)
181        results = parser.finish()
182    except:
183        threw = True
184
185    harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
186
187    parser = parser.reset()
188    threw = False
189    try:
190        parser.parse("""
191            [HTMLConstructor,
192             Constructor(DOMString a)]
193            interface TestHTMLConstructorAndConstructor {
194            };
195        """)
196    except:
197        threw = True
198
199    harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
200
201    parser = parser.reset()
202    threw = False
203    try:
204        parser.parse("""
205            [Constructor(DOMString a),
206             HTMLConstructor]
207            interface TestHTMLConstructorAndConstructor {
208            };
209        """)
210    except:
211        threw = True
212
213    harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
214
215    # Test HTMLConstructor and ChromeConstructor
216    parser = parser.reset()
217    threw = False
218    try:
219        parser.parse("""
220            [ChromeConstructor,
221             HTMLConstructor]
222            interface TestHTMLConstructorAndChromeConstructor {
223            };
224        """)
225        results = parser.finish()
226    except:
227        threw = True
228
229    harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
230
231    parser = parser.reset()
232    threw = False
233    try:
234        parser.parse("""
235            [HTMLConstructor,
236             ChromeConstructor]
237            interface TestHTMLConstructorAndChromeConstructor {
238            };
239        """)
240        results = parser.finish()
241    except:
242        threw = True
243
244    harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
245
246    parser = parser.reset()
247    threw = False
248    try:
249        parser.parse("""
250            [ChromeConstructor(DOMString a),
251             HTMLConstructor]
252            interface TestHTMLConstructorAndChromeConstructor {
253            };
254        """)
255        results = parser.finish()
256    except:
257        threw = True
258
259    parser = parser.reset()
260    threw = False
261    try:
262        parser.parse("""
263            [HTMLConstructor,
264             ChromeConstructor(DOMString a)]
265            interface TestHTMLConstructorAndChromeConstructor {
266            };
267        """)
268        results = parser.finish()
269    except:
270        threw = True
271
272    harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
273