tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_union.py (5340B)


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