michael@0: import WebIDL michael@0: michael@0: def WebIDLTest(parser, harness): michael@0: parser.parse(""" michael@0: interface TestNullableEquivalency1 { michael@0: attribute long a; michael@0: attribute long? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency2 { michael@0: attribute ArrayBuffer a; michael@0: attribute ArrayBuffer? b; michael@0: }; michael@0: michael@0: /* Can't have dictionary-valued attributes, so can't test that here */ michael@0: michael@0: enum TestNullableEquivalency4Enum { michael@0: "Foo", michael@0: "Bar" michael@0: }; michael@0: michael@0: interface TestNullableEquivalency4 { michael@0: attribute TestNullableEquivalency4Enum a; michael@0: attribute TestNullableEquivalency4Enum? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency5 { michael@0: attribute TestNullableEquivalency4 a; michael@0: attribute TestNullableEquivalency4? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency6 { michael@0: attribute boolean a; michael@0: attribute boolean? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency7 { michael@0: attribute DOMString a; michael@0: attribute DOMString? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency8 { michael@0: attribute float a; michael@0: attribute float? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency9 { michael@0: attribute double a; michael@0: attribute double? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency10 { michael@0: attribute object a; michael@0: attribute object? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency11 { michael@0: attribute double[] a; michael@0: attribute double[]? b; michael@0: }; michael@0: michael@0: interface TestNullableEquivalency12 { michael@0: attribute TestNullableEquivalency9[] a; michael@0: attribute TestNullableEquivalency9[]? b; michael@0: }; michael@0: """) michael@0: michael@0: for decl in parser.finish(): michael@0: if decl.isInterface(): michael@0: checkEquivalent(decl, harness) michael@0: michael@0: def checkEquivalent(iface, harness): michael@0: type1 = iface.members[0].type michael@0: type2 = iface.members[1].type michael@0: michael@0: harness.check(type1.nullable(), False, 'attr1 should not be nullable') michael@0: harness.check(type2.nullable(), True, 'attr2 should be nullable') michael@0: michael@0: # We don't know about type1, but type2, the nullable type, definitely michael@0: # shouldn't be builtin. michael@0: harness.check(type2.builtin, False, 'attr2 should not be builtin') michael@0: michael@0: # Ensure that all attributes of type2 match those in type1, except for: michael@0: # - names on an ignore list, michael@0: # - names beginning with '_', michael@0: # - functions which throw when called with no args, and michael@0: # - class-level non-callables ("static variables"). michael@0: # michael@0: # Yes, this is an ugly, fragile hack. But it finds bugs... michael@0: for attr in dir(type1): michael@0: if attr.startswith('_') or \ michael@0: attr in ['nullable', 'builtin', 'filename', 'location', michael@0: 'inner', 'QName', 'getDeps'] or \ michael@0: (hasattr(type(type1), attr) and not callable(getattr(type1, attr))): michael@0: continue michael@0: michael@0: a1 = getattr(type1, attr) michael@0: michael@0: if callable(a1): michael@0: try: michael@0: v1 = a1() michael@0: except: michael@0: # Can't call a1 with no args, so skip this attriute. michael@0: continue michael@0: michael@0: try: michael@0: a2 = getattr(type2, attr) michael@0: except: michael@0: harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) michael@0: continue michael@0: michael@0: if not callable(a2): michael@0: harness.ok(False, "%s attribute on type %s in %s wasn't callable" % (attr, type2, iface)) michael@0: continue michael@0: michael@0: v2 = a2() michael@0: harness.check(v2, v1, '%s method return value' % attr) michael@0: else: michael@0: try: michael@0: a2 = getattr(type2, attr) michael@0: except: michael@0: harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface)) michael@0: continue michael@0: michael@0: harness.check(a2, a1, '%s attribute should match' % attr)