summaryrefslogtreecommitdiffstats
path: root/dom/bindings/parser/tests/test_union.py
diff options
context:
space:
mode:
Diffstat (limited to 'dom/bindings/parser/tests/test_union.py')
-rw-r--r--dom/bindings/parser/tests/test_union.py196
1 files changed, 196 insertions, 0 deletions
diff --git a/dom/bindings/parser/tests/test_union.py b/dom/bindings/parser/tests/test_union.py
new file mode 100644
index 0000000000..675e2d0264
--- /dev/null
+++ b/dom/bindings/parser/tests/test_union.py
@@ -0,0 +1,196 @@
+import string
+
+# We'd like to use itertools.chain but it's 2.6 or higher.
+
+
+def chain(*iterables):
+ # chain('ABC', 'DEF') --> A B C D E F
+ for it in iterables:
+ for element in it:
+ yield element
+
+
+# We'd like to use itertools.combinations but it's 2.6 or higher.
+def combinations(iterable, r):
+ # combinations('ABCD', 2) --> AB AC AD BC BD CD
+ # combinations(range(4), 3) --> 012 013 023 123
+ pool = tuple(iterable)
+ n = len(pool)
+ if r > n:
+ return
+ indices = list(range(r))
+ yield tuple(pool[i] for i in indices)
+ while True:
+ for i in reversed(range(r)):
+ if indices[i] != i + n - r:
+ break
+ else:
+ return
+ indices[i] += 1
+ for j in range(i + 1, r):
+ indices[j] = indices[j - 1] + 1
+ yield tuple(pool[i] for i in indices)
+
+
+# We'd like to use itertools.combinations_with_replacement but it's 2.7 or
+# higher.
+def combinations_with_replacement(iterable, r):
+ # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
+ pool = tuple(iterable)
+ n = len(pool)
+ if not n and r:
+ return
+ indices = [0] * r
+ yield tuple(pool[i] for i in indices)
+ while True:
+ for i in reversed(range(r)):
+ if indices[i] != n - 1:
+ break
+ else:
+ return
+ indices[i:] = [indices[i] + 1] * (r - i)
+ yield tuple(pool[i] for i in indices)
+
+
+def WebIDLTest(parser, harness):
+ types = [
+ "float",
+ "double",
+ "short",
+ "unsigned short",
+ "long",
+ "unsigned long",
+ "long long",
+ "unsigned long long",
+ "boolean",
+ "byte",
+ "octet",
+ "DOMString",
+ "ByteString",
+ "USVString",
+ # "sequence<float>",
+ "object",
+ "ArrayBuffer",
+ # "Date",
+ "TestInterface1",
+ "TestInterface2",
+ ]
+
+ testPre = """
+ interface TestInterface1 {
+ };
+ interface TestInterface2 {
+ };
+ """
+
+ interface = (
+ testPre
+ + """
+ interface PrepareForTest {
+ """
+ )
+ for (i, type) in enumerate(types):
+ interface += string.Template(
+ """
+ readonly attribute ${type} attr${i};
+ """
+ ).substitute(i=i, type=type)
+ interface += """
+ };
+ """
+
+ parser.parse(interface)
+ results = parser.finish()
+
+ iface = results[2]
+
+ parser = parser.reset()
+
+ def typesAreDistinguishable(t):
+ return all(u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2))
+
+ def typesAreNotDistinguishable(t):
+ return any(not u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2))
+
+ def unionTypeName(t):
+ if len(t) > 2:
+ t[0:2] = [unionTypeName(t[0:2])]
+ return "(" + " or ".join(t) + ")"
+
+ # typeCombinations is an iterable of tuples containing the name of the type
+ # as a string and the parsed IDL type.
+ def unionTypes(typeCombinations, predicate):
+ for c in typeCombinations:
+ if predicate(t[1] for t in c):
+ yield unionTypeName([t[0] for t in c])
+
+ # We limit invalid union types with a union member type to the subset of 3
+ # types with one invalid combination.
+ # typeCombinations is an iterable of tuples containing the name of the type
+ # as a string and the parsed IDL type.
+ def invalidUnionWithUnion(typeCombinations):
+ for c in typeCombinations:
+ if (
+ typesAreNotDistinguishable((c[0][1], c[1][1]))
+ and typesAreDistinguishable((c[1][1], c[2][1]))
+ and typesAreDistinguishable((c[0][1], c[2][1]))
+ ):
+ yield unionTypeName([t[0] for t in c])
+
+ # Create a list of tuples containing the name of the type as a string and
+ # the parsed IDL type.
+ types = zip(types, (a.type for a in iface.members))
+
+ validUnionTypes = chain(
+ unionTypes(combinations(types, 2), typesAreDistinguishable),
+ unionTypes(combinations(types, 3), typesAreDistinguishable),
+ )
+ invalidUnionTypes = chain(
+ unionTypes(combinations_with_replacement(types, 2), typesAreNotDistinguishable),
+ invalidUnionWithUnion(combinations(types, 3)),
+ )
+ interface = (
+ testPre
+ + """
+ interface TestUnion {
+ """
+ )
+ for (i, type) in enumerate(validUnionTypes):
+ interface += string.Template(
+ """
+ undefined method${i}(${type} arg);
+ ${type} returnMethod${i}();
+ attribute ${type} attr${i};
+ undefined optionalMethod${i}(${type}? arg);
+ """
+ ).substitute(i=i, type=type)
+ interface += """
+ };
+ """
+ parser.parse(interface)
+ results = parser.finish()
+
+ parser = parser.reset()
+
+ for invalid in invalidUnionTypes:
+ interface = (
+ testPre
+ + string.Template(
+ """
+ interface TestUnion {
+ undefined method(${type} arg);
+ };
+ """
+ ).substitute(type=invalid)
+ )
+
+ threw = False
+ try:
+ parser.parse(interface)
+ results = parser.finish()
+ except Exception:
+ threw = True
+
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()