this repo has no description
at trunk 1649 lines 56 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "type-builtins.h" 3 4#include "cpython-types.h" 5#include "gtest/gtest.h" 6 7#include "attributedict.h" 8#include "builtins.h" 9#include "dict-builtins.h" 10#include "handles.h" 11#include "ic.h" 12#include "module-builtins.h" 13#include "objects.h" 14#include "runtime.h" 15#include "str-builtins.h" 16#include "test-utils.h" 17 18namespace py { 19namespace testing { 20 21using TypeBuiltinsDeathTest = RuntimeFixture; 22using TypeBuiltinsTest = RuntimeFixture; 23 24TEST_F(TypeBuiltinsTest, TypeAtReturnsNoPlaceholderValue) { 25 HandleScope scope(thread_); 26 Type type(&scope, runtime_->newType()); 27 Object name(&scope, Runtime::internStrFromCStr(thread_, "__ne__")); 28 Object value(&scope, Runtime::internStrFromCStr(thread_, "__ne__'s value")); 29 typeAtPut(thread_, type, name, value); 30 EXPECT_EQ(typeAt(type, name), *value); 31 EXPECT_EQ(typeAtById(thread_, type, ID(__ne__)), *value); 32} 33 34TEST_F(TypeBuiltinsTest, TypeAtReturnsErrorNotFoundForPlaceholder) { 35 HandleScope scope(thread_); 36 Type type(&scope, runtime_->newType()); 37 Object name(&scope, Runtime::internStrFromCStr(thread_, "__ne__")); 38 Object value(&scope, Runtime::internStrFromCStr(thread_, "__ne__'s value")); 39 ValueCell value_cell(&scope, typeAtPut(thread_, type, name, value)); 40 value_cell.makePlaceholder(); 41 EXPECT_TRUE(typeAt(type, name).isErrorNotFound()); 42 EXPECT_TRUE(typeAtById(thread_, type, ID(__ne__)).isErrorNotFound()); 43} 44 45TEST_F(TypeBuiltinsTest, TypeAtPutPutsValueInValueCell) { 46 HandleScope scope(thread_); 47 Type type(&scope, runtime_->newType()); 48 Object name(&scope, Runtime::internStrFromCStr(thread_, "__ne__")); 49 Object value(&scope, Runtime::internStrFromCStr(thread_, "__ne__'s value")); 50 51 ValueCell result(&scope, typeAtPut(thread_, type, name, value)); 52 ASSERT_EQ(result.value(), *value); 53 EXPECT_EQ(typeAt(type, name), *value); 54 result.setValue(NoneType::object()); 55 56 result = typeAtPutById(thread_, type, ID(__ne__), value); 57 ASSERT_EQ(result.value(), *value); 58 EXPECT_EQ(typeAtById(thread_, type, ID(__ne__)), *value); 59} 60 61TEST_F(TypeBuiltinsTest, TypeAtPutByStrInvalidatesCache) { 62 ASSERT_FALSE(runFromCStr(runtime_, R"( 63class A: 64 def foo(self): return 4 65 66def cache_a_foo(a): 67 return a.foo 68 69a = A() 70cache_a_foo(a) 71)") 72 .isError()); 73 HandleScope scope(thread_); 74 Function cache_a_foo(&scope, mainModuleAt(runtime_, "cache_a_foo")); 75 MutableTuple caches(&scope, cache_a_foo.caches()); 76 Object a(&scope, mainModuleAt(runtime_, "a")); 77 ASSERT_FALSE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 78 79 Type type_a(&scope, mainModuleAt(runtime_, "A")); 80 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 81 Object none(&scope, NoneType::object()); 82 typeAtPut(thread_, type_a, foo, none); 83 EXPECT_TRUE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 84} 85 86TEST_F(TypeBuiltinsTest, TypeAtPutByIdInvalidatesCache) { 87 ASSERT_FALSE(runFromCStr(runtime_, R"( 88class A: 89 def __eq__(self, other): return True 90 91def cache_a_eq(a): 92 return a.__eq__ 93 94a = A() 95cache_a_eq(a) 96)") 97 .isError()); 98 HandleScope scope(thread_); 99 Function cache_a_eq(&scope, mainModuleAt(runtime_, "cache_a_eq")); 100 MutableTuple caches(&scope, cache_a_eq.caches()); 101 Object a(&scope, mainModuleAt(runtime_, "a")); 102 ASSERT_FALSE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 103 104 Type type_a(&scope, mainModuleAt(runtime_, "A")); 105 Object none(&scope, NoneType::object()); 106 typeAtPutById(thread_, type_a, ID(__eq__), none); 107 EXPECT_TRUE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 108} 109 110TEST_F(TypeBuiltinsTest, TypeAtPutDoesNotGrowOnTombstones) { 111 ASSERT_FALSE(runFromCStr(runtime_, R"( 112class C: pass 113)") 114 .isError()); 115 HandleScope scope(thread_); 116 Type type(&scope, mainModuleAt(runtime_, "C")); 117 ASSERT_TRUE(type.attributes().isTuple()); 118 word initial_capacity = Tuple::cast(type.attributes()).length(); 119 // Insert and remove symbols to fill the dictionary with tombstones. 120 Object name(&scope, NoneType::object()); 121 for (word i = 0; i < static_cast<word>(SymbolId::kMaxId); i++) { 122 name = runtime_->symbols()->at(static_cast<SymbolId>(i)); 123 attributeValueCellAtPut(thread_, type, name); 124 typeRemove(thread_, type, name); 125 } 126 EXPECT_EQ(Tuple::cast(type.attributes()).length(), initial_capacity); 127} 128 129TEST_F(TypeBuiltinsTest, TypeRemoveForNonExistingEntryReturnsErrorNotFound) { 130 ASSERT_FALSE(runFromCStr(runtime_, R"( 131class A: 132 def __eq__(self, other): return True 133)") 134 .isError()); 135 HandleScope scope(thread_); 136 Type type(&scope, mainModuleAt(runtime_, "A")); 137 Str dunder_gt(&scope, runtime_->newStrFromCStr("__gt__")); 138 EXPECT_TRUE(typeRemove(thread_, type, dunder_gt).isErrorNotFound()); 139} 140 141TEST_F(TypeBuiltinsTest, TypeRemoveRemovesAssociatedEntry) { 142 ASSERT_FALSE(runFromCStr(runtime_, R"( 143class A: 144 def __eq__(self, other): return True 145)") 146 .isError()); 147 HandleScope scope(thread_); 148 Type type(&scope, mainModuleAt(runtime_, "A")); 149 Object dunder_eq(&scope, Runtime::internStrFromCStr(thread_, "__eq__")); 150 ASSERT_FALSE(typeAt(type, dunder_eq).isErrorNotFound()); 151 ASSERT_FALSE(typeRemove(thread_, type, dunder_eq).isErrorNotFound()); 152 EXPECT_TRUE(typeAt(type, dunder_eq).isErrorNotFound()); 153} 154 155TEST_F(TypeBuiltinsTest, TypeRemoveInvalidatesCache) { 156 ASSERT_FALSE(runFromCStr(runtime_, R"( 157class A: 158 def __eq__(self, other): return True 159 160def cache_a_eq(a): 161 return a.__eq__ 162 163a = A() 164cache_a_eq(a) 165)") 166 .isError()); 167 HandleScope scope(thread_); 168 Function cache_a_eq(&scope, mainModuleAt(runtime_, "cache_a_eq")); 169 MutableTuple caches(&scope, cache_a_eq.caches()); 170 Object a(&scope, mainModuleAt(runtime_, "a")); 171 ASSERT_FALSE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 172 173 Type type_a(&scope, mainModuleAt(runtime_, "A")); 174 Str dunder_eq(&scope, runtime_->newStrFromCStr("__eq__")); 175 ASSERT_FALSE(typeRemove(thread_, type_a, dunder_eq).isErrorNotFound()); 176 EXPECT_TRUE(icLookupAttr(*caches, 1, a.layoutId()).isErrorNotFound()); 177} 178 179TEST_F(TypeBuiltinsTest, TypeKeysFiltersOutPlaceholders) { 180 HandleScope scope(thread_); 181 Type type(&scope, runtime_->newType()); 182 183 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 184 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 185 Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); 186 Str value(&scope, runtime_->newStrFromCStr("value")); 187 188 typeAtPut(thread_, type, foo, value); 189 typeAtPut(thread_, type, bar, value); 190 typeAtPut(thread_, type, baz, value); 191 192 ValueCell::cast(typeValueCellAt(*type, *bar)).makePlaceholder(); 193 194 List keys(&scope, typeKeys(thread_, type)); 195 EXPECT_EQ(keys.numItems(), 2); 196 EXPECT_EQ(keys.at(0), *foo); 197 EXPECT_EQ(keys.at(1), *baz); 198} 199 200TEST_F(TypeBuiltinsTest, TypeLenReturnsItemCountExcludingPlaceholders) { 201 HandleScope scope(thread_); 202 Type type(&scope, runtime_->newType()); 203 204 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 205 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 206 Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); 207 Str value(&scope, runtime_->newStrFromCStr("value")); 208 209 typeAtPut(thread_, type, foo, value); 210 typeAtPut(thread_, type, bar, value); 211 typeAtPut(thread_, type, baz, value); 212 213 word previous_len = typeLen(thread_, type); 214 215 ValueCell::cast(typeValueCellAt(*type, *bar)).makePlaceholder(); 216 217 word after_len = typeLen(thread_, type); 218 EXPECT_EQ(previous_len, after_len + 1); 219} 220 221TEST_F(TypeBuiltinsTest, TypeValuesFiltersOutPlaceholders) { 222 HandleScope scope(thread_); 223 Type type(&scope, runtime_->newType()); 224 225 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 226 Object foo_value(&scope, runtime_->newStrFromCStr("foo_value")); 227 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 228 Object bar_value(&scope, runtime_->newStrFromCStr("bar_value")); 229 Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); 230 Object baz_value(&scope, runtime_->newStrFromCStr("baz_value")); 231 232 typeAtPut(thread_, type, foo, foo_value); 233 typeAtPut(thread_, type, bar, bar_value); 234 typeAtPut(thread_, type, baz, baz_value); 235 236 ValueCell::cast(typeValueCellAt(*type, *bar)).makePlaceholder(); 237 238 List values(&scope, typeValues(thread_, type)); 239 EXPECT_TRUE(listContains(values, foo_value)); 240 EXPECT_FALSE(listContains(values, bar_value)); 241 EXPECT_TRUE(listContains(values, baz_value)); 242} 243 244TEST_F(TypeBuiltinsTest, DunderBasesReturnsTuple) { 245 HandleScope scope(thread_); 246 ASSERT_FALSE(runFromCStr(runtime_, R"( 247class A: pass 248class B: pass 249class C(A, B): pass 250)") 251 .isError()); 252 Object a(&scope, mainModuleAt(runtime_, "A")); 253 Object b(&scope, mainModuleAt(runtime_, "B")); 254 Object c(&scope, mainModuleAt(runtime_, "C")); 255 Object result_obj(&scope, 256 runtime_->attributeAtById(thread_, c, ID(__bases__))); 257 ASSERT_TRUE(result_obj.isTuple()); 258 Tuple result(&scope, *result_obj); 259 ASSERT_EQ(result.length(), 2); 260 EXPECT_EQ(result.at(0), a); 261 EXPECT_EQ(result.at(1), b); 262} 263 264TEST_F(TypeBuiltinsTest, DunderBasesOnObjectReturnsEmptyTuple) { 265 HandleScope scope(thread_); 266 Object type(&scope, runtime_->typeAt(LayoutId::kObject)); 267 Object result_obj(&scope, 268 runtime_->attributeAtById(thread_, type, ID(__bases__))); 269 ASSERT_TRUE(result_obj.isTuple()); 270 EXPECT_EQ(Tuple::cast(*result_obj).length(), 0); 271} 272 273TEST_F(TypeBuiltinsTest, DunderBasesOnBuiltinTypeReturnsTuple) { 274 HandleScope scope(thread_); 275 Object type(&scope, runtime_->typeAt(LayoutId::kInt)); 276 Object result_obj(&scope, 277 runtime_->attributeAtById(thread_, type, ID(__bases__))); 278 ASSERT_TRUE(result_obj.isTuple()); 279 Tuple result(&scope, *result_obj); 280 ASSERT_EQ(result.length(), 1); 281 EXPECT_EQ(result.at(0), runtime_->typeAt(LayoutId::kObject)); 282} 283 284TEST_F(TypeBuiltinsTest, DunderCallType) { 285 HandleScope scope(thread_); 286 287 ASSERT_FALSE(runFromCStr(runtime_, R"( 288class C: pass 289c = C() 290)") 291 .isError()); 292 293 Type type(&scope, mainModuleAt(runtime_, "C")); 294 ASSERT_FALSE(type.isError()); 295 Object instance(&scope, mainModuleAt(runtime_, "c")); 296 ASSERT_FALSE(instance.isError()); 297 Object instance_type(&scope, runtime_->typeOf(*instance)); 298 ASSERT_FALSE(instance_type.isError()); 299 300 EXPECT_EQ(*type, *instance_type); 301} 302 303TEST_F(TypeBuiltinsTest, DunderCallTypeWithInit) { 304 HandleScope scope(thread_); 305 306 ASSERT_FALSE(runFromCStr(runtime_, R"( 307class C: 308 def __init__(self): 309 global g 310 g = 2 311 312g = 1 313C() 314)") 315 .isError()); 316 317 Object global(&scope, mainModuleAt(runtime_, "g")); 318 ASSERT_FALSE(global.isError()); 319 EXPECT_TRUE(isIntEqualsWord(*global, 2)); 320} 321 322TEST_F(TypeBuiltinsTest, DunderCallTypeWithInitAndArgs) { 323 HandleScope scope(thread_); 324 325 ASSERT_FALSE(runFromCStr(runtime_, R"( 326class C: 327 def __init__(self, x): 328 global g 329 g = x 330 331g = 1 332C(9) 333)") 334 .isError()); 335 336 Object global(&scope, mainModuleAt(runtime_, "g")); 337 ASSERT_FALSE(global.isError()); 338 EXPECT_TRUE(isIntEqualsWord(*global, 9)); 339} 340 341TEST_F(TypeBuiltinsTest, 342 DunderCallWithNonTypeDudnerNewResultReturnsWithoutCallingDunderInit) { 343 HandleScope scope(thread_); 344 ASSERT_FALSE(runFromCStr(runtime_, R"( 345class C: 346 def __new__(self, *args): 347 return 17 348 def __init__(self, *args): 349 raise Exception("should not happen") 350result = type.__call__(C, "C", (), {}) 351)") 352 .isError()); 353 Object result(&scope, mainModuleAt(runtime_, "result")); 354 EXPECT_TRUE(isIntEqualsWord(*result, 17)); 355} 356 357TEST_F(TypeBuiltinsTest, DunderDirReturnsList) { 358 HandleScope scope(thread_); 359 ASSERT_FALSE(runFromCStr(runtime_, R"( 360class A: 361 x = 42 362 def foo(): pass 363class B(A): 364 def bar(): pass 365dir = type.__dir__(B) 366)") 367 .isError()); 368 Object dir(&scope, mainModuleAt(runtime_, "dir")); 369 Object x(&scope, Runtime::internStrFromCStr(thread_, "x")); 370 EXPECT_TRUE(listContains(dir, x)); 371 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 372 EXPECT_TRUE(listContains(dir, foo)); 373 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 374 EXPECT_TRUE(listContains(dir, bar)); 375} 376 377TEST_F(TypeBuiltinsTest, DunderDocOnEmptyTypeReturnsNone) { 378 HandleScope scope(thread_); 379 ASSERT_FALSE(runFromCStr(runtime_, "class C: pass").isError()); 380 Object c(&scope, mainModuleAt(runtime_, "C")); 381 Object doc(&scope, runtime_->attributeAtById(thread_, c, ID(__doc__))); 382 EXPECT_EQ(doc, NoneType::object()); 383} 384 385TEST_F(TypeBuiltinsTest, DunderDocReturnsDocumentationString) { 386 HandleScope scope(thread_); 387 ASSERT_FALSE(runFromCStr(runtime_, R"( 388class C: 389 """hello documentation""" 390 pass 391)") 392 .isError()); 393 Object c(&scope, mainModuleAt(runtime_, "C")); 394 Object doc(&scope, runtime_->attributeAtById(thread_, c, ID(__doc__))); 395 EXPECT_TRUE(isStrEqualsCStr(*doc, "hello documentation")); 396} 397 398TEST_F(TypeBuiltinsTest, DunderGetattributeReturnsAttribute) { 399 HandleScope scope(thread_); 400 ASSERT_FALSE(runFromCStr(runtime_, R"( 401class C: 402 foo = -13 403)") 404 .isError()); 405 Object c(&scope, mainModuleAt(runtime_, "C")); 406 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 407 EXPECT_TRUE( 408 isIntEqualsWord(runBuiltin(METH(type, __getattribute__), c, name), -13)); 409} 410 411TEST_F(TypeBuiltinsTest, DunderGetattributeWithNonStringNameRaisesTypeError) { 412 HandleScope scope(thread_); 413 ASSERT_FALSE(runFromCStr(runtime_, R"( 414class C: 415 pass 416)") 417 .isError()); 418 Object c(&scope, mainModuleAt(runtime_, "C")); 419 Object name(&scope, runtime_->newInt(0)); 420 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(type, __getattribute__), c, name), 421 LayoutId::kTypeError, 422 "attribute name must be string, not 'int'")); 423} 424 425TEST_F(TypeBuiltinsTest, 426 DunderGetattributeWithMissingAttributeRaisesAttributeError) { 427 HandleScope scope(thread_); 428 ASSERT_FALSE(runFromCStr(runtime_, R"( 429class C: 430 pass 431)") 432 .isError()); 433 Object c(&scope, mainModuleAt(runtime_, "C")); 434 Object name(&scope, Runtime::internStrFromCStr(thread_, "xxx")); 435 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(type, __getattribute__), c, name), 436 LayoutId::kAttributeError, 437 "type object 'C' has no attribute 'xxx'")); 438} 439 440TEST_F(TypeBuiltinsTest, DunderReprForBuiltinReturnsStr) { 441 ASSERT_FALSE( 442 runFromCStr(runtime_, "result = type.__repr__(object)").isError()); 443 EXPECT_TRUE( 444 isStrEqualsCStr(mainModuleAt(runtime_, "result"), "<class 'object'>")); 445} 446 447TEST_F(TypeBuiltinsTest, DunderReprForUserDefinedTypeReturnsStr) { 448 ASSERT_FALSE(runFromCStr(runtime_, R"( 449class Foo: 450 pass 451result = type.__repr__(Foo) 452)") 453 .isError()); 454 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), 455 "<class '__main__.Foo'>")); 456} 457 458TEST_F(TypeBuiltinsTest, DunderNewWithOneArgReturnsTypeOfArg) { 459 HandleScope scope(thread_); 460 ASSERT_FALSE(runFromCStr(runtime_, R"( 461a = type.__new__(type, 1); 462b = type.__new__(type, "hello"); 463)") 464 .isError()); 465 Type a(&scope, mainModuleAt(runtime_, "a")); 466 Type b(&scope, mainModuleAt(runtime_, "b")); 467 468 EXPECT_EQ(a.instanceLayoutId(), LayoutId::kInt); 469 EXPECT_EQ(b.instanceLayoutId(), LayoutId::kStr); 470} 471 472TEST_F(TypeBuiltinsTest, DunderNewWithOneMetaclassArgReturnsType) { 473 HandleScope scope(thread_); 474 ASSERT_FALSE(runFromCStr(runtime_, R"( 475class Foo(type): 476 pass 477a = type.__new__(type, Foo); 478)") 479 .isError()); 480 Type a(&scope, mainModuleAt(runtime_, "a")); 481 EXPECT_EQ(a.instanceLayoutId(), LayoutId::kType); 482} 483 484TEST_F(TypeBuiltinsTest, DunderSetattrSetsAttribute) { 485 HandleScope scope(thread_); 486 ASSERT_FALSE(runFromCStr(runtime_, "class C: pass").isError()); 487 Object c_obj(&scope, mainModuleAt(runtime_, "C")); 488 ASSERT_TRUE(c_obj.isType()); 489 Type c(&scope, *c_obj); 490 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 491 Object value(&scope, runtime_->newInt(-7331)); 492 EXPECT_TRUE(runBuiltin(METH(type, __setattr__), c, name, value).isNoneType()); 493 EXPECT_TRUE(isIntEqualsWord(typeAt(c, name), -7331)); 494} 495 496TEST_F(TypeBuiltinsTest, DunderSetattrWithNonStrNameRaisesTypeError) { 497 HandleScope scope(thread_); 498 ASSERT_FALSE(runFromCStr(runtime_, "class C: pass").isError()); 499 Object c_obj(&scope, mainModuleAt(runtime_, "C")); 500 ASSERT_TRUE(c_obj.isType()); 501 Type c(&scope, *c_obj); 502 Object name(&scope, NoneType::object()); 503 Object value(&scope, runtime_->newInt(1)); 504 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(type, __setattr__), c, name, value), 505 LayoutId::kTypeError, 506 "attribute name must be string, not 'NoneType'")); 507} 508 509TEST_F(TypeBuiltinsTest, DunderSlotsCreatesLayoutWithInObjectAttributes) { 510 ASSERT_FALSE(runFromCStr(runtime_, R"( 511class C: 512 __slots__ = "x", "y", "z" 513)") 514 .isError()); 515 HandleScope scope(thread_); 516 Type c(&scope, mainModuleAt(runtime_, "C")); 517 EXPECT_TRUE(c.hasFlag(Type::Flag::kHasSlots)); 518 519 Layout layout(&scope, c.instanceLayout()); 520 EXPECT_TRUE(layout.isSealed()); 521 522 Tuple attributes(&scope, layout.inObjectAttributes()); 523 ASSERT_EQ(attributes.length(), 3); 524 525 Tuple elt0(&scope, attributes.at(0)); 526 EXPECT_TRUE(isStrEqualsCStr(elt0.at(0), "x")); 527 AttributeInfo info0(elt0.at(1)); 528 EXPECT_TRUE(info0.isInObject()); 529 EXPECT_TRUE(info0.isFixedOffset()); 530 531 Tuple elt1(&scope, attributes.at(1)); 532 EXPECT_TRUE(isStrEqualsCStr(elt1.at(0), "y")); 533 AttributeInfo info1(elt1.at(1)); 534 EXPECT_TRUE(info1.isInObject()); 535 EXPECT_TRUE(info1.isFixedOffset()); 536 537 Tuple elt2(&scope, attributes.at(2)); 538 EXPECT_TRUE(isStrEqualsCStr(elt2.at(0), "z")); 539 AttributeInfo info2(elt2.at(1)); 540 EXPECT_TRUE(info2.isInObject()); 541 EXPECT_TRUE(info2.isFixedOffset()); 542} 543 544TEST_F(TypeBuiltinsTest, DunderSlotsWithEmptyTupleCreatesEmptyLayout) { 545 ASSERT_FALSE(runFromCStr(runtime_, R"( 546class C: 547 __slots__ = () 548)") 549 .isError()); 550 HandleScope scope(thread_); 551 Type c(&scope, mainModuleAt(runtime_, "C")); 552 EXPECT_FALSE(c.hasFlag(Type::Flag::kHasSlots)); 553 554 Layout layout(&scope, c.instanceLayout()); 555 EXPECT_TRUE(layout.isSealed()); 556 557 Tuple attributes(&scope, layout.inObjectAttributes()); 558 ASSERT_EQ(attributes.length(), 0); 559} 560 561TEST_F(TypeBuiltinsTest, DunderSlotsAreInheritedFromLayoutBase) { 562 ASSERT_FALSE(runFromCStr(runtime_, R"( 563class C: 564 pass 565 566class D(C): 567 __slots__ = "x", "y" 568 569class E(D, C): 570 __slots__ = "z" 571)") 572 .isError()); 573 HandleScope scope(thread_); 574 Type e(&scope, mainModuleAt(runtime_, "E")); 575 Layout layout(&scope, e.instanceLayout()); 576 // The layout of E is not sealed due to C. 577 EXPECT_FALSE(layout.isSealed()); 578 Tuple attributes(&scope, layout.inObjectAttributes()); 579 // D is chosen as the layout base for E since D is a subtype of C. 580 ASSERT_EQ(attributes.length(), 3); 581 582 Tuple elt0(&scope, attributes.at(0)); 583 EXPECT_TRUE(isStrEqualsCStr(elt0.at(0), "x")); 584 AttributeInfo info0(elt0.at(1)); 585 EXPECT_TRUE(info0.isInObject()); 586 EXPECT_TRUE(info0.isFixedOffset()); 587 588 Tuple elt1(&scope, attributes.at(1)); 589 EXPECT_TRUE(isStrEqualsCStr(elt1.at(0), "y")); 590 AttributeInfo info1(elt1.at(1)); 591 EXPECT_TRUE(info1.isInObject()); 592 EXPECT_TRUE(info1.isFixedOffset()); 593 594 Tuple elt2(&scope, attributes.at(2)); 595 EXPECT_TRUE(isStrEqualsCStr(elt2.at(0), "z")); 596 AttributeInfo info2(elt2.at(1)); 597 EXPECT_TRUE(info2.isInObject()); 598 EXPECT_TRUE(info2.isFixedOffset()); 599} 600 601TEST_F(TypeBuiltinsTest, DunderSlotsSealsTypeWhenAllBasesAreSealed) { 602 ASSERT_FALSE(runFromCStr(runtime_, R"( 603class C: 604 __slots__ = () 605 606class D: 607 __slots__ = () 608 609class E(C, D): 610 __slots__ = "x" 611)") 612 .isError()); 613 HandleScope scope(thread_); 614 Type e(&scope, mainModuleAt(runtime_, "E")); 615 Layout layout(&scope, e.instanceLayout()); 616 EXPECT_TRUE(layout.isSealed()); 617} 618 619TEST_F(TypeBuiltinsTest, DunderSlotsDoesNotSealTypeWhenBaseHasDunderDict) { 620 ASSERT_FALSE(runFromCStr(runtime_, R"( 621class C: 622 pass 623 624class D: 625 __slots__ = () 626 627class E(C, D): 628 __slots__ = "x" 629)") 630 .isError()); 631 HandleScope scope(thread_); 632 Type c(&scope, mainModuleAt(runtime_, "C")); 633 ASSERT_FALSE(Layout::cast(c.instanceLayout()).isSealed()); 634 635 Type e(&scope, mainModuleAt(runtime_, "E")); 636 Layout layout(&scope, e.instanceLayout()); 637 EXPECT_FALSE(layout.isSealed()); 638} 639 640TEST_F(TypeBuiltinsTest, 641 DunderSlotsWithNonObjectBuiltinBaseAddsInObjectAttributes) { 642 ASSERT_FALSE(runFromCStr(runtime_, R"( 643class C(dict): 644 __slots__ = "x" 645)") 646 .isError()); 647 HandleScope scope(thread_); 648 Layout dict_layout(&scope, runtime_->layoutAt(LayoutId::kDict)); 649 ASSERT_TRUE(dict_layout.isSealed()); 650 Tuple dict_attributes(&scope, dict_layout.inObjectAttributes()); 651 ASSERT_EQ(dict_attributes.length(), 4); 652 Tuple dict_elt3(&scope, dict_attributes.at(3)); 653 AttributeInfo dict_elt3_info(dict_elt3.at(1)); 654 EXPECT_TRUE(dict_elt3_info.isInObject()); 655 EXPECT_TRUE(dict_elt3_info.isFixedOffset()); 656 657 Type c(&scope, mainModuleAt(runtime_, "C")); 658 Layout layout(&scope, c.instanceLayout()); 659 // C's layout is sealed since it has only a sealed base. 660 EXPECT_TRUE(layout.isSealed()); 661 Tuple attributes(&scope, layout.inObjectAttributes()); 662 ASSERT_EQ(attributes.length(), 5); 663 664 Tuple elt0(&scope, attributes.at(4)); 665 EXPECT_TRUE(isStrEqualsCStr(elt0.at(0), "x")); 666 AttributeInfo info0(elt0.at(1)); 667 EXPECT_TRUE(info0.isInObject()); 668 EXPECT_TRUE(info0.isFixedOffset()); 669 EXPECT_EQ(info0.offset(), dict_elt3_info.offset() + kPointerSize); 670} 671 672TEST_F(TypeBuiltinsTest, 673 DunderSlotsWithConflictingLayoutBasesOfUserTypeRaisesTypeError) { 674 ASSERT_FALSE(runFromCStr(runtime_, R"( 675class C: 676 __slots__ = "x" 677 678class D: 679 __slots__ = "y" 680)") 681 .isError()); 682 ASSERT_TRUE(raisedWithStr(runFromCStr(runtime_, "class E(C, D): pass"), 683 LayoutId::kTypeError, 684 "multiple bases have instance lay-out conflict")); 685} 686 687TEST_F(TypeBuiltinsTest, 688 DunderSlotsWithConflictingLayoutBasesOfBuiltinTypeRaisesTypeError) { 689 // Confliction between a builtin type and a user-defined type. 690 ASSERT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 691class C: 692 __slots__ = "x" # This is conflicting with dict's in-object attributes. 693 694class D(C, dict): 695 pass 696)"), 697 LayoutId::kTypeError, 698 "multiple bases have instance lay-out conflict")); 699} 700 701TEST_F(TypeBuiltinsTest, 702 DunderSlotsWithEmptyTupleDoesNotConflictWithOtherDunderSlots) { 703 ASSERT_FALSE(runFromCStr(runtime_, R"( 704class C: 705 __slots__ = () 706 707class D: 708 __slots__ = "x" 709 710class E(C, D): 711 pass 712)") 713 .isError()); 714 HandleScope scope(thread_); 715 Type e(&scope, mainModuleAt(runtime_, "E")); 716 Layout layout(&scope, e.instanceLayout()); 717 Tuple attributes(&scope, layout.inObjectAttributes()); 718 ASSERT_EQ(attributes.length(), 1); 719 720 Tuple elt0(&scope, attributes.at(0)); 721 EXPECT_TRUE(isStrEqualsCStr(elt0.at(0), "x")); 722 AttributeInfo info0(elt0.at(1)); 723 EXPECT_TRUE(info0.isInObject()); 724 EXPECT_TRUE(info0.isFixedOffset()); 725} 726 727TEST_F(TypeBuiltinsTest, DunderSlotsSharingSameLayoutBaseCanServceAsBases) { 728 // Although F's bases, D, E do not appear in the same type hierarchy 729 // (neither D is a subtype of E nor E is a subtype of D), but 730 // D's layout base (C) is the supertype of E, which makes the type checking 731 // succeed. 732 ASSERT_FALSE(runFromCStr(runtime_, R"( 733class C: 734 __slots__ = "x" 735 736class D(C): 737 pass 738 739class E(C): 740 __slots__ = "y" 741 742class F(D, E): 743 pass 744)") 745 .isError()); 746 HandleScope scope(thread_); 747 Type f(&scope, mainModuleAt(runtime_, "F")); 748 Layout layout(&scope, f.instanceLayout()); 749 Tuple attributes(&scope, layout.inObjectAttributes()); 750 ASSERT_EQ(attributes.length(), 2); 751 752 Tuple elt0(&scope, attributes.at(0)); 753 EXPECT_TRUE(isStrEqualsCStr(elt0.at(0), "x")); 754 AttributeInfo info0(elt0.at(1)); 755 EXPECT_TRUE(info0.isInObject()); 756 EXPECT_TRUE(info0.isFixedOffset()); 757 758 Tuple elt1(&scope, attributes.at(1)); 759 EXPECT_TRUE(isStrEqualsCStr(elt1.at(0), "y")); 760 AttributeInfo info1(elt1.at(1)); 761 EXPECT_TRUE(info1.isInObject()); 762 EXPECT_TRUE(info1.isFixedOffset()); 763} 764 765TEST_F(TypeBuiltinsTest, DunderSlotsPopulatesSlotDescriptorsWithCorrectValues) { 766 ASSERT_FALSE(runFromCStr(runtime_, R"( 767class C: 768 __slots__ = "x" 769 770class D(C): 771 __slots__ = "y" 772)") 773 .isError()); 774 HandleScope scope(thread_); 775 Type c(&scope, mainModuleAt(runtime_, "C")); 776 Layout c_layout(&scope, c.instanceLayout()); 777 // Checking descriptor for "x" in C. 778 { 779 Str x(&scope, runtime_->newStrFromCStr("x")); 780 SlotDescriptor descriptor_x(&scope, typeAt(c, x)); 781 EXPECT_EQ(descriptor_x.type(), *c); 782 EXPECT_TRUE(isStrEqualsCStr(descriptor_x.name(), "x")); 783 AttributeInfo info; 784 ASSERT_TRUE(Runtime::layoutFindAttribute(*c_layout, x, &info)); 785 EXPECT_EQ(descriptor_x.offset(), info.offset()); 786 } 787 788 Type d(&scope, mainModuleAt(runtime_, "D")); 789 Layout d_layout(&scope, d.instanceLayout()); 790 // Checking descriptors for "x" and "y" in D. 791 { 792 // "x" is inherited from C to D. 793 Str x(&scope, runtime_->newStrFromCStr("x")); 794 ASSERT_TRUE(typeAt(d, x).isErrorNotFound()); 795 SlotDescriptor descriptor_x(&scope, typeLookupInMro(thread_, *d, *x)); 796 EXPECT_EQ(descriptor_x.type(), *c); 797 EXPECT_TRUE(isStrEqualsCStr(descriptor_x.name(), "x")); 798 AttributeInfo info; 799 ASSERT_TRUE(Runtime::layoutFindAttribute(*d_layout, x, &info)); 800 EXPECT_EQ(descriptor_x.offset(), info.offset()); 801 802 // "y" is populated in D itself. 803 Str y(&scope, runtime_->newStrFromCStr("y")); 804 SlotDescriptor descriptor_y(&scope, typeAt(d, y)); 805 EXPECT_EQ(descriptor_y.type(), *d); 806 EXPECT_TRUE(isStrEqualsCStr(descriptor_y.name(), "y")); 807 ASSERT_TRUE(Runtime::layoutFindAttribute(*d_layout, y, &info)); 808 EXPECT_EQ(descriptor_y.offset(), info.offset()); 809 } 810} 811 812static RawObject newExtensionType(PyObject* extension_type) { 813 Thread* thread = Thread::current(); 814 Runtime* runtime = thread->runtime(); 815 HandleScope scope(thread); 816 817 Str name(&scope, runtime->newStrFromCStr("ExtType")); 818 Object object_type(&scope, runtime->typeAt(LayoutId::kObject)); 819 Tuple bases(&scope, runtime->newTupleWith1(object_type)); 820 Dict dict(&scope, runtime->newDict()); 821 Type metaclass(&scope, runtime->typeAt(LayoutId::kType)); 822 Type type(&scope, 823 typeNew(thread, metaclass, name, bases, dict, 824 Type::Flag::kHasNativeData | Type::Flag::kIsBasetype, 825 /*inherit_slots=*/false, 826 /*add_instance_dict=*/false)); 827 828 extension_type->reference_ = type.raw(); 829 return *type; 830} 831 832TEST_F(TypeBuiltinsTest, 833 DunderSlotsWithExtensionTypeAsBaseAllocatesExtraSpace) { 834 // Create a main module. 835 ASSERT_FALSE(runFromCStr(runtime_, "").isError()); 836 HandleScope scope(thread_); 837 PyObject extension_type; 838 Type type(&scope, newExtensionType(&extension_type)); 839 ASSERT_TRUE(type.hasFlag(Type::Flag::kHasNativeData)); 840 841 Module main_module(&scope, findMainModule(runtime_)); 842 Str type_name(&scope, runtime_->newStrFromCStr("ExtType")); 843 moduleAtPut(thread_, main_module, type_name, type); 844 845 ASSERT_FALSE(runFromCStr(runtime_, R"( 846class C(ExtType): 847 __slots__ = "x", "y" 848)") 849 .isError()); 850 Type c(&scope, mainModuleAt(runtime_, "C")); 851 ASSERT_TRUE(c.hasFlag(Type::Flag::kHasNativeData)); 852 853 Layout layout(&scope, c.instanceLayout()); 854 Tuple attributes(&scope, layout.inObjectAttributes()); 855 // "x" and "y" are added as a regular attribute. 856 ASSERT_EQ(attributes.length(), 2); 857 // However, more speace was allocated to be a native proxy. 858 EXPECT_EQ(layout.instanceSize(), 859 2 * kPointerSize + NativeProxy::kSizeFromEnd); 860 861 Tuple elt0(&scope, attributes.at(0)); 862 EXPECT_TRUE(isStrEqualsCStr(elt0.at(0), "x")); 863 AttributeInfo info0(elt0.at(1)); 864 EXPECT_TRUE(info0.isInObject()); 865 EXPECT_TRUE(info0.isFixedOffset()); 866 867 Tuple elt1(&scope, attributes.at(1)); 868 EXPECT_TRUE(isStrEqualsCStr(elt1.at(0), "y")); 869 AttributeInfo info1(elt1.at(1)); 870 EXPECT_TRUE(info1.isInObject()); 871 EXPECT_TRUE(info1.isFixedOffset()); 872} 873 874TEST_F(TypeBuiltinsTest, TypeHasDunderMroAttribute) { 875 HandleScope scope(thread_); 876 ASSERT_FALSE( 877 runFromCStr(runtime_, "result = str.__class__.__mro__").isError()); 878 Object result(&scope, mainModuleAt(runtime_, "result")); 879 ASSERT_TRUE(result.isTuple()); 880} 881 882TEST_F(TypeBuiltinsTest, TypeHasDunderNameAttribute) { 883 HandleScope scope(thread_); 884 ASSERT_FALSE( 885 runFromCStr(runtime_, "result = str.__class__.__name__").isError()); 886 Object result(&scope, mainModuleAt(runtime_, "result")); 887 EXPECT_TRUE(isStrEqualsCStr(*result, "type")); 888} 889 890TEST_F(TypeBuiltinsTest, TypeHasDunderDictAttribute) { 891 HandleScope scope(thread_); 892 ASSERT_FALSE( 893 runFromCStr(runtime_, "result = str.__class__.__dict__").isError()); 894 Object result(&scope, mainModuleAt(runtime_, "result")); 895 EXPECT_TRUE(result.isMappingProxy()); 896} 897 898TEST_F(TypeBuiltinsTest, TypeLookupNameInMroReturnsValue) { 899 HandleScope scope(thread_); 900 ASSERT_FALSE(runFromCStr(runtime_, R"( 901class A: 902 foo = 2 903)") 904 .isError()); 905 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 906 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 907 Type a(&scope, *a_obj); 908 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 909 EXPECT_TRUE(isIntEqualsWord(typeLookupInMro(thread_, *a, *foo), 2)); 910} 911 912TEST_F(TypeBuiltinsTest, TypeLookupNameInMroReturnsParentValue) { 913 HandleScope scope(thread_); 914 ASSERT_FALSE(runFromCStr(runtime_, R"( 915class A: 916 foo = 2 917class B(A): 918 bar = 4 919)") 920 .isError()); 921 Object b_obj(&scope, mainModuleAt(runtime_, "B")); 922 ASSERT_TRUE(b_obj.isType()); 923 Type b(&scope, *b_obj); 924 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 925 EXPECT_TRUE(isIntEqualsWord(typeLookupInMro(thread_, *b, *name), 2)); 926} 927 928TEST_F(TypeBuiltinsTest, TypeLookupNameInMroReturnsOverriddenValue) { 929 HandleScope scope(thread_); 930 ASSERT_FALSE(runFromCStr(runtime_, R"( 931class A: 932 foo = 2 933class B(A): 934 foo = 4 935)") 936 .isError()); 937 Object b_obj(&scope, mainModuleAt(runtime_, "B")); 938 ASSERT_TRUE(b_obj.isType()); 939 Type b(&scope, *b_obj); 940 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 941 EXPECT_TRUE(isIntEqualsWord(typeLookupInMro(thread_, *b, *name), 4)); 942} 943 944TEST_F(TypeBuiltinsTest, TypeLookupNameInMroWithNonExistentNameReturnsError) { 945 HandleScope scope(thread_); 946 ASSERT_FALSE(runFromCStr(runtime_, R"( 947class A: 948 bar = 2 949)") 950 .isError()); 951 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 952 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 953 Type a(&scope, *a_obj); 954 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 955 EXPECT_TRUE(typeLookupInMro(thread_, *a, *name).isError()); 956 EXPECT_FALSE(thread_->hasPendingException()); 957} 958 959TEST_F(TypeBuiltinsTest, TypeLookupSymbolInMroReturnsValue) { 960 HandleScope scope(thread_); 961 ASSERT_FALSE(runFromCStr(runtime_, R"( 962class A: 963 __add__ = 3 964)") 965 .isError()); 966 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 967 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 968 Type a(&scope, *a_obj); 969 EXPECT_TRUE( 970 isIntEqualsWord(typeLookupInMroById(thread_, *a, ID(__add__)), 3)); 971} 972 973TEST_F(TypeBuiltinsTest, DunderCallReceivesExArgs) { 974 ASSERT_FALSE(runFromCStr(runtime_, R"( 975class C: 976 def __init__(self, *args): 977 self.args = args 978 979 def num_args(self): 980 return len(self.args) 981 982result = C(*(1,2,3)).num_args() 983)") 984 .isError()); 985 HandleScope scope(thread_); 986 Object result(&scope, mainModuleAt(runtime_, "result")); 987 EXPECT_EQ(*result, RawSmallInt::fromWord(3)); 988} 989 990TEST_F(TypeBuiltinsTest, TypeNewWithNonStrKeyInDictRaisesTypeError) { 991 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 992ty = type.__new__(type, *("foo", (object,), {4: 1})) 993name = ty.__name__N 994)"), 995 LayoutId::kTypeError, 996 "attribute name must be string, not 'int'")); 997} 998 999TEST_F(TypeBuiltinsTest, ClassMethodDunderCallReceivesExArgs) { 1000 ASSERT_FALSE(runFromCStr(runtime_, R"( 1001class Foo: 1002 @classmethod 1003 def foo(cls, *args): 1004 return len(args) 1005 1006result = Foo.foo(*(1,2,3)) 1007)") 1008 .isError()); 1009 HandleScope scope(thread_); 1010 Object result(&scope, mainModuleAt(runtime_, "result")); 1011 EXPECT_EQ(*result, RawSmallInt::fromWord(3)); 1012} 1013 1014TEST_F(TypeBuiltinsTest, TypeNewReceivesExArgs) { 1015 ASSERT_FALSE(runFromCStr(runtime_, R"( 1016ty = type.__new__(type, *("foo", (object,), {'a': 1})) 1017name = ty.__name__ 1018)") 1019 .isError()); 1020 HandleScope scope(thread_); 1021 Object name(&scope, mainModuleAt(runtime_, "name")); 1022 EXPECT_TRUE(isStrEqualsCStr(*name, "foo")); 1023} 1024 1025TEST_F(TypeBuiltinsTest, TypeCallWithInitReturningNonNoneRaisesTypeError) { 1026 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 1027class C: 1028 def __init__(self, *args, **kwargs): 1029 return 5 1030C() 1031)"), 1032 LayoutId::kTypeError, 1033 "C.__init__ returned non None")); 1034} 1035 1036TEST_F(TypeBuiltinsTest, TypeGetAttributeReturnsAttributeValue) { 1037 HandleScope scope(thread_); 1038 ASSERT_FALSE(runFromCStr(runtime_, R"( 1039class C: 1040 x = 42 1041)") 1042 .isError()); 1043 Object c_obj(&scope, mainModuleAt(runtime_, "C")); 1044 ASSERT_TRUE(runtime_->isInstanceOfType(*c_obj)); 1045 Type c(&scope, *c_obj); 1046 Object name(&scope, Runtime::internStrFromCStr(thread_, "x")); 1047 EXPECT_TRUE(isIntEqualsWord(typeGetAttribute(thread_, c, name), 42)); 1048} 1049 1050TEST_F(TypeBuiltinsTest, TypeGetAttributeReturnsMetaclassAttributeValue) { 1051 HandleScope scope(thread_); 1052 ASSERT_FALSE(runFromCStr(runtime_, R"( 1053class M(type): 1054 x = 77 1055class C(metaclass=M): pass 1056)") 1057 .isError()); 1058 Object c_obj(&scope, mainModuleAt(runtime_, "C")); 1059 ASSERT_TRUE(runtime_->isInstanceOfType(*c_obj)); 1060 Type c(&scope, *c_obj); 1061 Object name(&scope, Runtime::internStrFromCStr(thread_, "x")); 1062 EXPECT_TRUE(isIntEqualsWord(typeGetAttribute(thread_, c, name), 77)); 1063} 1064 1065TEST_F(TypeBuiltinsTest, TypeGetAttributeWithMissingAttributeReturnsError) { 1066 HandleScope scope(thread_); 1067 ASSERT_FALSE(runFromCStr(runtime_, "class C: pass").isError()); 1068 Object c_obj(&scope, mainModuleAt(runtime_, "C")); 1069 ASSERT_TRUE(runtime_->isInstanceOfType(*c_obj)); 1070 Type c(&scope, *c_obj); 1071 Object name(&scope, Runtime::internStrFromCStr(thread_, "xxx")); 1072 EXPECT_TRUE(typeGetAttribute(thread_, c, name).isError()); 1073 EXPECT_FALSE(thread_->hasPendingException()); 1074} 1075 1076TEST_F(TypeBuiltinsTest, TypeGetAttributeCallsDunderGetOnDataDescriptor) { 1077 HandleScope scope(thread_); 1078 ASSERT_FALSE(runFromCStr(runtime_, R"( 1079class D: 1080 def __set__(self, instance, value): pass 1081 def __get__(self, instance, owner): return (self, instance, owner) 1082class M(type): 1083 foo = D() 1084class A(metaclass=M): pass 1085)") 1086 .isError()); 1087 Object d_obj(&scope, mainModuleAt(runtime_, "D")); 1088 ASSERT_TRUE(d_obj.isType()); 1089 Type d(&scope, *d_obj); 1090 Object m(&scope, mainModuleAt(runtime_, "M")); 1091 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1092 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1093 Type a(&scope, *a_obj); 1094 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1095 Object result_obj(&scope, typeGetAttribute(thread_, a, name)); 1096 ASSERT_TRUE(result_obj.isTuple()); 1097 Tuple result(&scope, *result_obj); 1098 ASSERT_EQ(result.length(), 3); 1099 Type result_0_type(&scope, runtime_->typeOf(result.at(0))); 1100 EXPECT_TRUE(typeIsSubclass(*result_0_type, *d)); 1101 EXPECT_EQ(result.at(1), a); 1102 EXPECT_EQ(result.at(2), m); 1103} 1104 1105TEST_F(TypeBuiltinsTest, TypeGetAttributeCallsDunderGetOnNonDataDescriptor) { 1106 HandleScope scope(thread_); 1107 ASSERT_FALSE(runFromCStr(runtime_, R"( 1108class D: 1109 def __get__(self, instance, owner): return 42 1110class M(type): 1111 foo = D() 1112class A(metaclass=M): pass 1113)") 1114 .isError()); 1115 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1116 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1117 Type a(&scope, *a_obj); 1118 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1119 EXPECT_TRUE(isIntEqualsWord(typeGetAttribute(thread_, a, name), 42)); 1120} 1121 1122TEST_F(TypeBuiltinsTest, TypeGetAttributePrefersDataDescriptorOverTypeAttr) { 1123 HandleScope scope(thread_); 1124 ASSERT_FALSE(runFromCStr(runtime_, R"( 1125class D: 1126 def __set__(self, instance, value): pass 1127 def __get__(self, instance, owner): return 42 1128class M(type): 1129 foo = D() 1130class A(metaclass=M): 1131 foo = 12 1132)") 1133 .isError()); 1134 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1135 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1136 Type a(&scope, *a_obj); 1137 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1138 EXPECT_TRUE(isIntEqualsWord(typeGetAttribute(thread_, a, name), 42)); 1139} 1140 1141TEST_F(TypeBuiltinsTest, TypeGetAttributePrefersFieldOverNonDataDescriptor) { 1142 HandleScope scope(thread_); 1143 ASSERT_FALSE(runFromCStr(runtime_, R"( 1144class D: 1145 def __get__(self, instance, owner): return 42 1146class M(type): 1147 foo = D() 1148class A(metaclass=M): 1149 foo = 12 1150)") 1151 .isError()); 1152 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1153 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1154 Type a(&scope, *a_obj); 1155 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1156 EXPECT_TRUE(isIntEqualsWord(typeGetAttribute(thread_, a, name), 12)); 1157} 1158 1159TEST_F(TypeBuiltinsTest, TypeGetAttributePropagatesDunderGetException) { 1160 HandleScope scope(thread_); 1161 ASSERT_FALSE(runFromCStr(runtime_, R"( 1162class D: 1163 def __set__(self, instance, value): pass 1164 def __get__(self, instance, owner): raise UserWarning() 1165class M(type): 1166 foo = D() 1167class A(metaclass=M): pass 1168)") 1169 .isError()); 1170 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1171 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1172 Type a(&scope, *a_obj); 1173 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1174 EXPECT_TRUE( 1175 raised(typeGetAttribute(thread_, a, name), LayoutId::kUserWarning)); 1176} 1177 1178TEST_F(TypeBuiltinsTest, TypeGetAttributeOnNoneTypeReturnsFunction) { 1179 HandleScope scope(thread_); 1180 Type none_type(&scope, runtime_->typeAt(LayoutId::kNoneType)); 1181 Object name(&scope, Runtime::internStrFromCStr(thread_, "__repr__")); 1182 EXPECT_TRUE(typeGetAttribute(thread_, none_type, name).isFunction()); 1183} 1184 1185TEST_F(TypeBuiltinsTest, TypeSetAttrSetsAttribute) { 1186 HandleScope scope(thread_); 1187 ASSERT_FALSE(runFromCStr(runtime_, "class C: pass").isError()); 1188 Object c_obj(&scope, mainModuleAt(runtime_, "C")); 1189 ASSERT_TRUE(runtime_->isInstanceOfType(*c_obj)); 1190 Type c(&scope, *c_obj); 1191 Object name(&scope, Runtime::internStrFromCStr(thread_, "foobarbaz")); 1192 Object value(&scope, runtime_->newInt(-444)); 1193 EXPECT_TRUE(typeSetAttr(thread_, c, name, value).isNoneType()); 1194 EXPECT_TRUE(isIntEqualsWord(typeAt(c, name), -444)); 1195} 1196 1197TEST_F(TypeBuiltinsTest, TypeSetAttrCallsDunderSetOnDataDescriptor) { 1198 HandleScope scope(thread_); 1199 ASSERT_FALSE(runFromCStr(runtime_, R"( 1200class D: 1201 def __get__(self, instance, owner): pass 1202 def __set__(self, instance, value): 1203 global set_args 1204 set_args = (self, instance, value) 1205 return "ignored result" 1206foo = D() 1207class M(type): 1208 foo = foo 1209class A(metaclass=M): 1210 foo = "hidden by data descriptor" 1211)") 1212 .isError()); 1213 Object foo(&scope, mainModuleAt(runtime_, "foo")); 1214 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1215 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1216 Type a(&scope, *a_obj); 1217 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1218 Object value(&scope, runtime_->newInt(77)); 1219 EXPECT_TRUE(typeSetAttr(thread_, a, name, value).isNoneType()); 1220 Object set_args_obj(&scope, mainModuleAt(runtime_, "set_args")); 1221 ASSERT_TRUE(set_args_obj.isTuple()); 1222 Tuple set_args(&scope, *set_args_obj); 1223 ASSERT_EQ(set_args.length(), 3); 1224 EXPECT_EQ(set_args.at(0), foo); 1225 EXPECT_EQ(set_args.at(1), a); 1226 EXPECT_TRUE(isIntEqualsWord(set_args.at(2), 77)); 1227} 1228 1229TEST_F(TypeBuiltinsTest, TypeSetAttrPropagatesDunderSetException) { 1230 HandleScope scope(thread_); 1231 ASSERT_FALSE(runFromCStr(runtime_, R"( 1232class D: 1233 def __get__(self, instance, owner): pass 1234 def __set__(self, instance, value): raise UserWarning() 1235class M(type): 1236 foo = D() 1237class A(metaclass=M): 1238 pass 1239)") 1240 .isError()); 1241 Object a_obj(&scope, mainModuleAt(runtime_, "A")); 1242 ASSERT_TRUE(runtime_->isInstanceOfType(*a_obj)); 1243 Type a(&scope, *a_obj); 1244 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1245 Object value(&scope, runtime_->newInt(1)); 1246 EXPECT_TRUE( 1247 raised(typeSetAttr(thread_, a, name, value), LayoutId::kUserWarning)); 1248} 1249 1250TEST_F(TypeBuiltinsTest, TypeSetAttrOnBuiltinTypeRaisesTypeError) { 1251 HandleScope scope(thread_); 1252 Type type(&scope, runtime_->typeAt(LayoutId::kInt)); 1253 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 1254 Object value(&scope, NoneType::object()); 1255 EXPECT_TRUE(raisedWithStr( 1256 typeSetAttr(thread_, type, name, value), LayoutId::kTypeError, 1257 "can't set attributes of built-in/extension type 'int'")); 1258} 1259 1260TEST_F(TypeBuiltinsTest, TypeofSmallStrReturnsStr) { 1261 ASSERT_FALSE(runFromCStr(runtime_, R"( 1262result = type('a') 1263)") 1264 .isError()); 1265 EXPECT_EQ(mainModuleAt(runtime_, "result"), runtime_->typeAt(LayoutId::kStr)); 1266} 1267 1268TEST_F(TypeBuiltinsTest, TypeofLargeStrReturnsStr) { 1269 ASSERT_FALSE(runFromCStr(runtime_, R"( 1270result = type('aaaaaaaaaaaaaaaaaaaaaaa') 1271)") 1272 .isError()); 1273 EXPECT_EQ(mainModuleAt(runtime_, "result"), runtime_->typeAt(LayoutId::kStr)); 1274} 1275 1276TEST_F(TypeBuiltinsTest, TypeofSmallIntReturnsInt) { 1277 ASSERT_FALSE(runFromCStr(runtime_, R"( 1278result = type(5) 1279)") 1280 .isError()); 1281 EXPECT_EQ(mainModuleAt(runtime_, "result"), runtime_->typeAt(LayoutId::kInt)); 1282} 1283 1284TEST_F(TypeBuiltinsTest, TypeofLargeIntReturnsInt) { 1285 ASSERT_FALSE(runFromCStr(runtime_, R"( 1286result = type(99999999999999999999999999999999999999999) 1287)") 1288 .isError()); 1289 EXPECT_EQ(mainModuleAt(runtime_, "result"), runtime_->typeAt(LayoutId::kInt)); 1290} 1291 1292TEST_F(TypeBuiltinsTest, ResolveDescriptorGetReturnsNonDescriptor) { 1293 HandleScope scope(thread_); 1294 1295 Object instance(&scope, runtime_->newInt(123)); 1296 Object owner(&scope, NoneType::object()); 1297 Object descr(&scope, runtime_->newInt(456)); 1298 EXPECT_EQ(resolveDescriptorGet(thread_, descr, instance, owner), *descr); 1299} 1300 1301TEST_F(TypeBuiltinsTest, ResolveDescriptorGetCallsDescriptorDunderGet) { 1302 HandleScope scope(thread_); 1303 1304 Object instance(&scope, runtime_->newInt(123)); 1305 Type owner(&scope, runtime_->typeOf(*instance)); 1306 Object descr(&scope, typeLookupInMroById(thread_, *owner, ID(__add__))); 1307 ASSERT_TRUE(descr.isFunction()); 1308 EXPECT_TRUE( 1309 resolveDescriptorGet(thread_, descr, instance, owner).isBoundMethod()); 1310} 1311 1312TEST_F( 1313 TypeBuiltinsTest, 1314 TerminateIfUnimplementedTypeAttrCacheInvalidationDoesNotTerminateRuntimeForSupportedCacheInvalidation) { 1315 // __len__ supports cache invalidation. 1316 EXPECT_FALSE(runFromCStr(runtime_, R"( 1317class C: 1318 def __len__(self): return 0 1319 1320C.__len__ = lambda self: 4 1321)") 1322 .isError()); 1323 1324 // __setattr__ does not support cache invalidation, but it is not populated in 1325 // C so we do not terminate the runtime. 1326 EXPECT_FALSE(runFromCStr(runtime_, R"( 1327class C: pass 1328 1329C.__setattr__ = lambda self, key: 5 1330)") 1331 .isError()); 1332} 1333 1334TEST_F( 1335 TypeBuiltinsDeathTest, 1336 TerminateIfUnimplementedTypeAttrCacheInvalidationTerminatesRuntimeForUnsupportedCacheInvalidation) { 1337 // Redefining the existing __setattr__ terminates the runtime due to the 1338 // unsupported cache invalidation for it. 1339 ASSERT_DEATH(static_cast<void>(runFromCStr(runtime_, R"( 1340class C: 1341 def __setattr__(self, key): pass 1342 1343C.__setattr__ = lambda self, key: 5 1344)")), 1345 "unimplemented cache invalidation for type.__setattr__ update"); 1346} 1347 1348TEST_F(TypeBuiltinsTest, TypeIsMarkedAsCustomDict) { 1349 HandleScope scope(thread_); 1350 Type type(&scope, runtime_->typeAt(LayoutId::kType)); 1351 EXPECT_TRUE(type.hasFlag(Type::Flag::kHasCustomDict)); 1352 EXPECT_TRUE(Layout::cast(type.instanceLayout()).isSealed()); 1353} 1354 1355TEST_F(TypeBuiltinsTest, TypeSubclassLayoutIsSealed) { 1356 HandleScope scope(thread_); 1357 EXPECT_FALSE(runFromCStr(runtime_, R"( 1358class Meta(type): pass 1359)") 1360 .isError()); 1361 Type meta(&scope, mainModuleAt(runtime_, "Meta")); 1362 EXPECT_TRUE(meta.hasFlag(Type::Flag::kHasCustomDict)); 1363 EXPECT_TRUE(Layout::cast(meta.instanceLayout()).isSealed()); 1364} 1365 1366TEST_F(TypeBuiltinsTest, BuiltinTypesHaveAppropriateAttributeTypeFlags) { 1367 HandleScope scope(thread_); 1368 Type object_type(&scope, runtime_->typeAt(LayoutId::kObject)); 1369 EXPECT_TRUE(object_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1370 EXPECT_TRUE(object_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1371 EXPECT_TRUE(object_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1372 EXPECT_FALSE(object_type.hasFlag(Type::Flag::kHasStrDunderHash)); 1373 EXPECT_FALSE(object_type.hasFlag(Type::Flag::kHasDunderBool)); 1374 EXPECT_FALSE(object_type.hasFlag(Type::Flag::kHasDunderLen)); 1375 EXPECT_TRUE(object_type.hasFlag(Type::Flag::kHasObjectDunderClass)); 1376 EXPECT_FALSE(object_type.hasFlag(Type::Flag::kHasDunderGet)); 1377 EXPECT_FALSE(object_type.hasFlag(Type::Flag::kHasDunderSet)); 1378 EXPECT_FALSE(object_type.hasFlag(Type::Flag::kHasDunderDelete)); 1379 EXPECT_TRUE(object_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1380 1381 Type type_type(&scope, runtime_->typeAt(LayoutId::kType)); 1382 EXPECT_TRUE(type_type.hasFlag(Type::Flag::kHasTypeDunderGetattribute)); 1383 EXPECT_FALSE(type_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1384 EXPECT_TRUE(type_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1385 EXPECT_TRUE(type_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1386 1387 Type module_type(&scope, runtime_->typeAt(LayoutId::kModule)); 1388 EXPECT_TRUE(module_type.hasFlag(Type::Flag::kHasModuleDunderGetattribute)); 1389 EXPECT_FALSE(module_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1390 EXPECT_TRUE(module_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1391 EXPECT_TRUE(module_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1392 1393 Type property_type(&scope, runtime_->typeAt(LayoutId::kProperty)); 1394 EXPECT_TRUE(property_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1395 EXPECT_FALSE(property_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1396 EXPECT_TRUE(property_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1397 EXPECT_TRUE(module_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1398 EXPECT_TRUE(property_type.hasFlag(Type::Flag::kHasDunderGet)); 1399 EXPECT_TRUE(property_type.hasFlag(Type::Flag::kHasDunderSet)); 1400 EXPECT_TRUE(property_type.hasFlag(Type::Flag::kHasDunderDelete)); 1401 EXPECT_TRUE(property_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1402 1403 Type function_type(&scope, runtime_->typeAt(LayoutId::kFunction)); 1404 EXPECT_TRUE(function_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1405 EXPECT_FALSE(function_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1406 EXPECT_TRUE(function_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1407 EXPECT_TRUE(function_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1408 1409 Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); 1410 EXPECT_TRUE(int_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1411 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1412 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1413 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasStrDunderHash)); 1414 EXPECT_TRUE(int_type.hasFlag(Type::Flag::kHasDunderBool)); 1415 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasDunderLen)); 1416 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasDunderGet)); 1417 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasDunderSet)); 1418 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasDunderDelete)); 1419 EXPECT_FALSE(int_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1420 1421 Type str_type(&scope, runtime_->typeAt(LayoutId::kStr)); 1422 EXPECT_TRUE(str_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1423 EXPECT_FALSE(str_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1424 EXPECT_FALSE(str_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1425 // TODO(T83275120): Flip the condition. 1426 EXPECT_TRUE(str_type.hasFlag(Type::Flag::kHasDunderBool)); 1427 EXPECT_TRUE(str_type.hasFlag(Type::Flag::kHasDunderLen)); 1428 EXPECT_FALSE(str_type.hasFlag(Type::Flag::kHasObjectDunderEq)); 1429 1430 // super.__getattribute__ is not same as object.__getattribute. 1431 Type super_type(&scope, runtime_->typeAt(LayoutId::kSuper)); 1432 EXPECT_FALSE(super_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1433 EXPECT_FALSE(super_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1434 EXPECT_TRUE(super_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1435 1436 // BaseException inherits object.__new__. 1437 Type base_exception_type(&scope, runtime_->typeAt(LayoutId::kBaseException)); 1438 EXPECT_TRUE( 1439 base_exception_type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1440 EXPECT_TRUE(base_exception_type.hasFlag(Type::Flag::kHasObjectDunderNew)); 1441 EXPECT_TRUE(base_exception_type.hasFlag(Type::Flag::kHasObjectDunderHash)); 1442 1443 // NoneType.__class__'s behavior is same as object.__class__ although 1444 // they point to different objects. 1445 Type none_type(&scope, runtime_->typeAt(LayoutId::kNoneType)); 1446 EXPECT_TRUE(none_type.hasFlag(Type::Flag::kHasObjectDunderClass)); 1447} 1448 1449TEST_F(TypeBuiltinsTest, UserTypesHaveAttributeTypeFlags) { 1450 HandleScope scope(thread_); 1451 EXPECT_FALSE(runFromCStr(runtime_, R"( 1452class C: pass 1453 1454class D(type): pass 1455 1456class E(module): pass 1457 1458class F: 1459 def __new__(cls): return None 1460 1461class G: 1462 def __hash__(self): return 10 1463 1464class H: 1465 def __bool__(self): return False 1466 1467class I: 1468 def __len__(self): return 10 1469 1470class J: 1471 __class__ = None 1472 1473class K: 1474 def __get__(self, owner, type): 1475 return None 1476 1477class L: 1478 def __set__(self, owner, value): 1479 return None 1480 1481class M: 1482 def __delete__(self, obj): 1483 return None 1484 1485class N: 1486 def __eq__(self, other): 1487 return None 1488 1489class SubN(N): 1490 pass 1491 1492class Str(str): pass 1493 1494class Str2(Str): 1495 def __hash__(self): return 10 1496 1497)") 1498 .isError()); 1499 Type c(&scope, mainModuleAt(runtime_, "C")); 1500 EXPECT_TRUE(c.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1501 EXPECT_TRUE(c.hasFlag(Type::Flag::kHasObjectDunderNew)); 1502 EXPECT_TRUE(c.hasFlag(Type::Flag::kHasObjectDunderHash)); 1503 EXPECT_TRUE(c.hasFlag(Type::Flag::kHasObjectDunderClass)); 1504 EXPECT_TRUE(c.hasFlag(Type::Flag::kHasObjectDunderEq)); 1505 1506 Type d(&scope, mainModuleAt(runtime_, "D")); 1507 EXPECT_TRUE(d.hasFlag(Type::Flag::kHasTypeDunderGetattribute)); 1508 EXPECT_FALSE(d.hasFlag(Type::Flag::kHasObjectDunderNew)); 1509 EXPECT_TRUE(d.hasFlag(Type::Flag::kHasObjectDunderHash)); 1510 1511 Type e(&scope, mainModuleAt(runtime_, "E")); 1512 EXPECT_TRUE(e.hasFlag(Type::Flag::kHasModuleDunderGetattribute)); 1513 EXPECT_FALSE(e.hasFlag(Type::Flag::kHasObjectDunderNew)); 1514 EXPECT_TRUE(e.hasFlag(Type::Flag::kHasObjectDunderHash)); 1515 1516 Type f(&scope, mainModuleAt(runtime_, "F")); 1517 EXPECT_TRUE(f.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1518 EXPECT_FALSE(f.hasFlag(Type::Flag::kHasObjectDunderNew)); 1519 EXPECT_TRUE(f.hasFlag(Type::Flag::kHasObjectDunderHash)); 1520 1521 Type g(&scope, mainModuleAt(runtime_, "G")); 1522 EXPECT_TRUE(g.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1523 EXPECT_TRUE(g.hasFlag(Type::Flag::kHasObjectDunderNew)); 1524 EXPECT_FALSE(g.hasFlag(Type::Flag::kHasObjectDunderHash)); 1525 1526 Type h(&scope, mainModuleAt(runtime_, "H")); 1527 EXPECT_TRUE(h.hasFlag(Type::Flag::kHasDunderBool)); 1528 EXPECT_FALSE(h.hasFlag(Type::Flag::kHasDunderLen)); 1529 1530 Type i(&scope, mainModuleAt(runtime_, "I")); 1531 EXPECT_FALSE(i.hasFlag(Type::Flag::kHasDunderBool)); 1532 EXPECT_TRUE(i.hasFlag(Type::Flag::kHasDunderLen)); 1533 1534 Type j(&scope, mainModuleAt(runtime_, "J")); 1535 EXPECT_FALSE(j.hasFlag(Type::Flag::kHasObjectDunderClass)); 1536 1537 Type k(&scope, mainModuleAt(runtime_, "K")); 1538 EXPECT_TRUE(k.hasFlag(Type::Flag::kHasDunderGet)); 1539 EXPECT_FALSE(k.hasFlag(Type::Flag::kHasDunderSet)); 1540 EXPECT_FALSE(k.hasFlag(Type::Flag::kHasDunderDelete)); 1541 EXPECT_FALSE(typeIsDataDescriptor(*k)); 1542 EXPECT_TRUE(typeIsNonDataDescriptor(*k)); 1543 1544 Type l(&scope, mainModuleAt(runtime_, "L")); 1545 EXPECT_FALSE(l.hasFlag(Type::Flag::kHasDunderGet)); 1546 EXPECT_TRUE(l.hasFlag(Type::Flag::kHasDunderSet)); 1547 EXPECT_FALSE(l.hasFlag(Type::Flag::kHasDunderDelete)); 1548 EXPECT_TRUE(typeIsDataDescriptor(*l)); 1549 EXPECT_FALSE(typeIsNonDataDescriptor(*l)); 1550 1551 Type m(&scope, mainModuleAt(runtime_, "M")); 1552 EXPECT_FALSE(m.hasFlag(Type::Flag::kHasDunderGet)); 1553 EXPECT_FALSE(m.hasFlag(Type::Flag::kHasDunderSet)); 1554 EXPECT_TRUE(m.hasFlag(Type::Flag::kHasDunderDelete)); 1555 EXPECT_TRUE(typeIsDataDescriptor(*m)); 1556 EXPECT_FALSE(typeIsNonDataDescriptor(*m)); 1557 1558 Type n(&scope, mainModuleAt(runtime_, "N")); 1559 EXPECT_FALSE(n.hasFlag(Type::Flag::kHasObjectDunderEq)); 1560 1561 Type sub_n(&scope, mainModuleAt(runtime_, "SubN")); 1562 EXPECT_FALSE(sub_n.hasFlag(Type::Flag::kHasObjectDunderEq)); 1563 1564 Type str(&scope, mainModuleAt(runtime_, "Str")); 1565 EXPECT_TRUE(str.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1566 EXPECT_FALSE(str.hasFlag(Type::Flag::kHasObjectDunderNew)); 1567 EXPECT_FALSE(str.hasFlag(Type::Flag::kHasObjectDunderHash)); 1568 EXPECT_TRUE(str.hasFlag(Type::Flag::kHasStrDunderHash)); 1569 1570 Type str2(&scope, mainModuleAt(runtime_, "Str2")); 1571 EXPECT_TRUE(str2.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1572 EXPECT_FALSE(str2.hasFlag(Type::Flag::kHasObjectDunderNew)); 1573 EXPECT_FALSE(str2.hasFlag(Type::Flag::kHasObjectDunderHash)); 1574 EXPECT_FALSE(str2.hasFlag(Type::Flag::kHasStrDunderHash)); 1575} 1576 1577TEST_F(TypeBuiltinsTest, AttributeTypeFlagsPropagateThroughTypeHierarchy) { 1578 HandleScope scope(thread_); 1579 ASSERT_FALSE(runFromCStr(runtime_, R"( 1580class A: 1581 pass 1582 1583class B(A): 1584 def __getattribute__(self, name): return name 1585 1586class C(B): 1587 pass 1588 1589class X: 1590 pass 1591 1592class D(X, C): 1593 pass 1594)") 1595 .isError()); 1596 Type a(&scope, mainModuleAt(runtime_, "A")); 1597 EXPECT_TRUE(a.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1598 Type b(&scope, mainModuleAt(runtime_, "B")); 1599 EXPECT_FALSE(b.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1600 Type c(&scope, mainModuleAt(runtime_, "C")); 1601 EXPECT_FALSE(c.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1602 Type d(&scope, mainModuleAt(runtime_, "D")); 1603 EXPECT_FALSE(d.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1604} 1605 1606TEST_F(TypeBuiltinsTest, 1607 AttributeTypeFlagsForTypesWithMetaclassWithDefaultMro) { 1608 HandleScope scope(thread_); 1609 ASSERT_FALSE(runFromCStr(runtime_, R"( 1610class MetaWithDefaultMro(type): 1611 def foo(self): return 500 1612 1613class A(metaclass=MetaWithDefaultMro): 1614 pass 1615 1616class B(A): 1617 pass 1618)") 1619 .isError()); 1620 Type a(&scope, mainModuleAt(runtime_, "A")); 1621 EXPECT_FALSE(a.hasFlag(Type::Flag::kHasCustomMro)); 1622 EXPECT_TRUE(a.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1623 Type b(&scope, mainModuleAt(runtime_, "B")); 1624 EXPECT_TRUE(b.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1625} 1626 1627TEST_F(TypeBuiltinsTest, AttributeTypeFlagsForTypesWithMetaclassWithCustomMro) { 1628 HandleScope scope(thread_); 1629 ASSERT_FALSE(runFromCStr(runtime_, R"( 1630class MetaWithCustomMro(type): 1631 def mro(self): 1632 return (self,) 1633 1634class A(metaclass=MetaWithCustomMro): 1635 pass 1636 1637class B(A): 1638 pass 1639)") 1640 .isError()); 1641 Type a(&scope, mainModuleAt(runtime_, "A")); 1642 EXPECT_TRUE(a.hasFlag(Type::Flag::kHasCustomMro)); 1643 EXPECT_FALSE(a.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1644 Type b(&scope, mainModuleAt(runtime_, "B")); 1645 EXPECT_FALSE(b.hasFlag(Type::Flag::kHasObjectDunderGetattribute)); 1646} 1647 1648} // namespace testing 1649} // namespace py