4 def WebIDLTest(parser
, harness
):
5 def shouldPass(prefix
, iface
, expectedMembers
, numProductions
=1):
12 "%s - Should have production count %d" % (prefix
, numProductions
),
15 isinstance(results
[0], WebIDL
.IDLInterface
),
16 "%s - Should be an IDLInterface" % (prefix
),
18 # Make a copy, since we plan to modify it
19 expectedMembers
= list(expectedMembers
)
20 for m
in results
[0].members
:
21 name
= m
.identifier
.name
22 if m
.isMethod() and m
.isStatic():
23 # None of the expected members are static methods, so ignore those.
24 harness
.ok(True, "%s - %s - Should be a %s" % (prefix
, name
, type(m
)))
25 elif (name
, type(m
)) in expectedMembers
:
26 harness
.ok(True, "%s - %s - Should be a %s" % (prefix
, name
, type(m
)))
27 expectedMembers
.remove((name
, type(m
)))
31 "%s - %s - Unknown symbol of type %s" % (prefix
, name
, type(m
)),
33 # A bit of a hoop because we can't generate the error string if we pass
34 if len(expectedMembers
) == 0:
35 harness
.ok(True, "Found all the members")
39 "Expected member not found: %s of type %s"
40 % (expectedMembers
[0][0], expectedMembers
[0][1]),
44 def shouldFail(prefix
, iface
):
49 harness
.ok(False, prefix
+ " - Interface passed when should've failed")
50 except WebIDL
.WebIDLError
:
51 harness
.ok(True, prefix
+ " - Interface failed as expected")
52 except Exception as e
:
56 + " - Interface failed but not as a WebIDLError exception: %s" % e
,
60 (x
, WebIDL
.IDLMethod
) for x
in ["entries", "keys", "values", "forEach"]
63 [(x
, WebIDL
.IDLMethod
) for x
in ["has"]]
64 + [("__setlike", WebIDL
.IDLMaplikeOrSetlike
)]
67 setROMembers
.extend([("size", WebIDL
.IDLAttribute
)])
69 (x
, WebIDL
.IDLMethod
) for x
in ["add", "clear", "delete"]
72 [(x
, WebIDL
.IDLMethod
) for x
in ["get", "has"]]
73 + [("__maplike", WebIDL
.IDLMaplikeOrSetlike
)]
76 mapROMembers
.extend([("size", WebIDL
.IDLAttribute
)])
78 (x
, WebIDL
.IDLMethod
) for x
in ["set", "clear", "delete"]
81 # OK, now that we've used iterableMembers to set up the above, append
82 # __iterable to it for the iterable<> case.
83 iterableMembers
.append(("__iterable", WebIDL
.IDLIterable
))
85 asyncIterableMembers
= [
86 (x
, WebIDL
.IDLMethod
) for x
in ["entries", "keys", "values"]
88 asyncIterableMembers
.append(("__iterable", WebIDL
.IDLAsyncIterable
))
90 valueIterableMembers
= [("__iterable", WebIDL
.IDLIterable
)]
91 valueIterableMembers
.append(("__indexedgetter", WebIDL
.IDLMethod
))
92 valueIterableMembers
.append(("length", WebIDL
.IDLAttribute
))
94 valueAsyncIterableMembers
= [("__iterable", WebIDL
.IDLAsyncIterable
)]
95 valueAsyncIterableMembers
.append(("values", WebIDL
.IDLMethod
))
97 disallowedIterableNames
= [
98 ("keys", WebIDL
.IDLMethod
),
99 ("entries", WebIDL
.IDLMethod
),
100 ("values", WebIDL
.IDLMethod
),
102 disallowedMemberNames
= [
103 ("forEach", WebIDL
.IDLMethod
),
104 ("has", WebIDL
.IDLMethod
),
105 ("size", WebIDL
.IDLAttribute
),
106 ] + disallowedIterableNames
107 mapDisallowedMemberNames
= [("get", WebIDL
.IDLMethod
)] + disallowedMemberNames
108 disallowedNonMethodNames
= [
109 ("clear", WebIDL
.IDLMethod
),
110 ("delete", WebIDL
.IDLMethod
),
112 mapDisallowedNonMethodNames
= [("set", WebIDL
.IDLMethod
)] + disallowedNonMethodNames
113 setDisallowedNonMethodNames
= [("add", WebIDL
.IDLMethod
)] + disallowedNonMethodNames
115 ("unrelatedAttribute", WebIDL
.IDLAttribute
),
116 ("unrelatedMethod", WebIDL
.IDLMethod
),
124 "Iterable (key only)",
128 readonly attribute unsigned long length;
129 getter long(unsigned long index);
130 attribute long unrelatedAttribute;
131 long unrelatedMethod();
134 valueIterableMembers
+ unrelatedMembers
,
138 "Iterable (key only) inheriting from parent",
140 interface Foo1 : Foo2 {
142 readonly attribute unsigned long length;
143 getter long(unsigned long index);
146 attribute long unrelatedAttribute;
147 long unrelatedMethod();
150 valueIterableMembers
,
155 "Iterable (key and value)",
158 iterable<long, long>;
159 attribute long unrelatedAttribute;
160 long unrelatedMethod();
163 iterableMembers
+ unrelatedMembers
,
164 # numProductions == 2 because of the generated iterator iface,
169 "Iterable (key and value) inheriting from parent",
171 interface Foo1 : Foo2 {
172 iterable<long, long>;
175 attribute long unrelatedAttribute;
176 long unrelatedMethod();
180 # numProductions == 3 because of the generated iterator iface,
185 "Async iterable (key only)",
188 async iterable<long>;
189 attribute long unrelatedAttribute;
190 long unrelatedMethod();
193 valueAsyncIterableMembers
+ unrelatedMembers
,
194 # numProductions == 2 because of the generated iterator iface,
199 "Async iterable (key only) inheriting from parent",
201 interface Foo1 : Foo2 {
202 async iterable<long>;
205 attribute long unrelatedAttribute;
206 long unrelatedMethod();
209 valueAsyncIterableMembers
,
210 # numProductions == 3 because of the generated iterator iface,
215 "Async iterable with argument (key only)",
218 async iterable<long>(optional long foo);
219 attribute long unrelatedAttribute;
220 long unrelatedMethod();
223 valueAsyncIterableMembers
+ unrelatedMembers
,
224 # numProductions == 2 because of the generated iterator iface,
229 "Async iterable (key and value)",
232 async iterable<long, long>;
233 attribute long unrelatedAttribute;
234 long unrelatedMethod();
237 asyncIterableMembers
+ unrelatedMembers
,
238 # numProductions == 2 because of the generated iterator iface,
243 "Async iterable (key and value) inheriting from parent",
245 interface Foo1 : Foo2 {
246 async iterable<long, long>;
249 attribute long unrelatedAttribute;
250 long unrelatedMethod();
253 asyncIterableMembers
,
254 # numProductions == 3 because of the generated iterator iface,
259 "Async iterable with argument (key and value)",
262 async iterable<long, long>(optional long foo);
263 attribute long unrelatedAttribute;
264 long unrelatedMethod();
267 asyncIterableMembers
+ unrelatedMembers
,
268 # numProductions == 2 because of the generated iterator iface,
273 "Maplike (readwrite)",
277 attribute long unrelatedAttribute;
278 long unrelatedMethod();
281 mapRWMembers
+ unrelatedMembers
,
285 "Maplike (readwrite) inheriting from parent",
287 interface Foo1 : Foo2 {
291 attribute long unrelatedAttribute;
292 long unrelatedMethod();
300 "Maplike (readwrite)",
304 attribute long unrelatedAttribute;
305 long unrelatedMethod();
308 mapRWMembers
+ unrelatedMembers
,
312 "Maplike (readwrite) inheriting from parent",
314 interface Foo1 : Foo2 {
318 attribute long unrelatedAttribute;
319 long unrelatedMethod();
327 "Maplike (readonly)",
330 readonly maplike<long, long>;
331 attribute long unrelatedAttribute;
332 long unrelatedMethod();
335 mapROMembers
+ unrelatedMembers
,
339 "Maplike (readonly) inheriting from parent",
341 interface Foo1 : Foo2 {
342 readonly maplike<long, long>;
345 attribute long unrelatedAttribute;
346 long unrelatedMethod();
354 "Setlike (readwrite)",
358 attribute long unrelatedAttribute;
359 long unrelatedMethod();
362 setRWMembers
+ unrelatedMembers
,
366 "Setlike (readwrite) inheriting from parent",
368 interface Foo1 : Foo2 {
372 attribute long unrelatedAttribute;
373 long unrelatedMethod();
381 "Setlike (readonly)",
384 readonly setlike<long>;
385 attribute long unrelatedAttribute;
386 long unrelatedMethod();
389 setROMembers
+ unrelatedMembers
,
393 "Setlike (readonly) inheriting from parent",
395 interface Foo1 : Foo2 {
396 readonly setlike<long>;
399 attribute long unrelatedAttribute;
400 long unrelatedMethod();
408 "Inheritance of maplike/setlike",
413 interface Foo2 : Foo1 {
421 "JS Implemented maplike interface",
423 [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
432 "JS Implemented maplike interface",
434 [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
443 # Multiple maplike/setlike tests
447 "Two maplike/setlikes on same interface",
457 "Two iterable/setlikes on same interface",
467 "Two iterables on same interface",
471 iterable<long, long>;
477 "Two iterables on same interface",
481 async iterable<long>;
487 "Two iterables on same interface",
490 async iterable<long>;
491 async iterable<long, long>;
497 "Async iterable with non-optional arguments",
500 async iterable<long>(long foo);
506 "Async iterable with non-optional arguments",
509 async iterable<long>(optional long foo, long bar);
515 "Async iterable with non-optional arguments",
518 async iterable<long, long>(long foo);
524 "Two maplike/setlikes in partials",
529 partial interface Foo1 {
536 "Conflicting maplike/setlikes across inheritance",
541 interface Foo2 : Foo1 {
548 "Conflicting maplike/iterable across inheritance",
553 interface Foo2 : Foo1 {
560 "Conflicting maplike/setlikes across multistep inheritance",
565 interface Foo2 : Foo1 {
567 interface Foo3 : Foo2 {
574 # Member name collision tests
577 def testConflictingMembers(
578 likeMember
, conflict
, expectedMembers
, methodPasses
, numProductions
=1
581 Tests for maplike/setlike member generation against conflicting member
582 names. If methodPasses is True, this means we expect the interface to
583 pass in the case of method shadowing, and expectedMembers should be the
584 list of interface members to check against on the passing interface.
587 (conflictName
, conflictType
) = conflict
590 "Conflicting method: %s and %s" % (likeMember
, conflictName
),
595 undefined %s(long test1, double test2, double test3);
598 % (likeMember
, conflictName
),
603 "Conflicting method: %s and %s" % (likeMember
, conflictName
),
608 undefined %s(long test1, double test2, double test3);
611 % (likeMember
, conflictName
),
613 # Inherited conflicting methods should ALWAYS fail
615 "Conflicting inherited method: %s and %s" % (likeMember
, conflictName
),
618 undefined %s(long test1, double test2, double test3);
620 interface Foo2 : Foo1 {
624 % (conflictName
, likeMember
),
626 if conflictType
== WebIDL
.IDLAttribute
:
628 "Conflicting static method: %s and %s" % (likeMember
, conflictName
),
632 static undefined %s(long test1, double test2, double test3);
635 % (likeMember
, conflictName
),
639 "Conflicting static method: %s and %s" % (likeMember
, conflictName
),
643 static undefined %s(long test1, double test2, double test3);
646 % (likeMember
, conflictName
),
648 numProductions
=numProductions
,
651 "Conflicting attribute: %s and %s" % (likeMember
, conflictName
),
658 % (likeMember
, conflictName
),
661 "Conflicting const: %s and %s" % (likeMember
, conflictName
),
668 % (likeMember
, conflictName
),
671 "Conflicting static attribute: %s and %s" % (likeMember
, conflictName
),
675 static attribute long %s;
678 % (likeMember
, conflictName
),
681 for member
in disallowedIterableNames
:
682 testConflictingMembers(
683 "iterable<long, long>", member
, iterableMembers
, False, numProductions
=2
685 for member
in mapDisallowedMemberNames
:
686 testConflictingMembers("maplike<long, long>", member
, mapRWMembers
, False)
687 for member
in disallowedMemberNames
:
688 testConflictingMembers("setlike<long>", member
, setRWMembers
, False)
689 for member
in mapDisallowedNonMethodNames
:
690 testConflictingMembers("maplike<long, long>", member
, mapRWMembers
, True)
691 for member
in setDisallowedNonMethodNames
:
692 testConflictingMembers("setlike<long>", member
, setRWMembers
, True)
695 "Inheritance of maplike/setlike with child member collision",
700 interface Foo2 : Foo1 {
709 "Inheritance of multi-level maplike/setlike with child member collision",
714 interface Foo2 : Foo1 {
716 interface Foo3 : Foo2 {
725 "Maplike interface with mixin member collision",
730 interface mixin Foo2 {
738 "Inherited Maplike interface with consequential interface member collision",
743 interface mixin Foo2 {
746 interface Foo3 : Foo1 {
755 "Inheritance of name collision with child maplike/setlike",
760 interface Foo2 : Foo1 {
767 "Inheritance of multi-level name collision with child maplike/setlike",
772 interface Foo2 : Foo1 {
774 interface Foo3 : Foo2 {
781 "Inheritance of attribute collision with parent maplike/setlike",
786 interface Foo2 : Foo1 {
787 attribute double size;
795 "Inheritance of multi-level attribute collision with parent maplike/setlike",
800 interface Foo2 : Foo1 {
802 interface Foo3 : Foo2 {
803 attribute double size;
811 "Inheritance of attribute collision with child maplike/setlike",
814 attribute double size;
816 interface Foo2 : Foo1 {
823 "Inheritance of multi-level attribute collision with child maplike/setlike",
826 attribute double size;
828 interface Foo2 : Foo1 {
830 interface Foo3 : Foo2 {
837 "Inheritance of attribute/rw function collision with child maplike/setlike",
840 attribute double set;
842 interface Foo2 : Foo1 {
849 "Inheritance of const/rw function collision with child maplike/setlike",
852 const double set = 0;
854 interface Foo2 : Foo1 {
861 "Inheritance of rw function with same name in child maplike/setlike",
866 interface Foo2 : Foo1 {
875 "Inheritance of unforgeable attribute collision with child maplike/setlike",
879 attribute double size;
881 interface Foo2 : Foo1 {
888 "Inheritance of multi-level unforgeable attribute collision with child maplike/setlike",
892 attribute double size;
894 interface Foo2 : Foo1 {
896 interface Foo3 : Foo2 {
903 "Interface with readonly allowable overrides",
906 readonly setlike<long>;
907 readonly attribute boolean clear;
910 setROMembers
+ [("clear", WebIDL
.IDLAttribute
)],
914 "Check proper override of clear/delete/set",
918 long clear(long a, long b, double c, double d);
919 long set(long a, long b, double c, double d);
920 long delete(long a, long b, double c, double d);
926 for m
in r
[0].members
:
927 if m
.identifier
.name
in ["clear", "set", "delete"]:
928 harness
.ok(m
.isMethod(), "%s should be a method" % m
.identifier
.name
)
930 m
.maxArgCount
, 4, "%s should have 4 arguments" % m
.identifier
.name
933 not m
.isMaplikeOrSetlikeOrIterableMethod(),
934 "%s should not be a maplike/setlike function" % m
.identifier
.name
,
938 ("maplike", " maplike<long, long>;"),
939 ("setlike", " readonly setlike<long>;"),
940 ("iterable", " iterable<long>;"),
941 ("iterable", " async iterable<long, long>;"),
944 for name
, line
in tests
:
945 parser
= parser
.reset()
949 " readonly attribute unsigned long length;",
950 " getter long(unsigned long index);",
953 parser
.parse("\n".join(lines
))
954 results
= parser
.finish()
956 p
= results
[0].members
[0]
958 harness
.check(p
.identifier
.name
, "__" + name
, "Correct name")
960 colno
= line
.find(name
)
962 loc_lines
= str(p
.identifier
.location
).split("\n")
964 harness
.check(loc_lines
[1], line
, "Second line shows the input")
968 "Correct column pointer in location string",