5 # We'd like to use itertools.chain but it's 2.6 or higher.
9 # chain('ABC', 'DEF') --> A B C D E F
15 # We'd like to use itertools.combinations but it's 2.6 or higher.
16 def combinations(iterable
, r
):
17 # combinations('ABCD', 2) --> AB AC AD BC BD CD
18 # combinations(range(4), 3) --> 012 013 023 123
19 pool
= tuple(iterable
)
23 indices
= list(range(r
))
24 yield tuple(pool
[i
] for i
in indices
)
26 for i
in reversed(range(r
)):
27 if indices
[i
] != i
+ n
- r
:
32 for j
in range(i
+ 1, r
):
33 indices
[j
] = indices
[j
- 1] + 1
34 yield tuple(pool
[i
] for i
in indices
)
37 # We'd like to use itertools.combinations_with_replacement but it's 2.7 or
39 def combinations_with_replacement(iterable
, r
):
40 # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
41 pool
= tuple(iterable
)
46 yield tuple(pool
[i
] for i
in indices
)
48 for i
in reversed(range(r
)):
49 if indices
[i
] != n
- 1:
53 indices
[i
:] = [indices
[i
] + 1] * (r
- i
)
54 yield tuple(pool
[i
] for i
in indices
)
57 def WebIDLTest(parser
, harness
):
82 interface TestInterface1 {
84 interface TestInterface2 {
91 interface PrepareForTest {
94 for i
, type in enumerate(types
):
95 interface
+= string
.Template(
97 readonly attribute ${type} attr${i};
99 ).substitute(i
=i
, type=type)
104 parser
.parse(interface
)
105 results
= parser
.finish()
109 parser
= parser
.reset()
111 def typesAreDistinguishable(t
):
112 return all(u
[0].isDistinguishableFrom(u
[1]) for u
in combinations(t
, 2))
114 def typesAreNotDistinguishable(t
):
115 return any(not u
[0].isDistinguishableFrom(u
[1]) for u
in combinations(t
, 2))
117 def unionTypeName(t
):
119 t
[0:2] = [unionTypeName(t
[0:2])]
120 return "(" + " or ".join(t
) + ")"
122 # typeCombinations is an iterable of tuples containing the name of the type
123 # as a string and the parsed IDL type.
124 def unionTypes(typeCombinations
, predicate
):
125 for c
in typeCombinations
:
126 if predicate(t
[1] for t
in c
):
127 yield unionTypeName([t
[0] for t
in c
])
129 # We limit invalid union types with a union member type to the subset of 3
130 # types with one invalid combination.
131 # typeCombinations is an iterable of tuples containing the name of the type
132 # as a string and the parsed IDL type.
133 def invalidUnionWithUnion(typeCombinations
):
134 for c
in typeCombinations
:
136 typesAreNotDistinguishable((c
[0][1], c
[1][1]))
137 and typesAreDistinguishable((c
[1][1], c
[2][1]))
138 and typesAreDistinguishable((c
[0][1], c
[2][1]))
140 yield unionTypeName([t
[0] for t
in c
])
142 # Create a list of tuples containing the name of the type as a string and
143 # the parsed IDL type.
144 types
= zip(types
, (a
.type for a
in iface
.members
))
146 validUnionTypes
= chain(
147 unionTypes(combinations(types
, 2), typesAreDistinguishable
),
148 unionTypes(combinations(types
, 3), typesAreDistinguishable
),
150 invalidUnionTypes
= chain(
151 unionTypes(combinations_with_replacement(types
, 2), typesAreNotDistinguishable
),
152 invalidUnionWithUnion(combinations(types
, 3)),
157 interface TestUnion {
160 for i
, type in enumerate(validUnionTypes
):
161 interface
+= string
.Template(
163 undefined method${i}(${type} arg);
164 ${type} returnMethod${i}();
165 attribute ${type} attr${i};
166 undefined optionalMethod${i}(${type}? arg);
168 ).substitute(i
=i
, type=type)
172 parser
.parse(interface
)
173 results
= parser
.finish()
175 parser
= parser
.reset()
177 for invalid
in invalidUnionTypes
:
182 interface TestUnion {
183 undefined method(${type} arg);
186 ).substitute(type=invalid
)
191 parser
.parse(interface
)
192 results
= parser
.finish()
193 except WebIDL
.WebIDLError
:
196 harness
.ok(threw
, "Should have thrown.")
198 parser
= parser
.reset()