tor-browser

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

test_interface.py (12506B)


      1 import WebIDL
      2 
      3 
      4 def WebIDLTest(parser, harness):
      5    parser.parse("interface Foo { };")
      6    results = parser.finish()
      7    harness.ok(True, "Empty interface parsed without error.")
      8    harness.check(len(results), 1, "Should be one production")
      9    harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
     10    iface = results[0]
     11    harness.check(iface.identifier.QName(), "::Foo", "Interface has the right QName")
     12    harness.check(iface.identifier.name, "Foo", "Interface has the right name")
     13    harness.check(iface.parent, None, "Interface has no parent")
     14 
     15    parser.parse("interface Bar : Foo { };")
     16    results = parser.finish()
     17    harness.ok(True, "Empty interface parsed without error.")
     18    harness.check(len(results), 2, "Should be two productions")
     19    harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
     20    iface = results[1]
     21    harness.check(iface.identifier.QName(), "::Bar", "Interface has the right QName")
     22    harness.check(iface.identifier.name, "Bar", "Interface has the right name")
     23    harness.ok(isinstance(iface.parent, WebIDL.IDLInterface), "Interface has a parent")
     24 
     25    parser = parser.reset()
     26    parser.parse(
     27        """
     28        interface QNameBase {
     29          attribute long foo;
     30        };
     31 
     32        interface QNameDerived : QNameBase {
     33          attribute long long foo;
     34          attribute byte bar;
     35        };
     36    """
     37    )
     38    results = parser.finish()
     39    harness.check(len(results), 2, "Should be two productions")
     40    harness.ok(isinstance(results[0], WebIDL.IDLInterface), "Should be an IDLInterface")
     41    harness.ok(isinstance(results[1], WebIDL.IDLInterface), "Should be an IDLInterface")
     42    harness.check(results[1].parent, results[0], "Inheritance chain is right")
     43    harness.check(len(results[0].members), 1, "Expect 1 productions")
     44    harness.check(len(results[1].members), 2, "Expect 2 productions")
     45    base = results[0]
     46    derived = results[1]
     47    harness.check(
     48        base.members[0].identifier.QName(),
     49        "::QNameBase::foo",
     50        "Member has the right QName",
     51    )
     52    harness.check(
     53        derived.members[0].identifier.QName(),
     54        "::QNameDerived::foo",
     55        "Member has the right QName",
     56    )
     57    harness.check(
     58        derived.members[1].identifier.QName(),
     59        "::QNameDerived::bar",
     60        "Member has the right QName",
     61    )
     62 
     63    parser = parser.reset()
     64    threw = False
     65    try:
     66        parser.parse(
     67            """
     68            interface A : B {};
     69            interface B : A {};
     70        """
     71        )
     72        results = parser.finish()
     73    except WebIDL.WebIDLError:
     74        threw = True
     75 
     76    harness.ok(threw, "Should not allow cycles in interface inheritance chains")
     77 
     78    parser = parser.reset()
     79    threw = False
     80    try:
     81        parser.parse(
     82            """
     83            interface A : C {};
     84            interface C : B {};
     85            interface B : A {};
     86        """
     87        )
     88        results = parser.finish()
     89    except WebIDL.WebIDLError:
     90        threw = True
     91 
     92    harness.ok(
     93        threw, "Should not allow indirect cycles in interface inheritance chains"
     94    )
     95 
     96    parser = parser.reset()
     97    threw = False
     98    try:
     99        parser.parse(
    100            """
    101            interface A;
    102            interface B : A {};
    103        """
    104        )
    105        results = parser.finish()
    106    except WebIDL.WebIDLError:
    107        threw = True
    108 
    109    harness.ok(
    110        threw,
    111        "Should not allow inheriting from an interface that is only forward declared",
    112    )
    113 
    114    parser = parser.reset()
    115    parser.parse(
    116        """
    117        interface A {
    118            constructor();
    119            constructor(long arg);
    120            readonly attribute boolean x;
    121            undefined foo();
    122        };
    123        partial interface A {
    124            readonly attribute boolean y;
    125            undefined foo(long arg);
    126        };
    127    """
    128    )
    129    results = parser.finish()
    130    harness.check(len(results), 2, "Should have two results with partial interface")
    131    iface = results[0]
    132    harness.check(
    133        len(iface.members), 3, "Should have three members with partial interface"
    134    )
    135    harness.check(
    136        iface.members[0].identifier.name,
    137        "x",
    138        "First member should be x with partial interface",
    139    )
    140    harness.check(
    141        iface.members[1].identifier.name,
    142        "foo",
    143        "Second member should be foo with partial interface",
    144    )
    145    harness.check(
    146        len(iface.members[1].signatures()),
    147        2,
    148        "Should have two foo signatures with partial interface",
    149    )
    150    harness.check(
    151        iface.members[2].identifier.name,
    152        "y",
    153        "Third member should be y with partial interface",
    154    )
    155    harness.check(
    156        len(iface.ctor().signatures()),
    157        2,
    158        "Should have two constructors with partial interface",
    159    )
    160 
    161    parser = parser.reset()
    162    parser.parse(
    163        """
    164        partial interface A {
    165            readonly attribute boolean y;
    166            undefined foo(long arg);
    167        };
    168        interface A {
    169            constructor();
    170            constructor(long arg);
    171            readonly attribute boolean x;
    172            undefined foo();
    173        };
    174    """
    175    )
    176    results = parser.finish()
    177    harness.check(
    178        len(results), 2, "Should have two results with reversed partial interface"
    179    )
    180    iface = results[1]
    181    harness.check(
    182        len(iface.members),
    183        3,
    184        "Should have three members with reversed partial interface",
    185    )
    186    harness.check(
    187        iface.members[0].identifier.name,
    188        "x",
    189        "First member should be x with reversed partial interface",
    190    )
    191    harness.check(
    192        iface.members[1].identifier.name,
    193        "foo",
    194        "Second member should be foo with reversed partial interface",
    195    )
    196    harness.check(
    197        len(iface.members[1].signatures()),
    198        2,
    199        "Should have two foo signatures with reversed partial interface",
    200    )
    201    harness.check(
    202        iface.members[2].identifier.name,
    203        "y",
    204        "Third member should be y with reversed partial interface",
    205    )
    206    harness.check(
    207        len(iface.ctor().signatures()),
    208        2,
    209        "Should have two constructors with reversed partial interface",
    210    )
    211 
    212    parser = parser.reset()
    213    threw = False
    214    try:
    215        parser.parse(
    216            """
    217            interface A {
    218                readonly attribute boolean x;
    219            };
    220            interface A {
    221                readonly attribute boolean y;
    222            };
    223        """
    224        )
    225        results = parser.finish()
    226    except WebIDL.WebIDLError:
    227        threw = True
    228    harness.ok(threw, "Should not allow two non-partial interfaces with the same name")
    229 
    230    parser = parser.reset()
    231    threw = False
    232    try:
    233        parser.parse(
    234            """
    235            partial interface A {
    236                readonly attribute boolean x;
    237            };
    238            partial interface A {
    239                readonly attribute boolean y;
    240            };
    241        """
    242        )
    243        results = parser.finish()
    244    except WebIDL.WebIDLError:
    245        threw = True
    246    harness.ok(threw, "Must have a non-partial interface for a given name")
    247 
    248    parser = parser.reset()
    249    threw = False
    250    try:
    251        parser.parse(
    252            """
    253            dictionary  A {
    254                boolean x;
    255            };
    256            partial interface A {
    257                readonly attribute boolean y;
    258            };
    259        """
    260        )
    261        results = parser.finish()
    262    except WebIDL.WebIDLError:
    263        threw = True
    264    harness.ok(
    265        threw,
    266        "Should not allow a name collision between partial interface and other object",
    267    )
    268 
    269    parser = parser.reset()
    270    threw = False
    271    try:
    272        parser.parse(
    273            """
    274            dictionary A {
    275                boolean x;
    276            };
    277            interface A {
    278                readonly attribute boolean y;
    279            };
    280        """
    281        )
    282        results = parser.finish()
    283    except WebIDL.WebIDLError:
    284        threw = True
    285    harness.ok(
    286        threw, "Should not allow a name collision between interface and other object"
    287    )
    288 
    289    parser = parser.reset()
    290    threw = False
    291    try:
    292        parser.parse(
    293            """
    294            dictionary A {
    295                boolean x;
    296            };
    297            interface A;
    298        """
    299        )
    300        results = parser.finish()
    301    except WebIDL.WebIDLError:
    302        threw = True
    303    harness.ok(
    304        threw,
    305        "Should not allow a name collision between external interface and other object",
    306    )
    307 
    308    parser = parser.reset()
    309    threw = False
    310    try:
    311        parser.parse(
    312            """
    313            interface A {
    314                readonly attribute boolean x;
    315            };
    316            interface A;
    317        """
    318        )
    319        results = parser.finish()
    320    except WebIDL.WebIDLError:
    321        threw = True
    322    harness.ok(
    323        threw,
    324        "Should not allow a name collision between external interface and interface",
    325    )
    326 
    327    parser = parser.reset()
    328    parser.parse(
    329        """
    330        interface A;
    331        interface A;
    332    """
    333    )
    334    results = parser.finish()
    335    harness.ok(
    336        len(results) == 1 and isinstance(results[0], WebIDL.IDLExternalInterface),
    337        "Should allow name collisions between external interface declarations",
    338    )
    339 
    340    parser = parser.reset()
    341    threw = False
    342    try:
    343        parser.parse(
    344            """
    345            [SomeRandomAnnotation]
    346            interface A {
    347                readonly attribute boolean y;
    348            };
    349        """
    350        )
    351        results = parser.finish()
    352    except WebIDL.WebIDLError:
    353        threw = True
    354    harness.ok(threw, "Should not allow unknown extended attributes on interfaces")
    355 
    356    parser = parser.reset()
    357    parser.parse(
    358        """
    359        [Global=Window, Exposed=Window] interface Window {};
    360        [Exposed=Window, LegacyWindowAlias=A]
    361        interface B {};
    362        [Exposed=Window, LegacyWindowAlias=(C, D)]
    363        interface E {};
    364    """
    365    )
    366    results = parser.finish()
    367    harness.check(
    368        results[1].legacyWindowAliases, ["A"], "Should support a single identifier"
    369    )
    370    harness.check(
    371        results[2].legacyWindowAliases, ["C", "D"], "Should support an identifier list"
    372    )
    373 
    374    parser = parser.reset()
    375    threw = False
    376    try:
    377        parser.parse(
    378            """
    379            [LegacyWindowAlias]
    380            interface A {};
    381        """
    382        )
    383        results = parser.finish()
    384    except WebIDL.WebIDLError:
    385        threw = True
    386    harness.ok(threw, "Should not allow [LegacyWindowAlias] with no value")
    387 
    388    parser = parser.reset()
    389    threw = False
    390    try:
    391        parser.parse(
    392            """
    393            [Exposed=Worker, LegacyWindowAlias=B]
    394            interface A {};
    395        """
    396        )
    397        results = parser.finish()
    398    except WebIDL.WebIDLError:
    399        threw = True
    400    harness.ok(threw, "Should not allow [LegacyWindowAlias] without Window exposure")
    401 
    402    parser = parser.reset()
    403    threw = False
    404    try:
    405        parser.parse(
    406            """
    407            [Global=Window, Exposed=Window] interface Window {};
    408            [Exposed=Window]
    409            interface A {};
    410            [Exposed=Window, LegacyWindowAlias=A]
    411            interface B {};
    412        """
    413        )
    414        results = parser.finish()
    415    except WebIDL.WebIDLError:
    416        threw = True
    417    harness.ok(
    418        threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
    419    )
    420 
    421    parser = parser.reset()
    422    threw = False
    423    try:
    424        parser.parse(
    425            """
    426            [Global=Window, Exposed=Window] interface Window {};
    427            [Exposed=Window, LegacyWindowAlias=A]
    428            interface B {};
    429            [Exposed=Window]
    430            interface A {};
    431        """
    432        )
    433        results = parser.finish()
    434    except WebIDL.WebIDLError:
    435        threw = True
    436    harness.ok(
    437        threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
    438    )
    439 
    440    parser = parser.reset()
    441    threw = False
    442    try:
    443        parser.parse(
    444            """
    445            [Global=Window, Exposed=Window] interface Window {};
    446            [Exposed=Window, LegacyWindowAlias=A]
    447            interface B {};
    448            [Exposed=Window, LegacyWindowAlias=A]
    449            interface C {};
    450        """
    451        )
    452        results = parser.finish()
    453    except WebIDL.WebIDLError:
    454        threw = True
    455    harness.ok(
    456        threw, "Should not allow [LegacyWindowAlias] to conflict with other identifiers"
    457    )