|
1 import WebIDL |
|
2 |
|
3 def WebIDLTest(parser, harness): |
|
4 parser.parse(""" |
|
5 interface TestNullableEquivalency1 { |
|
6 attribute long a; |
|
7 attribute long? b; |
|
8 }; |
|
9 |
|
10 interface TestNullableEquivalency2 { |
|
11 attribute ArrayBuffer a; |
|
12 attribute ArrayBuffer? b; |
|
13 }; |
|
14 |
|
15 /* Can't have dictionary-valued attributes, so can't test that here */ |
|
16 |
|
17 enum TestNullableEquivalency4Enum { |
|
18 "Foo", |
|
19 "Bar" |
|
20 }; |
|
21 |
|
22 interface TestNullableEquivalency4 { |
|
23 attribute TestNullableEquivalency4Enum a; |
|
24 attribute TestNullableEquivalency4Enum? b; |
|
25 }; |
|
26 |
|
27 interface TestNullableEquivalency5 { |
|
28 attribute TestNullableEquivalency4 a; |
|
29 attribute TestNullableEquivalency4? b; |
|
30 }; |
|
31 |
|
32 interface TestNullableEquivalency6 { |
|
33 attribute boolean a; |
|
34 attribute boolean? b; |
|
35 }; |
|
36 |
|
37 interface TestNullableEquivalency7 { |
|
38 attribute DOMString a; |
|
39 attribute DOMString? b; |
|
40 }; |
|
41 |
|
42 interface TestNullableEquivalency8 { |
|
43 attribute float a; |
|
44 attribute float? b; |
|
45 }; |
|
46 |
|
47 interface TestNullableEquivalency9 { |
|
48 attribute double a; |
|
49 attribute double? b; |
|
50 }; |
|
51 |
|
52 interface TestNullableEquivalency10 { |
|
53 attribute object a; |
|
54 attribute object? b; |
|
55 }; |
|
56 |
|
57 interface TestNullableEquivalency11 { |
|
58 attribute double[] a; |
|
59 attribute double[]? b; |
|
60 }; |
|
61 |
|
62 interface TestNullableEquivalency12 { |
|
63 attribute TestNullableEquivalency9[] a; |
|
64 attribute TestNullableEquivalency9[]? b; |
|
65 }; |
|
66 """) |
|
67 |
|
68 for decl in parser.finish(): |
|
69 if decl.isInterface(): |
|
70 checkEquivalent(decl, harness) |
|
71 |
|
72 def checkEquivalent(iface, harness): |
|
73 type1 = iface.members[0].type |
|
74 type2 = iface.members[1].type |
|
75 |
|
76 harness.check(type1.nullable(), False, 'attr1 should not be nullable') |
|
77 harness.check(type2.nullable(), True, 'attr2 should be nullable') |
|
78 |
|
79 # We don't know about type1, but type2, the nullable type, definitely |
|
80 # shouldn't be builtin. |
|
81 harness.check(type2.builtin, False, 'attr2 should not be builtin') |
|
82 |
|
83 # Ensure that all attributes of type2 match those in type1, except for: |
|
84 # - names on an ignore list, |
|
85 # - names beginning with '_', |
|
86 # - functions which throw when called with no args, and |
|
87 # - class-level non-callables ("static variables"). |
|
88 # |
|
89 # Yes, this is an ugly, fragile hack. But it finds bugs... |
|
90 for attr in dir(type1): |
|
91 if attr.startswith('_') or \ |
|
92 attr in ['nullable', 'builtin', 'filename', 'location', |
|
93 'inner', 'QName', 'getDeps'] or \ |
|
94 (hasattr(type(type1), attr) and not callable(getattr(type1, attr))): |
|
95 continue |
|
96 |
|
97 a1 = getattr(type1, attr) |
|
98 |
|
99 if callable(a1): |
|
100 try: |
|
101 v1 = a1() |
|
102 except: |
|
103 # Can't call a1 with no args, so skip this attriute. |
|
104 continue |
|
105 |
|
106 try: |
|
107 a2 = getattr(type2, attr) |
|
108 except: |
|
109 harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) |
|
110 continue |
|
111 |
|
112 if not callable(a2): |
|
113 harness.ok(False, "%s attribute on type %s in %s wasn't callable" % (attr, type2, iface)) |
|
114 continue |
|
115 |
|
116 v2 = a2() |
|
117 harness.check(v2, v1, '%s method return value' % attr) |
|
118 else: |
|
119 try: |
|
120 a2 = getattr(type2, attr) |
|
121 except: |
|
122 harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) |
|
123 continue |
|
124 |
|
125 harness.check(a2, a1, '%s attribute should match' % attr) |