dom/bindings/parser/tests/test_union.py

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 import WebIDL
michael@0 2 import itertools
michael@0 3 import string
michael@0 4
michael@0 5 # We'd like to use itertools.chain but it's 2.6 or higher.
michael@0 6 def chain(*iterables):
michael@0 7 # chain('ABC', 'DEF') --> A B C D E F
michael@0 8 for it in iterables:
michael@0 9 for element in it:
michael@0 10 yield element
michael@0 11
michael@0 12 # We'd like to use itertools.combinations but it's 2.6 or higher.
michael@0 13 def combinations(iterable, r):
michael@0 14 # combinations('ABCD', 2) --> AB AC AD BC BD CD
michael@0 15 # combinations(range(4), 3) --> 012 013 023 123
michael@0 16 pool = tuple(iterable)
michael@0 17 n = len(pool)
michael@0 18 if r > n:
michael@0 19 return
michael@0 20 indices = range(r)
michael@0 21 yield tuple(pool[i] for i in indices)
michael@0 22 while True:
michael@0 23 for i in reversed(range(r)):
michael@0 24 if indices[i] != i + n - r:
michael@0 25 break
michael@0 26 else:
michael@0 27 return
michael@0 28 indices[i] += 1
michael@0 29 for j in range(i+1, r):
michael@0 30 indices[j] = indices[j-1] + 1
michael@0 31 yield tuple(pool[i] for i in indices)
michael@0 32
michael@0 33 # We'd like to use itertools.combinations_with_replacement but it's 2.7 or
michael@0 34 # higher.
michael@0 35 def combinations_with_replacement(iterable, r):
michael@0 36 # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
michael@0 37 pool = tuple(iterable)
michael@0 38 n = len(pool)
michael@0 39 if not n and r:
michael@0 40 return
michael@0 41 indices = [0] * r
michael@0 42 yield tuple(pool[i] for i in indices)
michael@0 43 while True:
michael@0 44 for i in reversed(range(r)):
michael@0 45 if indices[i] != n - 1:
michael@0 46 break
michael@0 47 else:
michael@0 48 return
michael@0 49 indices[i:] = [indices[i] + 1] * (r - i)
michael@0 50 yield tuple(pool[i] for i in indices)
michael@0 51
michael@0 52 def WebIDLTest(parser, harness):
michael@0 53 types = ["float",
michael@0 54 "double",
michael@0 55 "short",
michael@0 56 "unsigned short",
michael@0 57 "long",
michael@0 58 "unsigned long",
michael@0 59 "long long",
michael@0 60 "unsigned long long",
michael@0 61 "boolean",
michael@0 62 "byte",
michael@0 63 "octet",
michael@0 64 "DOMString",
michael@0 65 "ByteString",
michael@0 66 #"sequence<float>",
michael@0 67 "object",
michael@0 68 "ArrayBuffer",
michael@0 69 #"Date",
michael@0 70 "TestInterface1",
michael@0 71 "TestInterface2"]
michael@0 72
michael@0 73 testPre = """
michael@0 74 interface TestInterface1 {
michael@0 75 };
michael@0 76 interface TestInterface2 {
michael@0 77 };
michael@0 78 """
michael@0 79
michael@0 80 interface = testPre + """
michael@0 81 interface PrepareForTest {
michael@0 82 """
michael@0 83 for (i, type) in enumerate(types):
michael@0 84 interface += string.Template("""
michael@0 85 readonly attribute ${type} attr${i};
michael@0 86 """).substitute(i=i, type=type)
michael@0 87 interface += """
michael@0 88 };
michael@0 89 """
michael@0 90
michael@0 91 parser.parse(interface)
michael@0 92 results = parser.finish()
michael@0 93
michael@0 94 iface = results[2]
michael@0 95
michael@0 96 parser = parser.reset()
michael@0 97
michael@0 98 def typesAreDistinguishable(t):
michael@0 99 return all(u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2))
michael@0 100 def typesAreNotDistinguishable(t):
michael@0 101 return any(not u[0].isDistinguishableFrom(u[1]) for u in combinations(t, 2))
michael@0 102 def unionTypeName(t):
michael@0 103 if len(t) > 2:
michael@0 104 t[0:2] = [unionTypeName(t[0:2])]
michael@0 105 return "(" + " or ".join(t) + ")"
michael@0 106
michael@0 107 # typeCombinations is an iterable of tuples containing the name of the type
michael@0 108 # as a string and the parsed IDL type.
michael@0 109 def unionTypes(typeCombinations, predicate):
michael@0 110 for c in typeCombinations:
michael@0 111 if predicate(t[1] for t in c):
michael@0 112 yield unionTypeName([t[0] for t in c])
michael@0 113
michael@0 114 # We limit invalid union types with a union member type to the subset of 3
michael@0 115 # types with one invalid combination.
michael@0 116 # typeCombinations is an iterable of tuples containing the name of the type
michael@0 117 # as a string and the parsed IDL type.
michael@0 118 def invalidUnionWithUnion(typeCombinations):
michael@0 119 for c in typeCombinations:
michael@0 120 if (typesAreNotDistinguishable((c[0][1], c[1][1])) and
michael@0 121 typesAreDistinguishable((c[1][1], c[2][1])) and
michael@0 122 typesAreDistinguishable((c[0][1], c[2][1]))):
michael@0 123 yield unionTypeName([t[0] for t in c])
michael@0 124
michael@0 125 # Create a list of tuples containing the name of the type as a string and
michael@0 126 # the parsed IDL type.
michael@0 127 types = zip(types, (a.type for a in iface.members))
michael@0 128
michael@0 129 validUnionTypes = chain(unionTypes(combinations(types, 2), typesAreDistinguishable),
michael@0 130 unionTypes(combinations(types, 3), typesAreDistinguishable))
michael@0 131 invalidUnionTypes = chain(unionTypes(combinations_with_replacement(types, 2), typesAreNotDistinguishable),
michael@0 132 invalidUnionWithUnion(combinations(types, 3)))
michael@0 133 interface = testPre + """
michael@0 134 interface TestUnion {
michael@0 135 """
michael@0 136 for (i, type) in enumerate(validUnionTypes):
michael@0 137 interface += string.Template("""
michael@0 138 void method${i}(${type} arg);
michael@0 139 ${type} returnMethod${i}();
michael@0 140 attribute ${type} attr${i};
michael@0 141 void arrayMethod${i}(${type}[] arg);
michael@0 142 ${type}[] arrayReturnMethod${i}();
michael@0 143 attribute ${type}[] arrayAttr${i};
michael@0 144 void optionalMethod${i}(${type}? arg);
michael@0 145 """).substitute(i=i, type=type)
michael@0 146 interface += """
michael@0 147 };
michael@0 148 """
michael@0 149 parser.parse(interface)
michael@0 150 results = parser.finish()
michael@0 151
michael@0 152 parser = parser.reset()
michael@0 153
michael@0 154 for invalid in invalidUnionTypes:
michael@0 155 interface = testPre + string.Template("""
michael@0 156 interface TestUnion {
michael@0 157 void method(${type} arg);
michael@0 158 };
michael@0 159 """).substitute(type=invalid)
michael@0 160
michael@0 161 threw = False
michael@0 162 try:
michael@0 163 parser.parse(interface)
michael@0 164 results = parser.finish()
michael@0 165 except:
michael@0 166 threw = True
michael@0 167
michael@0 168 harness.ok(threw, "Should have thrown.")
michael@0 169
michael@0 170 parser = parser.reset()

mercurial