1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
import WebIDL
import itertools
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 = 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",
#"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("""
void method${i}(${type} arg);
${type} returnMethod${i}();
attribute ${type} attr${i};
void arrayMethod${i}(${type}[] arg);
${type}[] arrayReturnMethod${i}();
attribute ${type}[] arrayAttr${i};
void 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 {
void method(${type} arg);
};
""").substitute(type=invalid)
threw = False
try:
parser.parse(interface)
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown.")
parser = parser.reset()
|