Bug 1915045 Ensure decode tasks are scheduled on BufferingState::Enter() r=media...
[gecko.git] / dom / bindings / parser / tests / test_distinguishability.py
blobcaf726c16b8762296049b260ea2f9c5a99c2b06c
1 import WebIDL
4 def firstArgType(method):
5 return method.signatures()[0][1][0].type
8 def WebIDLTest(parser, harness):
9 parser.parse(
10 """
11 // Give our dictionary a required member so we don't need to
12 // mess with optional and default values.
13 dictionary Dict {
14 required long member;
16 callback interface Foo {
18 interface Bar {
19 // Bit of a pain to get things that have dictionary types
20 undefined passDict(Dict arg);
21 undefined passFoo(Foo arg);
22 undefined passNullableUnion((object? or DOMString) arg);
23 undefined passNullable(Foo? arg);
25 """
27 results = parser.finish()
29 iface = results[2]
30 harness.ok(iface.isInterface(), "Should have interface")
31 dictMethod = iface.members[0]
32 ifaceMethod = iface.members[1]
33 nullableUnionMethod = iface.members[2]
34 nullableIfaceMethod = iface.members[3]
36 dictType = firstArgType(dictMethod)
37 ifaceType = firstArgType(ifaceMethod)
39 harness.ok(dictType.isDictionary(), "Should have dictionary type")
40 harness.ok(ifaceType.isInterface(), "Should have interface type")
41 harness.ok(ifaceType.isCallbackInterface(), "Should have callback interface type")
43 harness.ok(
44 not dictType.isDistinguishableFrom(ifaceType),
45 "Dictionary not distinguishable from callback interface",
47 harness.ok(
48 not ifaceType.isDistinguishableFrom(dictType),
49 "Callback interface not distinguishable from dictionary",
52 nullableUnionType = firstArgType(nullableUnionMethod)
53 nullableIfaceType = firstArgType(nullableIfaceMethod)
55 harness.ok(nullableUnionType.isUnion(), "Should have union type")
56 harness.ok(nullableIfaceType.isInterface(), "Should have interface type")
57 harness.ok(nullableIfaceType.nullable(), "Should have nullable type")
59 harness.ok(
60 not nullableUnionType.isDistinguishableFrom(nullableIfaceType),
61 "Nullable type not distinguishable from union with nullable " "member type",
63 harness.ok(
64 not nullableIfaceType.isDistinguishableFrom(nullableUnionType),
65 "Union with nullable member type not distinguishable from " "nullable type",
68 parser = parser.reset()
69 parser.parse(
70 """
71 interface TestIface {
72 undefined passKid(Kid arg);
73 undefined passParent(Parent arg);
74 undefined passGrandparent(Grandparent arg);
75 undefined passUnrelated1(Unrelated1 arg);
76 undefined passUnrelated2(Unrelated2 arg);
77 undefined passArrayBuffer(ArrayBuffer arg);
78 undefined passArrayBuffer(ArrayBufferView arg);
81 interface Kid : Parent {};
82 interface Parent : Grandparent {};
83 interface Grandparent {};
84 interface Unrelated1 {};
85 interface Unrelated2 {};
86 """
88 results = parser.finish()
90 iface = results[0]
91 harness.ok(iface.isInterface(), "Should have interface")
92 argTypes = [firstArgType(method) for method in iface.members]
93 unrelatedTypes = [firstArgType(method) for method in iface.members[-3:]]
95 for type1 in argTypes:
96 for type2 in argTypes:
97 distinguishable = type1 is not type2 and (
98 type1 in unrelatedTypes or type2 in unrelatedTypes
101 harness.check(
102 type1.isDistinguishableFrom(type2),
103 distinguishable,
104 "Type %s should %sbe distinguishable from type %s"
105 % (type1, "" if distinguishable else "not ", type2),
107 harness.check(
108 type2.isDistinguishableFrom(type1),
109 distinguishable,
110 "Type %s should %sbe distinguishable from type %s"
111 % (type2, "" if distinguishable else "not ", type1),
114 parser = parser.reset()
115 parser.parse(
117 interface Dummy {};
118 interface TestIface {
119 undefined method(long arg1, TestIface arg2);
120 undefined method(long arg1, long arg2);
121 undefined method(long arg1, Dummy arg2);
122 undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
126 results = parser.finish()
127 harness.check(len(results[1].members), 1, "Should look like we have one method")
128 harness.check(
129 len(results[1].members[0].signatures()), 4, "Should have four signatures"
132 parser = parser.reset()
133 threw = False
134 try:
135 parser.parse(
137 interface Dummy {};
138 interface TestIface {
139 undefined method(long arg1, TestIface arg2);
140 undefined method(long arg1, long arg2);
141 undefined method(any arg1, Dummy arg2);
142 undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
146 parser.finish()
147 except WebIDL.WebIDLError:
148 threw = True
150 harness.ok(
151 threw,
152 "Should throw when args before the distinguishing arg are not "
153 "all the same type",
156 parser = parser.reset()
157 threw = False
158 try:
159 parser.parse(
161 interface Dummy {};
162 interface TestIface {
163 undefined method(long arg1, TestIface arg2);
164 undefined method(long arg1, long arg2);
165 undefined method(any arg1, DOMString arg2);
166 undefined method(DOMString arg1, DOMString arg2, DOMString arg3);
170 parser.finish()
171 except WebIDL.WebIDLError:
172 threw = True
174 harness.ok(threw, "Should throw when there is no distinguishing index")
176 # Now let's test our whole distinguishability table
177 argTypes = [
178 "long",
179 "short",
180 "long?",
181 "short?",
182 "boolean",
183 "boolean?",
184 "undefined",
185 "undefined?",
186 "DOMString",
187 "ByteString",
188 "UTF8String",
189 "Enum",
190 "Enum2",
191 "Interface",
192 "Interface?",
193 "AncestorInterface",
194 "UnrelatedInterface",
195 "CallbackInterface",
196 "CallbackInterface?",
197 "CallbackInterface2",
198 "object",
199 "Callback",
200 "Callback2",
201 "Dict",
202 "Dict2",
203 "sequence<long>",
204 "sequence<short>",
205 "record<DOMString, object>",
206 "record<USVString, Dict>",
207 "record<ByteString, long>",
208 "record<UTF8String, long>",
209 "any",
210 "Promise<any>",
211 "Promise<any>?",
212 "USVString",
213 "JSString",
214 "ArrayBuffer",
215 "ArrayBufferView",
216 "Uint8Array",
217 "Uint16Array",
218 "(long or Callback)",
219 "(long or Dict)",
222 # Try to categorize things a bit to keep list lengths down
223 def allBut(list1, list2):
224 return [
226 for a in list1
227 if a not in list2
228 and (a != "any" and a != "Promise<any>" and a != "Promise<any>?")
231 unionsWithCallback = ["(long or Callback)"]
232 unionsNoCallback = ["(long or Dict)"]
233 unions = unionsWithCallback + unionsNoCallback
234 numerics = ["long", "short", "long?", "short?"]
235 booleans = ["boolean", "boolean?"]
236 undefineds = ["undefined", "undefined?"]
237 primitives = numerics + booleans
238 nonNumerics = allBut(argTypes, numerics + unions)
239 nonBooleans = allBut(argTypes, booleans)
240 strings = [
241 "DOMString",
242 "ByteString",
243 "Enum",
244 "Enum2",
245 "USVString",
246 "JSString",
247 "UTF8String",
249 nonStrings = allBut(argTypes, strings)
250 nonObjects = undefineds + primitives + strings
251 bufferSourceTypes = ["ArrayBuffer", "ArrayBufferView", "Uint8Array", "Uint16Array"]
252 interfaces = [
253 "Interface",
254 "Interface?",
255 "AncestorInterface",
256 "UnrelatedInterface",
257 ] + bufferSourceTypes
258 nullables = [
259 "long?",
260 "short?",
261 "boolean?",
262 "undefined?",
263 "Interface?",
264 "CallbackInterface?",
265 "Dict",
266 "Dict2",
267 "Date?",
268 "any",
269 "Promise<any>?",
270 ] + unionsNoCallback
271 sequences = ["sequence<long>", "sequence<short>"]
272 nonUserObjects = nonObjects + interfaces + sequences
273 otherObjects = allBut(argTypes, nonUserObjects + ["object"])
274 notRelatedInterfaces = (
275 nonObjects
276 + ["UnrelatedInterface"]
277 + otherObjects
278 + sequences
279 + bufferSourceTypes
281 records = [
282 "record<DOMString, object>",
283 "record<USVString, Dict>",
284 "record<ByteString, long>",
285 "record<UTF8String, long>",
286 ] # JSString not supported in records
287 dicts = ["Dict", "Dict2"]
288 callbacks = ["Callback", "Callback2"]
289 callbackInterfaces = [
290 "CallbackInterface",
291 "CallbackInterface?",
292 "CallbackInterface2",
294 dictionaryLike = dicts + callbackInterfaces + records + unionsNoCallback
296 # Build a representation of the distinguishability table as a dict
297 # of dicts, holding True values where needed, holes elsewhere.
298 data = dict()
299 for type in argTypes:
300 data[type] = dict()
302 def setDistinguishable(type, types):
303 for other in types:
304 data[type][other] = True
306 setDistinguishable("long", nonNumerics)
307 setDistinguishable("short", nonNumerics)
308 setDistinguishable("long?", allBut(nonNumerics, nullables))
309 setDistinguishable("short?", allBut(nonNumerics, nullables))
310 setDistinguishable("boolean", nonBooleans)
311 setDistinguishable("boolean?", allBut(nonBooleans, nullables))
312 setDistinguishable("undefined", allBut(argTypes, undefineds + dictionaryLike))
313 setDistinguishable(
314 "undefined?", allBut(argTypes, undefineds + dictionaryLike + nullables)
316 setDistinguishable("DOMString", nonStrings)
317 setDistinguishable("ByteString", nonStrings)
318 setDistinguishable("UTF8String", nonStrings)
319 setDistinguishable("USVString", nonStrings)
320 setDistinguishable("JSString", nonStrings)
321 setDistinguishable("Enum", nonStrings)
322 setDistinguishable("Enum2", nonStrings)
323 setDistinguishable("Interface", notRelatedInterfaces)
324 setDistinguishable("Interface?", allBut(notRelatedInterfaces, nullables))
325 setDistinguishable("AncestorInterface", notRelatedInterfaces)
326 setDistinguishable(
327 "UnrelatedInterface", allBut(argTypes, ["object", "UnrelatedInterface"])
329 setDistinguishable(
330 "CallbackInterface",
331 allBut(nonUserObjects + callbacks + unionsWithCallback, undefineds),
333 setDistinguishable(
334 "CallbackInterface?",
335 allBut(nonUserObjects + callbacks + unionsWithCallback, nullables + undefineds),
337 setDistinguishable(
338 "CallbackInterface2",
339 allBut(nonUserObjects + callbacks + unionsWithCallback, undefineds),
341 setDistinguishable("object", nonObjects)
342 setDistinguishable(
343 "Callback",
344 nonUserObjects + unionsNoCallback + dicts + records + callbackInterfaces,
346 setDistinguishable(
347 "Callback2",
348 nonUserObjects + unionsNoCallback + dicts + records + callbackInterfaces,
350 setDistinguishable(
351 "Dict",
352 allBut(nonUserObjects + unionsWithCallback + callbacks, nullables + undefineds),
354 setDistinguishable(
355 "Dict2",
356 allBut(nonUserObjects + unionsWithCallback + callbacks, nullables + undefineds),
358 setDistinguishable(
359 "sequence<long>",
360 allBut(argTypes, sequences + ["object"]),
362 setDistinguishable(
363 "sequence<short>",
364 allBut(argTypes, sequences + ["object"]),
366 setDistinguishable(
367 "record<DOMString, object>",
368 allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
370 setDistinguishable(
371 "record<USVString, Dict>",
372 allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
374 # JSString not supported in records
375 setDistinguishable(
376 "record<ByteString, long>",
377 allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
379 setDistinguishable(
380 "record<UTF8String, long>",
381 allBut(nonUserObjects + unionsWithCallback + callbacks, undefineds),
383 setDistinguishable("any", [])
384 setDistinguishable("Promise<any>", [])
385 setDistinguishable("Promise<any>?", [])
386 setDistinguishable("ArrayBuffer", allBut(argTypes, ["ArrayBuffer", "object"]))
387 setDistinguishable(
388 "ArrayBufferView",
389 allBut(argTypes, ["ArrayBufferView", "Uint8Array", "Uint16Array", "object"]),
391 setDistinguishable(
392 "Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"])
394 setDistinguishable(
395 "Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"])
397 setDistinguishable(
398 "(long or Callback)",
399 allBut(nonUserObjects + dicts + records + callbackInterfaces, numerics),
401 setDistinguishable(
402 "(long or Dict)",
403 allBut(nonUserObjects + callbacks, numerics + nullables + undefineds),
406 def areDistinguishable(type1, type2):
407 return data[type1].get(type2, False)
409 def checkDistinguishability(parser, type1, type2):
410 idlTemplate = """
411 enum Enum { "a", "b" };
412 enum Enum2 { "c", "d" };
413 interface Interface : AncestorInterface {};
414 interface AncestorInterface {};
415 interface UnrelatedInterface {};
416 callback interface CallbackInterface {};
417 callback interface CallbackInterface2 {};
418 callback Callback = any();
419 callback Callback2 = long(short arg);
420 [LegacyTreatNonObjectAsNull] callback LegacyCallback1 = any();
421 // Give our dictionaries required members so we don't need to
422 // mess with optional and default values.
423 dictionary Dict { required long member; };
424 dictionary Dict2 { required long member; };
425 interface TestInterface {%s
428 if type1 in undefineds or type2 in undefineds:
429 methods = """
430 (%s or %s) myMethod();""" % (
431 type1,
432 type2,
434 else:
435 methodTemplate = """
436 undefined myMethod(%s arg);"""
437 methods = (methodTemplate % type1) + (methodTemplate % type2)
438 idl = idlTemplate % methods
440 parser = parser.reset()
441 threw = False
442 try:
443 parser.parse(idl)
444 parser.finish()
445 except WebIDL.WebIDLError:
446 threw = True
448 if areDistinguishable(type1, type2):
449 harness.ok(
450 not threw,
451 "Should not throw for '%s' and '%s' because they are distinguishable"
452 % (type1, type2),
454 else:
455 harness.ok(
456 threw,
457 "Should throw for '%s' and '%s' because they are not distinguishable"
458 % (type1, type2),
461 # Enumerate over everything in both orders, since order matters in
462 # terms of our implementation of distinguishability checks
463 for type1 in argTypes:
464 for type2 in argTypes:
465 checkDistinguishability(parser, type1, type2)