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 )