summaryrefslogtreecommitdiffstats
path: root/dom/bindings/parser/tests/test_nullable_equivalency.py
blob: 5790288ccb9d91b59ec12a313cd7e3aba91b3919 (plain)
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
import WebIDL


def WebIDLTest(parser, harness):
    parser.parse(
        """
        interface TestNullableEquivalency1 {
          attribute long  a;
          attribute long? b;
        };

        interface TestNullableEquivalency2 {
          attribute ArrayBuffer  a;
          attribute ArrayBuffer? b;
        };

        /* Can't have dictionary-valued attributes, so can't test that here */

        enum TestNullableEquivalency4Enum {
          "Foo",
          "Bar"
        };

        interface TestNullableEquivalency4 {
          attribute TestNullableEquivalency4Enum  a;
          attribute TestNullableEquivalency4Enum? b;
        };

        interface TestNullableEquivalency5 {
          attribute TestNullableEquivalency4  a;
          attribute TestNullableEquivalency4? b;
        };

        interface TestNullableEquivalency6 {
          attribute boolean  a;
          attribute boolean? b;
        };

        interface TestNullableEquivalency7 {
          attribute DOMString  a;
          attribute DOMString? b;
        };

        interface TestNullableEquivalency8 {
          attribute float  a;
          attribute float? b;
        };

        interface TestNullableEquivalency9 {
          attribute double  a;
          attribute double? b;
        };

        interface TestNullableEquivalency10 {
          attribute object  a;
          attribute object? b;
        };
    """
    )

    for decl in parser.finish():
        if decl.isInterface():
            checkEquivalent(decl, harness)


def checkEquivalent(iface, harness):
    type1 = iface.members[0].type
    type2 = iface.members[1].type

    harness.check(type1.nullable(), False, "attr1 should not be nullable")
    harness.check(type2.nullable(), True, "attr2 should be nullable")

    # We don't know about type1, but type2, the nullable type, definitely
    # shouldn't be builtin.
    harness.check(type2.builtin, False, "attr2 should not be builtin")

    # Ensure that all attributes of type2 match those in type1, except for:
    #  - names on an ignore list,
    #  - names beginning with '_',
    #  - functions which throw when called with no args, and
    #  - class-level non-callables ("static variables").
    #
    # Yes, this is an ugly, fragile hack.  But it finds bugs...
    for attr in dir(type1):
        if (
            attr.startswith("_")
            or attr
            in [
                "nullable",
                "builtin",
                "filename",
                "location",
                "inner",
                "QName",
                "getDeps",
                "name",
                "prettyName",
            ]
            or (hasattr(type(type1), attr) and not callable(getattr(type1, attr)))
        ):
            continue

        a1 = getattr(type1, attr)

        if callable(a1):
            try:
                v1 = a1()
            except AssertionError:
                # Various methods assert that they're called on objects of
                # the right type, skip them if the assert fails.
                continue
            except TypeError:
                # a1 requires positional arguments, so skip this attribute.
                continue

            try:
                a2 = getattr(type2, attr)
            except WebIDL.WebIDLError:
                harness.ok(
                    False,
                    "Missing %s attribute on type %s in %s" % (attr, type2, iface),
                )
                continue

            if not callable(a2):
                harness.ok(
                    False,
                    "%s attribute on type %s in %s wasn't callable"
                    % (attr, type2, iface),
                )
                continue

            v2 = a2()
            harness.check(v2, v1, "%s method return value" % attr)
        else:
            try:
                a2 = getattr(type2, attr)
            except WebIDL.WebIDLError:
                harness.ok(
                    False,
                    "Missing %s attribute on type %s in %s" % (attr, type2, iface),
                )
                continue

            harness.check(a2, a1, "%s attribute should match" % attr)