tor-browser

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

test_interface_maplikesetlikeiterable.py (28497B)


      1 import WebIDL
      2 
      3 
      4 def WebIDLTest(parser, harness):
      5    def shouldPass(prefix, iface, expectedMembers, numProductions=1):
      6        p = parser.reset()
      7        p.parse(iface)
      8        results = p.finish()
      9        harness.check(
     10            len(results),
     11            numProductions,
     12            "%s - Should have production count %d" % (prefix, numProductions),
     13        )
     14        harness.ok(
     15            isinstance(results[0], WebIDL.IDLInterface),
     16            "%s - Should be an IDLInterface" % (prefix),
     17        )
     18        # Make a copy, since we plan to modify it
     19        expectedMembers = list(expectedMembers)
     20        for m in results[0].members:
     21            name = m.identifier.name
     22            if m.isMethod() and m.isStatic():
     23                # None of the expected members are static methods, so ignore those.
     24                harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m)))
     25            elif (name, type(m)) in expectedMembers:
     26                harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m)))
     27                expectedMembers.remove((name, type(m)))
     28            else:
     29                harness.ok(
     30                    False,
     31                    "%s - %s - Unknown symbol of type %s" % (prefix, name, type(m)),
     32                )
     33        # A bit of a hoop because we can't generate the error string if we pass
     34        if len(expectedMembers) == 0:
     35            harness.ok(True, "Found all the members")
     36        else:
     37            harness.ok(
     38                False,
     39                "Expected member not found: %s of type %s"
     40                % (expectedMembers[0][0], expectedMembers[0][1]),
     41            )
     42        return results
     43 
     44    def shouldFail(prefix, iface):
     45        try:
     46            p = parser.reset()
     47            p.parse(iface)
     48            p.finish()
     49            harness.ok(False, prefix + " - Interface passed when should've failed")
     50        except WebIDL.WebIDLError:
     51            harness.ok(True, prefix + " - Interface failed as expected")
     52        except Exception as e:
     53            harness.ok(
     54                False,
     55                prefix
     56                + " - Interface failed but not as a WebIDLError exception: %s" % e,
     57            )
     58 
     59    iterableMembers = [
     60        (x, WebIDL.IDLMethod) for x in ["entries", "keys", "values", "forEach"]
     61    ]
     62    setROMembers = (
     63        [(x, WebIDL.IDLMethod) for x in ["has"]]
     64        + [("__setlike", WebIDL.IDLMaplikeOrSetlike)]
     65        + iterableMembers
     66    )
     67    setROMembers.extend([("size", WebIDL.IDLAttribute)])
     68    setRWMembers = [
     69        (x, WebIDL.IDLMethod) for x in ["add", "clear", "delete"]
     70    ] + setROMembers
     71    mapROMembers = (
     72        [(x, WebIDL.IDLMethod) for x in ["get", "has"]]
     73        + [("__maplike", WebIDL.IDLMaplikeOrSetlike)]
     74        + iterableMembers
     75    )
     76    mapROMembers.extend([("size", WebIDL.IDLAttribute)])
     77    mapRWMembers = [
     78        (x, WebIDL.IDLMethod) for x in ["set", "clear", "delete"]
     79    ] + mapROMembers
     80 
     81    # OK, now that we've used iterableMembers to set up the above, append
     82    # __iterable to it for the iterable<> case.
     83    iterableMembers.append(("__iterable", WebIDL.IDLIterable))
     84 
     85    asyncIterableMembers = [
     86        (x, WebIDL.IDLMethod) for x in ["entries", "keys", "values"]
     87    ]
     88    asyncIterableMembers.append(("__async_iterable", WebIDL.IDLAsyncIterable))
     89 
     90    valueIterableMembers = [("__iterable", WebIDL.IDLIterable)]
     91    valueIterableMembers.append(("__indexedgetter", WebIDL.IDLMethod))
     92    valueIterableMembers.append(("length", WebIDL.IDLAttribute))
     93 
     94    valueAsyncIterableMembers = [("__async_iterable", WebIDL.IDLAsyncIterable)]
     95    valueAsyncIterableMembers.append(("values", WebIDL.IDLMethod))
     96 
     97    disallowedIterableNames = [
     98        ("keys", WebIDL.IDLMethod),
     99        ("entries", WebIDL.IDLMethod),
    100        ("values", WebIDL.IDLMethod),
    101    ]
    102    disallowedMemberNames = [
    103        ("forEach", WebIDL.IDLMethod),
    104        ("has", WebIDL.IDLMethod),
    105        ("size", WebIDL.IDLAttribute),
    106    ] + disallowedIterableNames
    107    mapDisallowedMemberNames = [("get", WebIDL.IDLMethod)] + disallowedMemberNames
    108    disallowedNonMethodNames = [
    109        ("clear", WebIDL.IDLMethod),
    110        ("delete", WebIDL.IDLMethod),
    111    ]
    112    mapDisallowedNonMethodNames = [("set", WebIDL.IDLMethod)] + disallowedNonMethodNames
    113    setDisallowedNonMethodNames = [("add", WebIDL.IDLMethod)] + disallowedNonMethodNames
    114    unrelatedMembers = [
    115        ("unrelatedAttribute", WebIDL.IDLAttribute),
    116        ("unrelatedMethod", WebIDL.IDLMethod),
    117    ]
    118 
    119    #
    120    # Simple Usage Tests
    121    #
    122 
    123    shouldPass(
    124        "Iterable (key only)",
    125        """
    126               interface Foo1 {
    127               iterable<long>;
    128               readonly attribute unsigned long length;
    129               getter long(unsigned long index);
    130               attribute long unrelatedAttribute;
    131               long unrelatedMethod();
    132               };
    133               """,
    134        valueIterableMembers + unrelatedMembers,
    135    )
    136 
    137    shouldPass(
    138        "Iterable (key only) inheriting from parent",
    139        """
    140               interface Foo1 : Foo2 {
    141               iterable<long>;
    142               readonly attribute unsigned long length;
    143               getter long(unsigned long index);
    144               };
    145               interface Foo2 {
    146               attribute long unrelatedAttribute;
    147               long unrelatedMethod();
    148               };
    149               """,
    150        valueIterableMembers,
    151        numProductions=2,
    152    )
    153 
    154    shouldPass(
    155        "Iterable (key and value)",
    156        """
    157               interface Foo1 {
    158               iterable<long, long>;
    159               attribute long unrelatedAttribute;
    160               long unrelatedMethod();
    161               };
    162               """,
    163        iterableMembers + unrelatedMembers,
    164        # numProductions == 2 because of the generated iterator iface,
    165        numProductions=2,
    166    )
    167 
    168    shouldPass(
    169        "Iterable (key and value) inheriting from parent",
    170        """
    171               interface Foo1 : Foo2 {
    172               iterable<long, long>;
    173               };
    174               interface Foo2 {
    175               attribute long unrelatedAttribute;
    176               long unrelatedMethod();
    177               };
    178               """,
    179        iterableMembers,
    180        # numProductions == 3 because of the generated iterator iface,
    181        numProductions=3,
    182    )
    183 
    184    shouldPass(
    185        "Async iterable (key only)",
    186        """
    187               interface Foo1 {
    188               async_iterable<long>;
    189               attribute long unrelatedAttribute;
    190               long unrelatedMethod();
    191               };
    192               """,
    193        valueAsyncIterableMembers + unrelatedMembers,
    194        # numProductions == 2 because of the generated iterator iface,
    195        numProductions=2,
    196    )
    197 
    198    shouldPass(
    199        "Async iterable (key only) inheriting from parent",
    200        """
    201               interface Foo1 : Foo2 {
    202               async_iterable<long>;
    203               };
    204               interface Foo2 {
    205               attribute long unrelatedAttribute;
    206               long unrelatedMethod();
    207               };
    208               """,
    209        valueAsyncIterableMembers,
    210        # numProductions == 3 because of the generated iterator iface,
    211        numProductions=3,
    212    )
    213 
    214    shouldPass(
    215        "Async iterable with argument (key only)",
    216        """
    217               interface Foo1 {
    218               async_iterable<long>(optional long foo);
    219               attribute long unrelatedAttribute;
    220               long unrelatedMethod();
    221               };
    222               """,
    223        valueAsyncIterableMembers + unrelatedMembers,
    224        # numProductions == 2 because of the generated iterator iface,
    225        numProductions=2,
    226    )
    227 
    228    shouldPass(
    229        "Async iterable (key and value)",
    230        """
    231               interface Foo1 {
    232               async_iterable<long, long>;
    233               attribute long unrelatedAttribute;
    234               long unrelatedMethod();
    235               };
    236               """,
    237        asyncIterableMembers + unrelatedMembers,
    238        # numProductions == 2 because of the generated iterator iface,
    239        numProductions=2,
    240    )
    241 
    242    shouldPass(
    243        "Async iterable (key and value) inheriting from parent",
    244        """
    245               interface Foo1 : Foo2 {
    246               async_iterable<long, long>;
    247               };
    248               interface Foo2 {
    249               attribute long unrelatedAttribute;
    250               long unrelatedMethod();
    251               };
    252               """,
    253        asyncIterableMembers,
    254        # numProductions == 3 because of the generated iterator iface,
    255        numProductions=3,
    256    )
    257 
    258    shouldPass(
    259        "Async iterable with argument (key and value)",
    260        """
    261               interface Foo1 {
    262               async_iterable<long, long>(optional long foo);
    263               attribute long unrelatedAttribute;
    264               long unrelatedMethod();
    265               };
    266               """,
    267        asyncIterableMembers + unrelatedMembers,
    268        # numProductions == 2 because of the generated iterator iface,
    269        numProductions=2,
    270    )
    271 
    272    shouldPass(
    273        "Maplike (readwrite)",
    274        """
    275               interface Foo1 {
    276               maplike<long, long>;
    277               attribute long unrelatedAttribute;
    278               long unrelatedMethod();
    279               };
    280               """,
    281        mapRWMembers + unrelatedMembers,
    282    )
    283 
    284    shouldPass(
    285        "Maplike (readwrite) inheriting from parent",
    286        """
    287               interface Foo1 : Foo2 {
    288               maplike<long, long>;
    289               };
    290               interface Foo2 {
    291               attribute long unrelatedAttribute;
    292               long unrelatedMethod();
    293               };
    294               """,
    295        mapRWMembers,
    296        numProductions=2,
    297    )
    298 
    299    shouldPass(
    300        "Maplike (readwrite)",
    301        """
    302               interface Foo1 {
    303               maplike<long, long>;
    304               attribute long unrelatedAttribute;
    305               long unrelatedMethod();
    306               };
    307               """,
    308        mapRWMembers + unrelatedMembers,
    309    )
    310 
    311    shouldPass(
    312        "Maplike (readwrite) inheriting from parent",
    313        """
    314               interface Foo1 : Foo2 {
    315               maplike<long, long>;
    316               };
    317               interface Foo2 {
    318               attribute long unrelatedAttribute;
    319               long unrelatedMethod();
    320               };
    321               """,
    322        mapRWMembers,
    323        numProductions=2,
    324    )
    325 
    326    shouldPass(
    327        "Maplike (readonly)",
    328        """
    329               interface Foo1 {
    330               readonly maplike<long, long>;
    331               attribute long unrelatedAttribute;
    332               long unrelatedMethod();
    333               };
    334               """,
    335        mapROMembers + unrelatedMembers,
    336    )
    337 
    338    shouldPass(
    339        "Maplike (readonly) inheriting from parent",
    340        """
    341               interface Foo1 : Foo2 {
    342               readonly maplike<long, long>;
    343               };
    344               interface Foo2 {
    345               attribute long unrelatedAttribute;
    346               long unrelatedMethod();
    347               };
    348               """,
    349        mapROMembers,
    350        numProductions=2,
    351    )
    352 
    353    shouldPass(
    354        "Setlike (readwrite)",
    355        """
    356               interface Foo1 {
    357               setlike<long>;
    358               attribute long unrelatedAttribute;
    359               long unrelatedMethod();
    360               };
    361               """,
    362        setRWMembers + unrelatedMembers,
    363    )
    364 
    365    shouldPass(
    366        "Setlike (readwrite) inheriting from parent",
    367        """
    368               interface Foo1 : Foo2 {
    369               setlike<long>;
    370               };
    371               interface Foo2 {
    372               attribute long unrelatedAttribute;
    373               long unrelatedMethod();
    374               };
    375               """,
    376        setRWMembers,
    377        numProductions=2,
    378    )
    379 
    380    shouldPass(
    381        "Setlike (readonly)",
    382        """
    383               interface Foo1 {
    384               readonly setlike<long>;
    385               attribute long unrelatedAttribute;
    386               long unrelatedMethod();
    387               };
    388               """,
    389        setROMembers + unrelatedMembers,
    390    )
    391 
    392    shouldPass(
    393        "Setlike (readonly) inheriting from parent",
    394        """
    395               interface Foo1 : Foo2 {
    396               readonly setlike<long>;
    397               };
    398               interface Foo2 {
    399               attribute long unrelatedAttribute;
    400               long unrelatedMethod();
    401               };
    402               """,
    403        setROMembers,
    404        numProductions=2,
    405    )
    406 
    407    shouldPass(
    408        "Inheritance of maplike/setlike",
    409        """
    410               interface Foo1 {
    411               maplike<long, long>;
    412               };
    413               interface Foo2 : Foo1 {
    414               };
    415               """,
    416        mapRWMembers,
    417        numProductions=2,
    418    )
    419 
    420    shouldFail(
    421        "JS Implemented maplike interface",
    422        """
    423               [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
    424               interface Foo1 {
    425               constructor();
    426               setlike<long>;
    427               };
    428               """,
    429    )
    430 
    431    shouldFail(
    432        "JS Implemented maplike interface",
    433        """
    434               [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1"]
    435               interface Foo1 {
    436               constructor();
    437               maplike<long, long>;
    438               };
    439               """,
    440    )
    441 
    442    #
    443    # Multiple maplike/setlike tests
    444    #
    445 
    446    shouldFail(
    447        "Two maplike/setlikes on same interface",
    448        """
    449               interface Foo1 {
    450               setlike<long>;
    451               maplike<long, long>;
    452               };
    453               """,
    454    )
    455 
    456    shouldFail(
    457        "Two iterable/setlikes on same interface",
    458        """
    459               interface Foo1 {
    460               iterable<long>;
    461               maplike<long, long>;
    462               };
    463               """,
    464    )
    465 
    466    shouldFail(
    467        "Two iterables on same interface",
    468        """
    469               interface Foo1 {
    470               iterable<long>;
    471               iterable<long, long>;
    472               };
    473               """,
    474    )
    475 
    476    shouldFail(
    477        "Two iterables on same interface",
    478        """
    479               interface Foo1 {
    480               iterable<long>;
    481               async_iterable<long>;
    482               };
    483               """,
    484    )
    485 
    486    shouldFail(
    487        "Two iterables on same interface",
    488        """
    489               interface Foo1 {
    490               async_iterable<long>;
    491               async_iterable<long, long>;
    492               };
    493               """,
    494    )
    495 
    496    shouldFail(
    497        "Async iterable with non-optional arguments",
    498        """
    499               interface Foo1 {
    500               async_iterable<long>(long foo);
    501               };
    502               """,
    503    )
    504 
    505    shouldFail(
    506        "Async iterable with non-optional arguments",
    507        """
    508               interface Foo1 {
    509               async_iterable<long>(optional long foo, long bar);
    510               };
    511               """,
    512    )
    513 
    514    shouldFail(
    515        "Async iterable with non-optional arguments",
    516        """
    517               interface Foo1 {
    518               async_iterable<long, long>(long foo);
    519               };
    520               """,
    521    )
    522 
    523    shouldFail(
    524        "Two maplike/setlikes in partials",
    525        """
    526               interface Foo1 {
    527               maplike<long, long>;
    528               };
    529               partial interface Foo1 {
    530               setlike<long>;
    531               };
    532               """,
    533    )
    534 
    535    shouldFail(
    536        "Conflicting maplike/setlikes across inheritance",
    537        """
    538               interface Foo1 {
    539               maplike<long, long>;
    540               };
    541               interface Foo2 : Foo1 {
    542               setlike<long>;
    543               };
    544               """,
    545    )
    546 
    547    shouldFail(
    548        "Conflicting maplike/iterable across inheritance",
    549        """
    550               interface Foo1 {
    551               maplike<long, long>;
    552               };
    553               interface Foo2 : Foo1 {
    554               iterable<long>;
    555               };
    556               """,
    557    )
    558 
    559    shouldFail(
    560        "Conflicting maplike/setlikes across multistep inheritance",
    561        """
    562               interface Foo1 {
    563               maplike<long, long>;
    564               };
    565               interface Foo2 : Foo1 {
    566               };
    567               interface Foo3 : Foo2 {
    568               setlike<long>;
    569               };
    570               """,
    571    )
    572 
    573    #
    574    # Member name collision tests
    575    #
    576 
    577    def testConflictingMembers(
    578        likeMember, conflict, expectedMembers, methodPasses, numProductions=1
    579    ):
    580        """
    581        Tests for maplike/setlike member generation against conflicting member
    582        names. If methodPasses is True, this means we expect the interface to
    583        pass in the case of method shadowing, and expectedMembers should be the
    584        list of interface members to check against on the passing interface.
    585 
    586        """
    587        (conflictName, conflictType) = conflict
    588        if methodPasses:
    589            shouldPass(
    590                "Conflicting method: %s and %s" % (likeMember, conflictName),
    591                """
    592                       interface Foo1 {
    593                       %s;
    594                       [Throws]
    595                       undefined %s(long test1, double test2, double test3);
    596                       };
    597                       """
    598                % (likeMember, conflictName),
    599                expectedMembers,
    600            )
    601        else:
    602            shouldFail(
    603                "Conflicting method: %s and %s" % (likeMember, conflictName),
    604                """
    605                       interface Foo1 {
    606                       %s;
    607                       [Throws]
    608                       undefined %s(long test1, double test2, double test3);
    609                       };
    610                       """
    611                % (likeMember, conflictName),
    612            )
    613        # Inherited conflicting methods should ALWAYS fail
    614        shouldFail(
    615            "Conflicting inherited method: %s and %s" % (likeMember, conflictName),
    616            """
    617                   interface Foo1 {
    618                   undefined %s(long test1, double test2, double test3);
    619                   };
    620                   interface Foo2 : Foo1 {
    621                   %s;
    622                   };
    623                   """
    624            % (conflictName, likeMember),
    625        )
    626        if conflictType == WebIDL.IDLAttribute:
    627            shouldFail(
    628                "Conflicting static method: %s and %s" % (likeMember, conflictName),
    629                """
    630                       interface Foo1 {
    631                       %s;
    632                       static undefined %s(long test1, double test2, double test3);
    633                       };
    634                       """
    635                % (likeMember, conflictName),
    636            )
    637        else:
    638            shouldPass(
    639                "Conflicting static method: %s and %s" % (likeMember, conflictName),
    640                """
    641                       interface Foo1 {
    642                       %s;
    643                       static undefined %s(long test1, double test2, double test3);
    644                       };
    645                       """
    646                % (likeMember, conflictName),
    647                expectedMembers,
    648                numProductions=numProductions,
    649            )
    650        shouldFail(
    651            "Conflicting attribute: %s and %s" % (likeMember, conflictName),
    652            """
    653                   interface Foo1 {
    654                   %s
    655                   attribute double %s;
    656                   };
    657                   """
    658            % (likeMember, conflictName),
    659        )
    660        shouldFail(
    661            "Conflicting const: %s and %s" % (likeMember, conflictName),
    662            """
    663                   interface Foo1 {
    664                   %s;
    665                   const double %s = 0;
    666                   };
    667                   """
    668            % (likeMember, conflictName),
    669        )
    670        shouldFail(
    671            "Conflicting static attribute: %s and %s" % (likeMember, conflictName),
    672            """
    673                   interface Foo1 {
    674                   %s;
    675                   static attribute long %s;
    676                   };
    677                   """
    678            % (likeMember, conflictName),
    679        )
    680 
    681    for member in disallowedIterableNames:
    682        testConflictingMembers(
    683            "iterable<long, long>", member, iterableMembers, False, numProductions=2
    684        )
    685    for member in mapDisallowedMemberNames:
    686        testConflictingMembers("maplike<long, long>", member, mapRWMembers, False)
    687    for member in disallowedMemberNames:
    688        testConflictingMembers("setlike<long>", member, setRWMembers, False)
    689    for member in mapDisallowedNonMethodNames:
    690        testConflictingMembers("maplike<long, long>", member, mapRWMembers, True)
    691    for member in setDisallowedNonMethodNames:
    692        testConflictingMembers("setlike<long>", member, setRWMembers, True)
    693 
    694    shouldPass(
    695        "Inheritance of maplike/setlike with child member collision",
    696        """
    697               interface Foo1 {
    698               maplike<long, long>;
    699               };
    700               interface Foo2 : Foo1 {
    701               undefined entries();
    702               };
    703               """,
    704        mapRWMembers,
    705        numProductions=2,
    706    )
    707 
    708    shouldPass(
    709        "Inheritance of multi-level maplike/setlike with child member collision",
    710        """
    711               interface Foo1 {
    712               maplike<long, long>;
    713               };
    714               interface Foo2 : Foo1 {
    715               };
    716               interface Foo3 : Foo2 {
    717               undefined entries();
    718               };
    719               """,
    720        mapRWMembers,
    721        numProductions=3,
    722    )
    723 
    724    shouldFail(
    725        "Maplike interface with mixin member collision",
    726        """
    727               interface Foo1 {
    728               maplike<long, long>;
    729               };
    730               interface mixin Foo2 {
    731               undefined entries();
    732               };
    733               Foo1 includes Foo2;
    734               """,
    735    )
    736 
    737    shouldPass(
    738        "Inherited Maplike interface with consequential interface member collision",
    739        """
    740               interface Foo1 {
    741               maplike<long, long>;
    742               };
    743               interface mixin Foo2 {
    744               undefined entries();
    745               };
    746               interface Foo3 : Foo1 {
    747               };
    748               Foo3 includes Foo2;
    749               """,
    750        mapRWMembers,
    751        numProductions=4,
    752    )
    753 
    754    shouldFail(
    755        "Inheritance of name collision with child maplike/setlike",
    756        """
    757               interface Foo1 {
    758               undefined entries();
    759               };
    760               interface Foo2 : Foo1 {
    761               maplike<long, long>;
    762               };
    763               """,
    764    )
    765 
    766    shouldFail(
    767        "Inheritance of multi-level name collision with child maplike/setlike",
    768        """
    769               interface Foo1 {
    770               undefined entries();
    771               };
    772               interface Foo2 : Foo1 {
    773               };
    774               interface Foo3 : Foo2 {
    775               maplike<long, long>;
    776               };
    777               """,
    778    )
    779 
    780    shouldPass(
    781        "Inheritance of attribute collision with parent maplike/setlike",
    782        """
    783               interface Foo1 {
    784               maplike<long, long>;
    785               };
    786               interface Foo2 : Foo1 {
    787               attribute double size;
    788               };
    789               """,
    790        mapRWMembers,
    791        numProductions=2,
    792    )
    793 
    794    shouldPass(
    795        "Inheritance of multi-level attribute collision with parent maplike/setlike",
    796        """
    797               interface Foo1 {
    798               maplike<long, long>;
    799               };
    800               interface Foo2 : Foo1 {
    801               };
    802               interface Foo3 : Foo2 {
    803               attribute double size;
    804               };
    805               """,
    806        mapRWMembers,
    807        numProductions=3,
    808    )
    809 
    810    shouldFail(
    811        "Inheritance of attribute collision with child maplike/setlike",
    812        """
    813               interface Foo1 {
    814               attribute double size;
    815               };
    816               interface Foo2 : Foo1 {
    817               maplike<long, long>;
    818               };
    819               """,
    820    )
    821 
    822    shouldFail(
    823        "Inheritance of multi-level attribute collision with child maplike/setlike",
    824        """
    825               interface Foo1 {
    826               attribute double size;
    827               };
    828               interface Foo2 : Foo1 {
    829               };
    830               interface Foo3 : Foo2 {
    831               maplike<long, long>;
    832               };
    833               """,
    834    )
    835 
    836    shouldFail(
    837        "Inheritance of attribute/rw function collision with child maplike/setlike",
    838        """
    839               interface Foo1 {
    840               attribute double set;
    841               };
    842               interface Foo2 : Foo1 {
    843               maplike<long, long>;
    844               };
    845               """,
    846    )
    847 
    848    shouldFail(
    849        "Inheritance of const/rw function collision with child maplike/setlike",
    850        """
    851               interface Foo1 {
    852               const double set = 0;
    853               };
    854               interface Foo2 : Foo1 {
    855               maplike<long, long>;
    856               };
    857               """,
    858    )
    859 
    860    shouldPass(
    861        "Inheritance of rw function with same name in child maplike/setlike",
    862        """
    863               interface Foo1 {
    864               maplike<long, long>;
    865               };
    866               interface Foo2 : Foo1 {
    867               undefined clear();
    868               };
    869               """,
    870        mapRWMembers,
    871        numProductions=2,
    872    )
    873 
    874    shouldFail(
    875        "Inheritance of unforgeable attribute collision with child maplike/setlike",
    876        """
    877               interface Foo1 {
    878               [LegacyUnforgeable]
    879               attribute double size;
    880               };
    881               interface Foo2 : Foo1 {
    882               maplike<long, long>;
    883               };
    884               """,
    885    )
    886 
    887    shouldFail(
    888        "Inheritance of multi-level unforgeable attribute collision with child maplike/setlike",
    889        """
    890               interface Foo1 {
    891               [LegacyUnforgeable]
    892               attribute double size;
    893               };
    894               interface Foo2 : Foo1 {
    895               };
    896               interface Foo3 : Foo2 {
    897               maplike<long, long>;
    898               };
    899               """,
    900    )
    901 
    902    shouldPass(
    903        "Interface with readonly allowable overrides",
    904        """
    905               interface Foo1 {
    906               readonly setlike<long>;
    907               readonly attribute boolean clear;
    908               };
    909               """,
    910        setROMembers + [("clear", WebIDL.IDLAttribute)],
    911    )
    912 
    913    r = shouldPass(
    914        "Check proper override of clear/delete/set",
    915        """
    916                   interface Foo1 {
    917                   maplike<long, long>;
    918                   long clear(long a, long b, double c, double d);
    919                   long set(long a, long b, double c, double d);
    920                   long delete(long a, long b, double c, double d);
    921                   };
    922                   """,
    923        mapRWMembers,
    924    )
    925 
    926    for m in r[0].members:
    927        if m.identifier.name in ["clear", "set", "delete"]:
    928            harness.ok(m.isMethod(), "%s should be a method" % m.identifier.name)
    929            harness.check(
    930                m.maxArgCount, 4, "%s should have 4 arguments" % m.identifier.name
    931            )
    932            harness.ok(
    933                not m.isMaplikeOrSetlikeOrIterableMethod(),
    934                "%s should not be a maplike/setlike function" % m.identifier.name,
    935            )
    936 
    937    tests = [
    938        ("maplike", "  maplike<long, long>;"),
    939        ("setlike", "  readonly setlike<long>;"),
    940        ("iterable", "  iterable<long>;"),
    941        ("async_iterable", "  async_iterable<long, long>;"),
    942    ]
    943 
    944    for name, line in tests:
    945        parser = parser.reset()
    946        lines = [
    947            "interface Foo {",
    948            line,
    949            "  readonly attribute unsigned long length;",
    950            "  getter long(unsigned long index);",
    951            "};",
    952        ]
    953        parser.parse("\n".join(lines))
    954        results = parser.finish()
    955 
    956        p = results[0].members[0]
    957 
    958        harness.check(p.identifier.name, "__" + name, "Correct name")
    959 
    960        colno = line.find(name)
    961 
    962        loc_lines = str(p.identifier.location).split("\n")
    963 
    964        harness.check(loc_lines[1], line, "Second line shows the input")
    965        harness.check(
    966            loc_lines[2],
    967            " " * colno + "^",
    968            "Correct column pointer in location string",
    969        )