summaryrefslogtreecommitdiffstats
path: root/dom/bindings/parser/tests/test_nullable_equivalency.py
blob: 278794f71984afa3010e5a414c1ac2ac514bd969 (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
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 Exception:
                # Can't call a1 with no args, so skip this attriute.
                continue

            try:
                a2 = getattr(type2, attr)
            except Exception:
                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 Exception:
                harness.ok(
                    False,
                    "Missing %s attribute on type %s in %s" % (attr, type2, iface),
                )
                continue

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