this repo has no description
at trunk 3731 lines 129 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "runtime.h" 3 4#include <csignal> 5#include <cstdlib> 6#include <memory> 7 8#include "gtest/gtest.h" 9 10#include "bytecode.h" 11#include "bytes-builtins.h" 12#include "capi.h" 13#include "dict-builtins.h" 14#include "file.h" 15#include "frame.h" 16#include "int-builtins.h" 17#include "layout.h" 18#include "memoryview-builtins.h" 19#include "module-builtins.h" 20#include "object-builtins.h" 21#include "set-builtins.h" 22#include "str-builtins.h" 23#include "symbols.h" 24#include "test-utils.h" 25#include "trampolines.h" 26#include "type-builtins.h" 27 28namespace py { 29namespace testing { 30 31using RuntimeAttributeTest = RuntimeFixture; 32using RuntimeBytearrayTest = RuntimeFixture; 33using RuntimeBytesTest = RuntimeFixture; 34using RuntimeClassAttrTest = RuntimeFixture; 35using RuntimeFunctionAttrTest = RuntimeFixture; 36using RuntimeInstanceAttrTest = RuntimeFixture; 37using RuntimeIntTest = RuntimeFixture; 38using RuntimeListTest = RuntimeFixture; 39using RuntimeMetaclassTest = RuntimeFixture; 40using RuntimeModuleAttrTest = RuntimeFixture; 41using RuntimeModuleTest = RuntimeFixture; 42using RuntimeSetTest = RuntimeFixture; 43using RuntimeStrArrayTest = RuntimeFixture; 44using RuntimeStrTest = RuntimeFixture; 45using RuntimeTest = RuntimeFixture; 46using RuntimeTupleTest = RuntimeFixture; 47using RuntimeTypeCallTest = RuntimeFixture; 48 49RawObject makeTestFunction() { 50 Thread* thread = Thread::current(); 51 HandleScope scope(thread); 52 Runtime* runtime = thread->runtime(); 53 Object obj(&scope, NoneType::object()); 54 Tuple consts(&scope, runtime->newTupleWith1(obj)); 55 const byte bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0}; 56 Code code(&scope, newCodeWithBytesConsts(bytecode, consts)); 57 Object qualname(&scope, runtime->newStrFromCStr("foo")); 58 Module module(&scope, findMainModule(runtime)); 59 return runtime->newFunctionWithCode(thread, qualname, code, module); 60} 61 62TEST_F(RuntimeTest, CollectGarbage) { 63 ASSERT_TRUE(runtime_->heap()->verify()); 64 runtime_->collectGarbage(); 65 ASSERT_TRUE(runtime_->heap()->verify()); 66} 67 68TEST_F(RuntimeTest, ComputeBuiltinBaseReturnsMostSpecificBase) { 69 ASSERT_FALSE(runFromCStr(runtime_, R"( 70class C(UnicodeDecodeError, LookupError): 71 pass 72)") 73 .isError()); 74 HandleScope scope(thread_); 75 Object c(&scope, mainModuleAt(runtime_, "C")); 76 ASSERT_TRUE(c.isType()); 77 EXPECT_EQ(Type::cast(*c).builtinBase(), LayoutId::kUnicodeDecodeError); 78} 79 80TEST_F(RuntimeTest, ComputeBuiltinBaseWithConflictingBasesRaisesTypeError) { 81 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 82class FailingMultiClass(UnicodeDecodeError, UnicodeEncodeError): 83 pass 84)"), 85 LayoutId::kTypeError, 86 "multiple bases have instance lay-out conflict")); 87} 88 89TEST(RuntimeTestNoFixture, AllocateAndCollectGarbage) { 90 const word heap_size = 32 * kMiB; 91 const word array_length = 1024; 92 const word allocation_size = 93 roundAllocationSize(array_length + HeapObject::headerSize(array_length)); 94 const word total_allocation_size = heap_size * 10; 95 RandomState random_seed = randomStateFromSeed(0); 96 std::unique_ptr<Runtime> runtime(new Runtime( 97 heap_size, createCppInterpreter(), random_seed, StdioState::kBuffered)); 98 99 ASSERT_TRUE(runtime->heap()->verify()); 100 for (word i = 0; i < total_allocation_size; i += allocation_size) { 101 runtime->newBytes(array_length, 0); 102 } 103 ASSERT_TRUE(runtime->heap()->verify()); 104} 105 106TEST_F(RuntimeTest, AttributeAtCallsDunderGetattribute) { 107 HandleScope scope(thread_); 108 ASSERT_FALSE(runFromCStr(runtime_, R"( 109class C: 110 foo = None 111 def __getattribute__(self, name): 112 return (self, name) 113c = C() 114)") 115 .isError()); 116 Object c(&scope, mainModuleAt(runtime_, "c")); 117 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 118 Object result_obj(&scope, runtime_->attributeAt(thread_, c, name)); 119 ASSERT_TRUE(result_obj.isTuple()); 120 Tuple result(&scope, *result_obj); 121 ASSERT_EQ(result.length(), 2); 122 EXPECT_EQ(result.at(0), c); 123 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "foo")); 124} 125 126TEST_F(RuntimeTest, AttributeAtPropagatesExceptionFromDunderGetAttribute) { 127 HandleScope scope(thread_); 128 ASSERT_FALSE(runFromCStr(runtime_, R"( 129class C: 130 def __getattribute__(self, name): 131 raise UserWarning() 132c = C() 133)") 134 .isError()); 135 Object c(&scope, mainModuleAt(runtime_, "c")); 136 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 137 EXPECT_TRUE( 138 raised(runtime_->attributeAt(thread_, c, name), LayoutId::kUserWarning)); 139} 140 141TEST_F(RuntimeTest, AttributeAtPropagatesExceptionFromDunderGetAttributeDescr) { 142 HandleScope scope(thread_); 143 ASSERT_FALSE(runFromCStr(runtime_, R"( 144class Descr: 145 def __get__(self, instance, owner): 146 raise UserWarning("foo") 147class C: 148 __getattribute__ = Descr() 149c = C() 150)") 151 .isError()); 152 Object c(&scope, mainModuleAt(runtime_, "c")); 153 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 154 EXPECT_TRUE( 155 raised(runtime_->attributeAt(thread_, c, name), LayoutId::kUserWarning)); 156} 157 158TEST_F(RuntimeTest, AttributeAtCallsDunderGetattr) { 159 HandleScope scope(thread_); 160 ASSERT_FALSE(runFromCStr(runtime_, R"( 161class C: 162 foo = 10 163 def __getattr__(self, name): 164 return (self, name) 165c = C() 166)") 167 .isError()); 168 Object c(&scope, mainModuleAt(runtime_, "c")); 169 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 170 EXPECT_TRUE(isIntEqualsWord(runtime_->attributeAt(thread_, c, foo), 10)); 171 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 172 Object result_obj(&scope, runtime_->attributeAt(thread_, c, bar)); 173 ASSERT_TRUE(result_obj.isTuple()); 174 Tuple result(&scope, *result_obj); 175 ASSERT_EQ(result.length(), 2); 176 EXPECT_EQ(result.at(0), c); 177 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "bar")); 178} 179 180TEST_F(RuntimeTest, AttributeAtDoesNotCallDunderGetattrOnNonAttributeError) { 181 HandleScope scope(thread_); 182 ASSERT_FALSE(runFromCStr(runtime_, R"( 183class C: 184 def __getattribute__(self, name): 185 raise UserWarning() 186 def __getattr__(self, name): 187 _unimplemented() 188c = C() 189)") 190 .isError()); 191 Object c(&scope, mainModuleAt(runtime_, "c")); 192 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 193 EXPECT_TRUE( 194 raised(runtime_->attributeAt(thread_, c, foo), LayoutId::kUserWarning)); 195} 196 197TEST_F(RuntimeTest, AttributeAtSetLocationSetsLocation) { 198 HandleScope scope(thread_); 199 ASSERT_FALSE(runFromCStr(runtime_, R"( 200class C: 201 def __init__(self): 202 self.foo = 42 203i = C() 204)") 205 .isError()); 206 Object i(&scope, mainModuleAt(runtime_, "i")); 207 208 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 209 Object to_cache(&scope, NoneType::object()); 210 LoadAttrKind kind = LoadAttrKind::kInstanceOffset; 211 EXPECT_TRUE(isIntEqualsWord( 212 runtime_->attributeAtSetLocation(thread_, i, name, &kind, &to_cache), 213 42)); 214 EXPECT_EQ(kind, LoadAttrKind::kInstanceOffset); 215 EXPECT_TRUE(isIntEqualsWord( 216 Interpreter::loadAttrWithLocation(thread_, *i, *to_cache), 42)); 217} 218 219TEST_F(RuntimeTest, AttributeAtSetLocationSetsLocationToProprty) { 220 HandleScope scope(thread_); 221 ASSERT_FALSE(runFromCStr(runtime_, R"( 222 223def foo(self): return "data descriptor" 224 225class C: 226 foo = property (foo) 227 228c = C() 229)") 230 .isError()); 231 Object c(&scope, mainModuleAt(runtime_, "c")); 232 Str name(&scope, runtime_->newStrFromCStr("foo")); 233 Object to_cache(&scope, NoneType::object()); 234 LoadAttrKind kind = LoadAttrKind::kUnknown; 235 EXPECT_TRUE(isStrEqualsCStr( 236 runtime_->attributeAtSetLocation(thread_, c, name, &kind, &to_cache), 237 "data descriptor")); 238 EXPECT_EQ(kind, LoadAttrKind::kInstanceProperty); 239 EXPECT_EQ(to_cache, mainModuleAt(runtime_, "foo")); 240} 241 242TEST_F( 243 RuntimeTest, 244 AttributeAtSetLocationSetLocationToPropertyAsDataDescriptorWithNoneGetter) { 245 HandleScope scope(thread_); 246 ASSERT_FALSE(runFromCStr(runtime_, R"( 247C_foo = property (fget=None, fset=lambda self,v: None, fdel=lambda self: None) 248class C: 249 foo = C_foo 250 251c = C() 252)") 253 .isError()); 254 Object c(&scope, mainModuleAt(runtime_, "c")); 255 Str name(&scope, runtime_->newStrFromCStr("foo")); 256 Object to_cache(&scope, NoneType::object()); 257 LoadAttrKind kind = LoadAttrKind::kUnknown; 258 EXPECT_TRUE( 259 runtime_->attributeAtSetLocation(thread_, c, name, &kind, &to_cache) 260 .isError()); 261 EXPECT_EQ(to_cache, mainModuleAt(runtime_, "C_foo")); 262 EXPECT_EQ(kind, LoadAttrKind::kInstanceTypeDescr); 263} 264 265TEST_F(RuntimeTest, LoadAttrWithModuleSetLocationSetsLocation) { 266 HandleScope scope(thread_); 267 ASSERT_FALSE(runFromCStr(runtime_, R"( 268a_global = 1234 269)") 270 .isError()); 271 Object mod(&scope, findMainModule(runtime_)); 272 Object name(&scope, Runtime::internStrFromCStr(thread_, "a_global")); 273 274 Object to_cache(&scope, NoneType::object()); 275 LoadAttrKind kind; 276 ASSERT_TRUE(isIntEqualsWord( 277 runtime_->attributeAtSetLocation(thread_, mod, name, &kind, &to_cache), 278 1234)); 279 EXPECT_EQ(kind, LoadAttrKind::kModule); 280 EXPECT_EQ(to_cache.layoutId(), LayoutId::kValueCell); 281} 282 283TEST_F(RuntimeTest, LoadAttrWithTypeSetLocationSetsLocation) { 284 HandleScope scope(thread_); 285 ASSERT_FALSE(runFromCStr(runtime_, R"( 286class C: 287 an_attribute = 1234 288)") 289 .isError()); 290 Object type(&scope, mainModuleAt(runtime_, "C")); 291 292 Object name(&scope, Runtime::internStrFromCStr(thread_, "an_attribute")); 293 294 Object to_cache(&scope, NoneType::object()); 295 LoadAttrKind kind; 296 ASSERT_TRUE(isIntEqualsWord( 297 runtime_->attributeAtSetLocation(thread_, type, name, &kind, &to_cache), 298 1234)); 299 EXPECT_EQ(kind, LoadAttrKind::kType); 300 EXPECT_EQ(to_cache.layoutId(), LayoutId::kValueCell); 301} 302 303TEST_F(RuntimeTest, 304 AttributeAtSetLocationWithCustomGetAttributeSetsNoLocation) { 305 HandleScope scope(thread_); 306 ASSERT_FALSE(runFromCStr(runtime_, R"( 307class C: 308 def __getattribute__(self, name): 309 return 11 310i = C() 311)") 312 .isError()); 313 Object i(&scope, mainModuleAt(runtime_, "i")); 314 315 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo")); 316 Object to_cache(&scope, NoneType::object()); 317 LoadAttrKind kind; 318 EXPECT_TRUE(isIntEqualsWord( 319 runtime_->attributeAtSetLocation(thread_, i, name, &kind, &to_cache), 320 11)); 321 EXPECT_EQ(kind, LoadAttrKind::kUnknown); 322 EXPECT_TRUE(to_cache.isNoneType()); 323} 324 325TEST_F(RuntimeTest, AttributeAtSetLocationCallsDunderGetattr) { 326 HandleScope scope(thread_); 327 ASSERT_FALSE(runFromCStr(runtime_, R"( 328class C: 329 def __init__(self): 330 self.foo = 42 331 def __getattr__(self, name): 332 return 5 333i = C() 334)") 335 .isError()); 336 Object i(&scope, mainModuleAt(runtime_, "i")); 337 338 Object name(&scope, Runtime::internStrFromCStr(thread_, "bar")); 339 Object to_cache(&scope, NoneType::object()); 340 LoadAttrKind kind; 341 342 EXPECT_TRUE(isIntEqualsWord( 343 runtime_->attributeAtSetLocation(thread_, i, name, &kind, &to_cache), 5)); 344 EXPECT_EQ(kind, LoadAttrKind::kUnknown); 345 EXPECT_TRUE(to_cache.isNoneType()); 346} 347 348TEST_F(RuntimeTest, AttributeAtSetLocationWithNoAttributeRaisesAttributeError) { 349 HandleScope scope(thread_); 350 ASSERT_FALSE(runFromCStr(runtime_, R"( 351obj = object() 352)") 353 .isError()); 354 355 Object obj(&scope, mainModuleAt(runtime_, "obj")); 356 Object name(&scope, Runtime::internStrFromCStr(thread_, "nonexistent_attr")); 357 LoadAttrKind kind; 358 EXPECT_TRUE(raisedWithStr( 359 runtime_->attributeAtSetLocation(thread_, obj, name, &kind, nullptr), 360 LayoutId::kAttributeError, 361 "'object' object has no attribute 'nonexistent_attr'")); 362} 363 364// Return the raw name of a builtin LayoutId, or "<invalid>" for user-defined or 365// invalid LayoutIds. 366static const char* layoutIdName(LayoutId id) { 367 switch (id) { 368 case LayoutId::kError: 369 // Special-case the one type that isn't really a class so we don't have to 370 // have it in CLASS_NAMES. 371 return "RawError"; 372 373#define CASE(name) \ 374 case LayoutId::k##name: \ 375 return #name; 376 CLASS_NAMES(CASE) 377#undef CASE 378 case LayoutId::kSentinelId: 379 return "<SentinelId>"; 380 } 381 return "<invalid>"; 382} 383 384class BuiltinTypeIdsTest : public ::testing::TestWithParam<LayoutId> {}; 385 386// Make sure that each built-in class has a class object. Check that its class 387// object points to a layout with the same layout ID as the built-in class. 388TEST_P(BuiltinTypeIdsTest, HasTypeObject) { 389 std::unique_ptr<Runtime> runtime(createTestRuntime()); 390 HandleScope scope(Thread::current()); 391 392 LayoutId id = GetParam(); 393 ASSERT_EQ(runtime->layoutAt(id).layoutId(), LayoutId::kLayout) 394 << "Bad RawLayout for " << layoutIdName(id); 395 Object elt(&scope, runtime->concreteTypeAt(id)); 396 ASSERT_TRUE(elt.isType()); 397 Type cls(&scope, *elt); 398 Layout layout(&scope, cls.instanceLayout()); 399 EXPECT_EQ(layout.id(), GetParam()); 400} 401 402static const LayoutId kBuiltinHeapTypeIds[] = { 403#define ENUM(x) LayoutId::k##x, 404 HEAP_CLASS_NAMES(ENUM) 405#undef ENUM 406}; 407 408INSTANTIATE_TEST_SUITE_P(BuiltinTypeIdsParameters, BuiltinTypeIdsTest, 409 ::testing::ValuesIn(kBuiltinHeapTypeIds)); 410 411TEST_F(RuntimeTest, ConcreteIntTypeBaseIsUserType) { 412 HandleScope scope(thread_); 413 Object smallint(&scope, SmallInt::fromWord(42)); 414 Object largeint(&scope, runtime_->newIntFromUnsigned(kMaxUword)); 415 Type smallint_type(&scope, runtime_->concreteTypeOf(*smallint)); 416 Type largeint_type(&scope, runtime_->concreteTypeOf(*largeint)); 417 EXPECT_EQ(smallint_type.instanceLayout(), 418 runtime_->layoutAt(LayoutId::kSmallInt)); 419 EXPECT_EQ(largeint_type.instanceLayout(), 420 runtime_->layoutAt(LayoutId::kLargeInt)); 421 EXPECT_EQ(smallint_type.builtinBase(), LayoutId::kInt); 422 EXPECT_EQ(largeint_type.builtinBase(), LayoutId::kInt); 423} 424 425TEST_F(RuntimeTest, ConcreteBytesTypeBaseIsUserType) { 426 HandleScope scope(thread_); 427 byte small_src[] = "42"; 428 byte large_src[] = "my long bytes"; 429 Object smallbytes(&scope, SmallBytes::fromBytes(small_src)); 430 Object largebytes(&scope, runtime_->newBytesWithAll(large_src)); 431 Type smallbytes_type(&scope, runtime_->concreteTypeOf(*smallbytes)); 432 Type largebytes_type(&scope, runtime_->concreteTypeOf(*largebytes)); 433 EXPECT_EQ(smallbytes_type.instanceLayout(), 434 runtime_->layoutAt(LayoutId::kSmallBytes)); 435 EXPECT_EQ(largebytes_type.instanceLayout(), 436 runtime_->layoutAt(LayoutId::kLargeBytes)); 437 EXPECT_EQ(smallbytes_type.builtinBase(), LayoutId::kBytes); 438 EXPECT_EQ(largebytes_type.builtinBase(), LayoutId::kBytes); 439} 440 441TEST_F(RuntimeTest, ConcreteStrTypeBaseIsUserType) { 442 HandleScope scope(thread_); 443 Object smallstr(&scope, SmallStr::fromCStr("42")); 444 Object largestr(&scope, runtime_->newStrFromCStr("my long str")); 445 Type smallstr_type(&scope, runtime_->concreteTypeOf(*smallstr)); 446 Type largestr_type(&scope, runtime_->concreteTypeOf(*largestr)); 447 EXPECT_EQ(smallstr_type.instanceLayout(), 448 runtime_->layoutAt(LayoutId::kSmallStr)); 449 EXPECT_EQ(largestr_type.instanceLayout(), 450 runtime_->layoutAt(LayoutId::kLargeStr)); 451 EXPECT_EQ(smallstr_type.builtinBase(), LayoutId::kStr); 452 EXPECT_EQ(largestr_type.builtinBase(), LayoutId::kStr); 453} 454 455TEST_F(RuntimeBytearrayTest, EnsureCapacity) { 456 HandleScope scope(thread_); 457 458 Bytearray array(&scope, runtime_->newBytearray()); 459 word length = 1; 460 word expected_capacity = 16; 461 runtime_->bytearrayEnsureCapacity(thread_, array, length); 462 EXPECT_EQ(array.capacity(), expected_capacity); 463 464 length = 17; 465 expected_capacity = 24; 466 runtime_->bytearrayEnsureCapacity(thread_, array, length); 467 EXPECT_EQ(array.capacity(), expected_capacity); 468 469 length = 40; 470 expected_capacity = 40; 471 runtime_->bytearrayEnsureCapacity(thread_, array, length); 472 EXPECT_EQ(array.capacity(), expected_capacity); 473} 474 475TEST_F(RuntimeBytearrayTest, Extend) { 476 HandleScope scope(thread_); 477 478 Bytearray array(&scope, runtime_->newBytearray()); 479 View<byte> hello(reinterpret_cast<const byte*>("Hello world!"), 5); 480 runtime_->bytearrayExtend(thread_, array, hello); 481 EXPECT_GE(array.capacity(), 5); 482 EXPECT_EQ(array.numItems(), 5); 483 484 Bytes bytes(&scope, array.items()); 485 bytes = bytesSubseq(thread_, bytes, 0, 5); 486 EXPECT_TRUE(isBytesEqualsCStr(bytes, "Hello")); 487} 488 489TEST_F(RuntimeBytesTest, BytesReplaceWithSmallBytesAndNegativeReplacesAll) { 490 HandleScope scope(thread_); 491 const byte src[] = {'1', '2', '2'}; 492 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 493 494 const byte in[] = {'2'}; 495 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 496 497 const byte out[] = {'*'}; 498 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 499 500 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 1, 501 new_bytes, 1, -1)); 502 EXPECT_TRUE(isBytesEqualsCStr(result, "1**")); 503} 504 505TEST_F(RuntimeBytesTest, BytesReplaceWithLargeBytesAndNegativeReplacesAll) { 506 HandleScope scope(thread_); 507 const byte src[] = {'1', '1', '1', '1', '1', '1', '1', '2', '1', '1', '1', 508 '1', '1', '1', '1', '1', '1', '1', '2', '1', '1'}; 509 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 510 511 const byte in[] = {'2'}; 512 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 513 514 const byte out[] = {'*'}; 515 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 516 517 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 1, 518 new_bytes, 1, -1)); 519 EXPECT_TRUE(isBytesEqualsCStr(result, "1111111*1111111111*11")); 520} 521 522TEST_F(RuntimeBytesTest, BytesReplaceWithLargeBytesAndCountReplacesSome) { 523 HandleScope scope(thread_); 524 const byte src[] = {'1', '1', '1', '1', '1', '1', '1', '2', '1', '1', '1', 525 '1', '1', '1', '1', '1', '1', '1', '2', '1', '1'}; 526 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 527 528 const byte in[] = {'2'}; 529 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 530 531 const byte out[] = {'*'}; 532 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 533 534 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 1, 535 new_bytes, 1, 1)); 536 EXPECT_TRUE(isBytesEqualsCStr(result, "1111111*1111111111211")); 537} 538 539TEST_F(RuntimeBytesTest, BytesReplaceWithLongerNewReturnsLonger) { 540 HandleScope scope(thread_); 541 const byte src[] = {'1', '2'}; 542 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 543 544 const byte in[] = {'2'}; 545 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 546 547 const byte out[] = {'*', '*'}; 548 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 549 550 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 1, 551 new_bytes, 2, -1)); 552 EXPECT_TRUE(isBytesEqualsCStr(result, "1**")); 553} 554 555TEST_F(RuntimeBytesTest, BytesReplaceWithShorterNewReturnsShorter) { 556 HandleScope scope(thread_); 557 const byte src[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1'}; 558 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 559 560 const byte in[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1'}; 561 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 562 563 const byte out[] = {'*'}; 564 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 565 566 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 11, 567 new_bytes, 1, -1)); 568 EXPECT_TRUE(isBytesEqualsCStr(result, "*")); 569} 570 571TEST_F(RuntimeBytesTest, BytesReplaceWithCountZero) { 572 HandleScope scope(thread_); 573 const byte src[] = {'1', '2'}; 574 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 575 576 const byte in[] = {'1'}; 577 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 578 579 const byte out[] = {'*'}; 580 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 581 582 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 1, 583 new_bytes, 1, 0)); 584 EXPECT_TRUE(isBytesEqualsCStr(result, "12")); 585} 586 587TEST_F(RuntimeBytesTest, BytesReplaceWithCountGreaterThanOccurences) { 588 HandleScope scope(thread_); 589 const byte src[] = {'1', '2'}; 590 Bytes bytes(&scope, runtime_->newBytesWithAll(src)); 591 592 const byte in[] = {'1'}; 593 Bytes old_bytes(&scope, runtime_->newBytesWithAll(in)); 594 595 const byte out[] = {'*'}; 596 Bytes new_bytes(&scope, runtime_->newBytesWithAll(out)); 597 598 Bytes result(&scope, runtime_->bytesReplace(thread_, bytes, old_bytes, 1, 599 new_bytes, 1, 9)); 600 EXPECT_TRUE(isBytesEqualsCStr(result, "*2")); 601} 602 603TEST_F(RuntimeBytesTest, Concat) { 604 HandleScope scope(thread_); 605 606 View<byte> foo(reinterpret_cast<const byte*>("foo"), 3); 607 Bytes self(&scope, runtime_->newBytesWithAll(foo)); 608 View<byte> bar(reinterpret_cast<const byte*>("bar"), 3); 609 Bytes other(&scope, runtime_->newBytesWithAll(bar)); 610 Bytes result(&scope, runtime_->bytesConcat(thread_, self, other)); 611 EXPECT_TRUE(isBytesEqualsCStr(result, "foobar")); 612} 613 614TEST_F(RuntimeBytesTest, FromTupleWithSizeReturnsBytesMatchingSize) { 615 HandleScope scope(thread_); 616 Object obj1(&scope, SmallInt::fromWord(42)); 617 Object obj2(&scope, SmallInt::fromWord(123)); 618 Object obj3(&scope, SmallInt::fromWord(456)); 619 Tuple tuple(&scope, runtime_->newTupleWith3(obj1, obj2, obj3)); 620 Object result(&scope, runtime_->bytesFromTuple(thread_, tuple, 2)); 621 const byte bytes[] = {42, 123}; 622 EXPECT_TRUE(isBytesEqualsBytes(result, bytes)); 623} 624 625TEST_F(RuntimeBytesTest, FromTupleWithNonIndexReturnsNone) { 626 HandleScope scope(thread_); 627 Object obj(&scope, runtime_->newFloat(1)); 628 Tuple tuple(&scope, runtime_->newTupleWith1(obj)); 629 EXPECT_EQ(runtime_->bytesFromTuple(thread_, tuple, 1), NoneType::object()); 630} 631 632TEST_F(RuntimeBytesTest, FromTupleWithNegativeIntRaisesValueError) { 633 HandleScope scope(thread_); 634 Object obj(&scope, SmallInt::fromWord(-1)); 635 Tuple tuple(&scope, runtime_->newTupleWith1(obj)); 636 Object result(&scope, runtime_->bytesFromTuple(thread_, tuple, 1)); 637 EXPECT_TRUE(raisedWithStr(*result, LayoutId::kValueError, 638 "bytes must be in range(0, 256)")); 639} 640 641TEST_F(RuntimeBytesTest, FromTupleWithBigIntRaisesValueError) { 642 HandleScope scope(thread_); 643 Object obj(&scope, SmallInt::fromWord(256)); 644 Tuple tuple(&scope, runtime_->newTupleWith1(obj)); 645 Object result(&scope, runtime_->bytesFromTuple(thread_, tuple, 1)); 646 EXPECT_TRUE(raisedWithStr(*result, LayoutId::kValueError, 647 "bytes must be in range(0, 256)")); 648} 649 650TEST_F(RuntimeBytesTest, FromTupleWithIntSubclassReturnsBytes) { 651 ASSERT_FALSE(runFromCStr(runtime_, R"( 652class C(int): pass 653a = C(97) 654b = C(98) 655c = C(99) 656)") 657 .isError()); 658 HandleScope scope(thread_); 659 Object obj1(&scope, mainModuleAt(runtime_, "a")); 660 Object obj2(&scope, mainModuleAt(runtime_, "b")); 661 Object obj3(&scope, mainModuleAt(runtime_, "c")); 662 Tuple tuple(&scope, runtime_->newTupleWith3(obj1, obj2, obj3)); 663 Object result(&scope, runtime_->bytesFromTuple(thread_, tuple, 3)); 664 EXPECT_TRUE(isBytesEqualsCStr(result, "abc")); 665} 666 667TEST_F(RuntimeTest, LayoutAddAttributeReturnsExistingEdgeMatchingName) { 668 ASSERT_FALSE(runFromCStr(runtime_, R"( 669class C: 670 pass 671)") 672 .isError()); 673 674 HandleScope scope(thread_); 675 Type c(&scope, mainModuleAt(runtime_, "C")); 676 Layout instance_layout(&scope, c.instanceLayout()); 677 Str name(&scope, runtime_->newStrFromCStr("attr")); 678 AttributeInfo info; 679 Layout layout(&scope, runtime_->layoutAddAttribute(thread_, instance_layout, 680 name, 0, &info)); 681 682 // Using the same name returns the same layout. 683 EXPECT_EQ(*layout, runtime_->layoutAddAttribute(thread_, instance_layout, 684 name, 0, &info)); 685 686 // A different name creates a new layout. 687 Str different_name(&scope, runtime_->newStrFromCStr("attr_new")); 688 EXPECT_NE(*layout, runtime_->layoutAddAttribute(thread_, instance_layout, 689 different_name, 0, &info)); 690 691 // Using the existing layout as `name` also creates a new layout. 692 EXPECT_NE(*layout, runtime_->layoutAddAttribute(thread_, instance_layout, 693 layout, 0, &info)); 694} 695 696TEST_F(RuntimeListTest, ListGrowth) { 697 HandleScope scope(thread_); 698 List list(&scope, runtime_->newList()); 699 Tuple array1(&scope, runtime_->newMutableTuple(1)); 700 list.setItems(*array1); 701 EXPECT_EQ(array1.length(), 1); 702 runtime_->listEnsureCapacity(thread_, list, 2); 703 Tuple array2(&scope, list.items()); 704 EXPECT_NE(*array1, *array2); 705 EXPECT_GE(array2.length(), 2); 706 707 Tuple array4(&scope, runtime_->newMutableTuple(4)); 708 list.setItems(*array4); 709 runtime_->listEnsureCapacity(thread_, list, 5); 710 Tuple array16(&scope, list.items()); 711 EXPECT_NE(*array4, *array16); 712 EXPECT_EQ(array16.length(), 16); 713 runtime_->listEnsureCapacity(thread_, list, 17); 714 Tuple array24(&scope, list.items()); 715 EXPECT_NE(*array16, *array24); 716 EXPECT_EQ(array24.length(), 24); 717 runtime_->listEnsureCapacity(thread_, list, 40); 718 EXPECT_EQ(list.capacity(), 40); 719} 720 721TEST_F(RuntimeListTest, EmptyListInvariants) { 722 RawList list = List::cast(runtime_->newList()); 723 ASSERT_EQ(list.capacity(), 0); 724 ASSERT_EQ(list.numItems(), 0); 725} 726 727TEST_F(RuntimeListTest, AppendToList) { 728 HandleScope scope(thread_); 729 List list(&scope, runtime_->newList()); 730 731 // Check that list capacity grows by 1.5 732 word expected_capacity[] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 733 16, 16, 16, 16, 16, 16, 16, 24, 24, 734 24, 24, 24, 24, 24, 24, 36}; 735 for (int i = 0; i < 25; i++) { 736 Object value(&scope, SmallInt::fromWord(i)); 737 runtime_->listAdd(thread_, list, value); 738 ASSERT_EQ(list.capacity(), expected_capacity[i]) << i; 739 ASSERT_EQ(list.numItems(), i + 1) << i; 740 } 741 742 // Sanity check list contents 743 for (int i = 0; i < 25; i++) { 744 EXPECT_TRUE(isIntEqualsWord(list.at(i), i)) << i; 745 } 746} 747 748TEST_F(RuntimeTest, NewMutableBytesUninitializedReturnsMutableBytes) { 749 HandleScope scope(thread_); 750 Object result(&scope, runtime_->newMutableBytesUninitialized(3)); 751 ASSERT_TRUE(result.isMutableBytes()); 752 EXPECT_EQ(MutableBytes::cast(*result).length(), 3); 753} 754 755TEST_F(RuntimeTest, MutableBytesFromBytesWithSmallBytes) { 756 HandleScope scope(thread_); 757 758 const byte data[] = {0x11, 0x22, 0x33}; 759 Bytes src(&scope, runtime_->newBytesWithAll(data)); 760 ASSERT_TRUE(src.isSmallBytes()); 761 MutableBytes dst(&scope, runtime_->mutableBytesFromBytes(thread_, src)); 762 EXPECT_EQ(dst.length(), 3); 763 EXPECT_EQ(dst.byteAt(0), 0x11); 764 EXPECT_EQ(dst.byteAt(1), 0x22); 765 EXPECT_EQ(dst.byteAt(2), 0x33); 766} 767 768TEST_F(RuntimeTest, MutableBytesFromBytesWithLargeBytes) { 769 HandleScope scope(thread_); 770 771 MutableBytes mutable_bytes(&scope, runtime_->newMutableBytesUninitialized(8)); 772 mutable_bytes.byteAtPut(0, 0x11); 773 mutable_bytes.byteAtPut(1, 0x22); 774 mutable_bytes.byteAtPut(2, 0x33); 775 mutable_bytes.byteAtPut(3, 0x44); 776 mutable_bytes.byteAtPut(4, 0x55); 777 mutable_bytes.byteAtPut(5, 0x66); 778 mutable_bytes.byteAtPut(6, 0x77); 779 mutable_bytes.byteAtPut(7, 0x88); 780 Bytes src(&scope, mutable_bytes.becomeImmutable()); 781 ASSERT_TRUE(src.isLargeBytes()); 782 MutableBytes dst(&scope, runtime_->mutableBytesFromBytes(thread_, src)); 783 EXPECT_EQ(dst.length(), 8); 784 EXPECT_EQ(dst.byteAt(0), 0x11); 785 EXPECT_EQ(dst.byteAt(1), 0x22); 786 EXPECT_EQ(dst.byteAt(2), 0x33); 787 EXPECT_EQ(dst.byteAt(3), 0x44); 788 EXPECT_EQ(dst.byteAt(4), 0x55); 789 EXPECT_EQ(dst.byteAt(5), 0x66); 790 EXPECT_EQ(dst.byteAt(6), 0x77); 791 EXPECT_EQ(dst.byteAt(7), 0x88); 792} 793 794TEST_F(RuntimeTest, MutableBytesFromBytesWithMutableBytes) { 795 HandleScope scope(thread_); 796 797 MutableBytes mutable_bytes(&scope, runtime_->newMutableBytesUninitialized(3)); 798 mutable_bytes.byteAtPut(0, 0x11); 799 mutable_bytes.byteAtPut(1, 0x22); 800 mutable_bytes.byteAtPut(2, 0x33); 801 Bytes src(&scope, *mutable_bytes); 802 ASSERT_TRUE(src.isMutableBytes()); 803 MutableBytes dst(&scope, runtime_->mutableBytesFromBytes(thread_, src)); 804 EXPECT_EQ(dst.length(), 3); 805 EXPECT_EQ(dst.byteAt(0), 0x11); 806 EXPECT_EQ(dst.byteAt(1), 0x22); 807 EXPECT_EQ(dst.byteAt(2), 0x33); 808} 809 810TEST_F(RuntimeTest, NewBytearray) { 811 HandleScope scope(thread_); 812 813 Bytearray array(&scope, runtime_->newBytearray()); 814 EXPECT_EQ(array.numItems(), 0); 815 EXPECT_EQ(array.capacity(), 0); 816} 817 818TEST_F(RuntimeTest, NewBytes) { 819 HandleScope scope(thread_); 820 821 Bytes len0(&scope, Bytes::empty()); 822 EXPECT_EQ(len0.length(), 0); 823 824 Bytes len3(&scope, runtime_->newBytes(3, 9)); 825 EXPECT_EQ(len3.length(), 3); 826 EXPECT_EQ(len3.byteAt(0), 9); 827 EXPECT_EQ(len3.byteAt(1), 9); 828 EXPECT_EQ(len3.byteAt(2), 9); 829 830 Bytes len254(&scope, runtime_->newBytes(254, 0)); 831 EXPECT_EQ(len254.length(), 254); 832 833 Bytes len255(&scope, runtime_->newBytes(255, 0)); 834 EXPECT_EQ(len255.length(), 255); 835} 836 837TEST_F(RuntimeTest, NewBytesWithAll) { 838 HandleScope scope(thread_); 839 840 Bytes len0(&scope, runtime_->newBytesWithAll(View<byte>(nullptr, 0))); 841 EXPECT_EQ(len0.length(), 0); 842 843 const byte src1[] = {0x42}; 844 Bytes len1(&scope, runtime_->newBytesWithAll(src1)); 845 EXPECT_EQ(len1.length(), 1); 846 EXPECT_EQ(len1.byteAt(0), 0x42); 847 848 const byte src3[] = {0xAA, 0xBB, 0xCC}; 849 Bytes len3(&scope, runtime_->newBytesWithAll(src3)); 850 EXPECT_EQ(len3.length(), 3); 851 EXPECT_EQ(len3.byteAt(0), 0xAA); 852 EXPECT_EQ(len3.byteAt(1), 0xBB); 853 EXPECT_EQ(len3.byteAt(2), 0xCC); 854} 855 856TEST_F(RuntimeTest, NewMemoryViewFromCPtrCreatesMemoryView) { 857 HandleScope scope(thread_); 858 word length = 5; 859 std::unique_ptr<byte[]> memory(new byte[length]); 860 for (word i = 0; i < length; i++) { 861 memory[i] = i; 862 } 863 Object none(&scope, NoneType::object()); 864 MemoryView view(&scope, 865 runtime_->newMemoryViewFromCPtr(thread_, none, memory.get(), 866 length, ReadOnly::ReadOnly)); 867 Pointer pointer(&scope, view.buffer()); 868 EXPECT_EQ(view.length(), length); 869 byte* ptr = reinterpret_cast<byte*>(pointer.cptr()); 870 EXPECT_EQ(ptr[0], 0); 871 EXPECT_EQ(ptr[1], 1); 872 EXPECT_EQ(ptr[2], 2); 873 EXPECT_EQ(ptr[3], 3); 874 EXPECT_EQ(ptr[4], 4); 875} 876 877TEST_F(RuntimeTest, NewMmapReturnsEmptyMmap) { 878 HandleScope scope(thread_); 879 Object obj(&scope, runtime_->newMmap()); 880 ASSERT_TRUE(obj.isMmap()); 881 Mmap mmap_obj(&scope, *obj); 882 EXPECT_EQ(mmap_obj.isReadable(), false); 883 EXPECT_EQ(mmap_obj.isWritable(), false); 884 EXPECT_EQ(mmap_obj.isCopyOnWrite(), false); 885 EXPECT_EQ(mmap_obj.data(), NoneType::object()); 886 EXPECT_EQ(mmap_obj.fd(), NoneType::object()); 887} 888 889TEST_F(RuntimeTest, LargeBytesSizeRoundedUpToPointerSizeMultiple) { 890 HandleScope scope(thread_); 891 892 LargeBytes len10(&scope, runtime_->newBytes(10, 0)); 893 EXPECT_EQ(len10.size(), roundAllocationSize(kPointerSize + 10)); 894 895 LargeBytes len254(&scope, runtime_->newBytes(254, 0)); 896 EXPECT_EQ(len254.size(), roundAllocationSize(kPointerSize + 254)); 897 898 LargeBytes len255(&scope, runtime_->newBytes(255, 0)); 899 EXPECT_EQ(len255.size(), roundAllocationSize(kPointerSize * 2 + 255)); 900} 901 902TEST_F(RuntimeTest, NewPointerReturnsEmptyPointer) { 903 HandleScope scope(thread_); 904 Object obj(&scope, runtime_->newPointer(nullptr, -1)); 905 ASSERT_TRUE(obj.isPointer()); 906 Pointer pointer(&scope, *obj); 907 EXPECT_EQ(pointer.cptr(), nullptr); 908 EXPECT_EQ(pointer.length(), -1); 909} 910 911TEST_F(RuntimeTest, NewStr) { 912 HandleScope scope(thread_); 913 Str empty0(&scope, runtime_->newStrWithAll(View<byte>(nullptr, 0))); 914 ASSERT_TRUE(empty0.isSmallStr()); 915 EXPECT_EQ(empty0.length(), 0); 916 917 Str empty1(&scope, runtime_->newStrWithAll(View<byte>(nullptr, 0))); 918 ASSERT_TRUE(empty1.isSmallStr()); 919 EXPECT_EQ(*empty0, *empty1); 920 921 Str empty2(&scope, runtime_->newStrFromCStr("\0")); 922 ASSERT_TRUE(empty2.isSmallStr()); 923 EXPECT_EQ(*empty0, *empty2); 924 925 const byte bytes1[1] = {0}; 926 Str s1(&scope, runtime_->newStrWithAll(bytes1)); 927 ASSERT_TRUE(s1.isSmallStr()); 928 EXPECT_EQ(s1.length(), 1); 929 930 const byte bytes254[254] = {0}; 931 Str s254(&scope, runtime_->newStrWithAll(bytes254)); 932 EXPECT_EQ(s254.length(), 254); 933 ASSERT_TRUE(s254.isLargeStr()); 934 EXPECT_EQ(HeapObject::cast(*s254).size(), 935 roundAllocationSize(kPointerSize + 254)); 936 937 const byte bytes255[255] = {0}; 938 Str s255(&scope, runtime_->newStrWithAll(bytes255)); 939 EXPECT_EQ(s255.length(), 255); 940 ASSERT_TRUE(s255.isLargeStr()); 941 EXPECT_EQ(HeapObject::cast(*s255).size(), 942 roundAllocationSize(kPointerSize * 2 + 255)); 943 944 const byte bytes300[300] = {0}; 945 Str s300(&scope, runtime_->newStrWithAll(bytes300)); 946 ASSERT_EQ(s300.length(), 300); 947} 948 949TEST_F(RuntimeTest, NewStrFromFmtFormatsWord) { 950 word x = 5; 951 HandleScope scope(thread_); 952 Object result(&scope, runtime_->newStrFromFmt("hello %w world", x)); 953 EXPECT_TRUE(isStrEqualsCStr(*result, "hello 5 world")); 954} 955 956TEST_F(RuntimeTest, NewStrFromFmtWithStrArg) { 957 HandleScope scope(thread_); 958 959 Object str(&scope, runtime_->newStrFromCStr("hello")); 960 Object result(&scope, runtime_->newStrFromFmt("%S", &str)); 961 EXPECT_EQ(*result, str); 962} 963 964TEST_F(RuntimeTest, NewStrFromFmtWithStrSubclassArg) { 965 HandleScope scope(thread_); 966 ASSERT_FALSE(runFromCStr(runtime_, R"( 967class C(str): 968 pass 969value = C("foo") 970)") 971 .isError()); 972 Object value(&scope, mainModuleAt(runtime_, "value")); 973 Object result(&scope, runtime_->newStrFromFmt("hello %S", &value)); 974 EXPECT_TRUE(isStrEqualsCStr(*result, "hello foo")); 975} 976 977TEST_F(RuntimeStrTest, NewStrFromFmtFormatsFunctionName) { 978 HandleScope scope(thread_); 979 Function function(&scope, newEmptyFunction()); 980 function.setQualname(runtime_->newStrFromCStr("foo")); 981 Object str(&scope, runtime_->newStrFromFmt("hello %F", &function)); 982 EXPECT_TRUE(isStrEqualsCStr(*str, "hello foo")); 983} 984 985TEST_F(RuntimeStrTest, NewStrFromFmtFormatsTypeName) { 986 HandleScope scope(thread_); 987 Object obj(&scope, runtime_->newDict()); 988 Object str(&scope, runtime_->newStrFromFmt("hello %T", &obj)); 989 EXPECT_TRUE(isStrEqualsCStr(*str, "hello dict")); 990} 991 992TEST_F(RuntimeStrTest, NewStrFromFmtFormatsSymbolid) { 993 HandleScope scope(thread_); 994 Object str(&scope, runtime_->newStrFromFmt("hello %Y", ID(dict))); 995 EXPECT_TRUE(isStrEqualsCStr(*str, "hello dict")); 996} 997 998TEST_F(RuntimeStrTest, NewStrFromFmtFormatsASCIIChar) { 999 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%c'", 124), "'|'")); 1000} 1001 1002TEST_F(RuntimeStrTest, NewStrFromFmtFormatsNonASCIIAsReplacementChar) { 1003 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%c'", kMaxASCII + 1), 1004 "'\xef\xbf\xbd'")); 1005} 1006 1007TEST_F(RuntimeStrTest, NewStrFromFmtFormatsCodePoint) { 1008 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%C'", 124), "'|'")); 1009 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%C'", 0x1F40D), 1010 "'\xf0\x9f\x90\x8d'")); 1011} 1012 1013TEST_F(RuntimeStrTest, NewStrFromFormatFormatsString) { 1014 EXPECT_TRUE( 1015 isStrEqualsCStr(runtime_->newStrFromFmt("'%s'", "hello"), "'hello'")); 1016} 1017 1018TEST_F(RuntimeStrTest, NewStrFromFormatFormatsInt) { 1019 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%d'", -321), "'-321'")); 1020} 1021 1022TEST_F(RuntimeStrTest, NewStrFromFormatFormatsFloat) { 1023 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%g'", 3.5), "'3.5'")); 1024} 1025 1026TEST_F(RuntimeStrTest, NewStrFromFormatFormatsHexadecimalInt) { 1027 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%x'", 0x2AB), "'2ab'")); 1028} 1029 1030TEST_F(RuntimeStrTest, NewStrFromFormatFormatsPercent) { 1031 EXPECT_TRUE(isStrEqualsCStr(runtime_->newStrFromFmt("'%%'"), "'%'")); 1032} 1033 1034TEST_F(RuntimeStrTest, NewStrFromFmtFormatsReplacesNonUnicodeWithReplacement) { 1035 EXPECT_TRUE( 1036 isStrEqualsCStr(runtime_->newStrFromFmt("'%C'", -1), "'\xef\xbf\xbd'")); 1037} 1038 1039TEST_F(RuntimeStrTest, NewStrWithAll) { 1040 HandleScope scope(thread_); 1041 1042 Str str0(&scope, runtime_->newStrWithAll(View<byte>(nullptr, 0))); 1043 EXPECT_EQ(str0.length(), 0); 1044 EXPECT_TRUE(str0.equalsCStr("")); 1045 1046 const byte bytes3[] = {'A', 'B', 'C'}; 1047 Str str3(&scope, runtime_->newStrWithAll(bytes3)); 1048 EXPECT_EQ(str3.length(), 3); 1049 EXPECT_TRUE(str3.equalsCStr("ABC")); 1050 1051 const byte bytes10[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}; 1052 Str str10(&scope, runtime_->newStrWithAll(bytes10)); 1053 EXPECT_EQ(str10.length(), 10); 1054 EXPECT_TRUE(str10.equalsCStr("ABCDEFGHIJ")); 1055} 1056 1057TEST_F(RuntimeStrTest, NewStrFromUTF32WithZeroSizeReturnsEmpty) { 1058 HandleScope scope(thread_); 1059 int32_t str[2] = {'a', 's'}; 1060 Str empty(&scope, runtime_->newStrFromUTF32(View<int32_t>(str, 0))); 1061 EXPECT_EQ(empty.length(), 0); 1062} 1063 1064TEST_F(RuntimeStrTest, NewStrFromUTF32WithLargeASCIIStringReturnsString) { 1065 HandleScope scope(thread_); 1066 int32_t str[7] = {'a', 'b', 'c', '1', '2', '3', '-'}; 1067 Str unicode(&scope, runtime_->newStrFromUTF32(View<int32_t>(str, 7))); 1068 EXPECT_EQ(unicode.length(), 7); 1069 EXPECT_TRUE(unicode.equalsCStr("abc123-")); 1070} 1071 1072TEST_F(RuntimeStrTest, NewStrFromUTF32WithSmallASCIIStringReturnsString) { 1073 HandleScope scope(thread_); 1074 int32_t str[7] = {'a', 'b'}; 1075 Str unicode(&scope, runtime_->newStrFromUTF32(View<int32_t>(str, 2))); 1076 EXPECT_EQ(unicode.length(), 2); 1077 EXPECT_TRUE(unicode.equalsCStr("ab")); 1078} 1079 1080TEST_F(RuntimeStrTest, NewStrFromUTF32WithSmallNonASCIIReturnsString) { 1081 HandleScope scope(thread_); 1082 const int32_t codepoints[] = {0xC4}; 1083 Str unicode(&scope, runtime_->newStrFromUTF32(codepoints)); 1084 EXPECT_TRUE(unicode.equals(Str::cast(SmallStr::fromCodePoint(0xC4)))); 1085} 1086 1087TEST_F(RuntimeStrTest, NewStrFromUTF32WithLargeNonASCIIReturnsString) { 1088 HandleScope scope(thread_); 1089 const int32_t codepoints[] = {0x3041, ' ', 'c', 0xF6, 1090 0xF6, 'l', ' ', 0x1F192}; 1091 Str unicode(&scope, runtime_->newStrFromUTF32(codepoints)); 1092 Str expected(&scope, runtime_->newStrFromCStr( 1093 "\xe3\x81\x81 c\xC3\xB6\xC3\xB6l \xF0\x9F\x86\x92")); 1094 EXPECT_TRUE(unicode.equals(*expected)); 1095} 1096 1097TEST_F(RuntimeTest, HashBools) { 1098 // In CPython, False hashes to 0 and True hashes to 1. 1099 EXPECT_EQ(runtime_->hash(Bool::falseObj()), 0); 1100 EXPECT_EQ(runtime_->hash(Bool::trueObj()), 1); 1101} 1102 1103TEST_F(RuntimeTest, HashLargeBytes) { 1104 HandleScope scope(thread_); 1105 1106 // LargeBytes have their hash codes computed lazily. 1107 const byte src1[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 1108 LargeBytes arr1(&scope, runtime_->newBytesWithAll(src1)); 1109 EXPECT_EQ(arr1.header().hashCode(), 0); 1110 word hash1 = runtime_->hash(*arr1); 1111 EXPECT_NE(arr1.header().hashCode(), 0); 1112 EXPECT_EQ(arr1.header().hashCode(), hash1); 1113 1114 word code1 = runtime_->bytesHash(src1); 1115 EXPECT_EQ(code1, hash1); 1116 1117 // LargeBytes with different values should (ideally) hash differently. 1118 const byte src2[] = {0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1}; 1119 LargeBytes arr2(&scope, runtime_->newBytesWithAll(src2)); 1120 word hash2 = runtime_->hash(*arr2); 1121 EXPECT_NE(hash1, hash2); 1122 1123 word code2 = runtime_->bytesHash(src2); 1124 EXPECT_EQ(code2, hash2); 1125 1126 // LargeBytes with the same value should hash the same. 1127 LargeBytes arr3(&scope, runtime_->newBytesWithAll(src1)); 1128 EXPECT_NE(arr3, arr1); 1129 word hash3 = runtime_->hash(*arr3); 1130 EXPECT_EQ(hash1, hash3); 1131} 1132 1133TEST_F(RuntimeTest, HashSmallInts) { 1134 // In CPython, Ints hash to themselves. 1135 EXPECT_EQ(runtime_->hash(SmallInt::fromWord(123)), 123); 1136 EXPECT_EQ(runtime_->hash(SmallInt::fromWord(456)), 456); 1137 EXPECT_EQ(runtime_->hash(SmallInt::fromWord(-1)), -2); 1138} 1139 1140TEST_F(RuntimeTest, HashSingletonImmediates) { 1141 // In CPython, these objects hash to arbitrary values. 1142 word none_value = NoneType::object().raw(); 1143 EXPECT_EQ(runtime_->hash(NoneType::object()), none_value); 1144 1145 word error_value = Error::error().raw(); 1146 EXPECT_EQ(runtime_->hash(Error::error()), error_value); 1147} 1148 1149TEST_F(RuntimeTest, HashStr) { 1150 HandleScope scope(thread_); 1151 1152 // LargeStr instances have their hash codes computed lazily. 1153 Object str1(&scope, runtime_->newStrFromCStr("testing 123")); 1154 EXPECT_EQ(HeapObject::cast(*str1).header().hashCode(), 0); 1155 word hash1 = runtime_->hash(*str1); 1156 EXPECT_NE(HeapObject::cast(*str1).header().hashCode(), 0); 1157 EXPECT_EQ(HeapObject::cast(*str1).header().hashCode(), hash1); 1158 1159 // Str with different values should (ideally) hash differently. 1160 Str str2(&scope, runtime_->newStrFromCStr("321 testing")); 1161 word hash2 = runtime_->hash(*str2); 1162 EXPECT_NE(hash1, hash2); 1163 1164 // Strings with the same value should hash the same. 1165 Str str3(&scope, runtime_->newStrFromCStr("testing 123")); 1166 word hash3 = runtime_->hash(*str3); 1167 EXPECT_EQ(hash1, hash3); 1168} 1169 1170TEST(RuntimeTestNoFixture, InitializeRandomSetsRandomRandomRNGSeed) { 1171 word heap_size = 32 * kMiB; 1172 std::unique_ptr<Runtime> runtime0(new Runtime( 1173 heap_size, createCppInterpreter(), randomState(), StdioState::kBuffered)); 1174 uword r0 = runtime0->random(); 1175 std::unique_ptr<Runtime> runtime1(new Runtime( 1176 heap_size, createCppInterpreter(), randomState(), StdioState::kBuffered)); 1177 uword r1 = runtime1->random(); 1178 std::unique_ptr<Runtime> runtime2(new Runtime( 1179 heap_size, createCppInterpreter(), randomState(), StdioState::kBuffered)); 1180 uword r2 = runtime2->random(); 1181 // Having 3 random numbers be the same will practically never happen. 1182 EXPECT_TRUE(r0 != r1 || r0 != r2); 1183} 1184 1185TEST(RuntimeTestNoFixture, 1186 InitializeRandomWithPyroHashSeedEnvVarSetsDeterministicRNGSeed) { 1187 word heap_size = 32 * kMiB; 1188 RandomState seed = randomStateFromSeed(42); 1189 std::unique_ptr<Runtime> runtime0(new Runtime( 1190 heap_size, createCppInterpreter(), seed, StdioState::kBuffered)); 1191 uword r0_a = runtime0->random(); 1192 uword r0_b = runtime0->random(); 1193 EXPECT_NE(r0_a, r0_b); 1194 std::unique_ptr<Runtime> runtime1(new Runtime( 1195 heap_size, createCppInterpreter(), seed, StdioState::kBuffered)); 1196 uword r1_a = runtime1->random(); 1197 uword r1_b = runtime1->random(); 1198 EXPECT_EQ(r0_a, r1_a); 1199 EXPECT_EQ(r0_b, r1_b); 1200} 1201 1202TEST_F(RuntimeTest, TypeDictOnlyLayoutReturnsLayoutWithDictOverflow) { 1203 ASSERT_FALSE(runFromCStr(runtime_, R"( 1204class C: pass 1205 1206c = C() 1207)") 1208 .isError()); 1209 HandleScope scope(thread_); 1210 Type c(&scope, mainModuleAt(runtime_, "C")); 1211 Layout layout(&scope, c.instanceLayout()); 1212 word in_object_attributes_length = 1213 Tuple::cast(layout.inObjectAttributes()).length(); 1214 ASSERT_TRUE(!layout.hasDictOverflow()); 1215 Layout new_layout(&scope, runtime_->typeDictOnlyLayout( 1216 thread_, c, in_object_attributes_length)); 1217 EXPECT_NE(layout, new_layout); 1218 EXPECT_TRUE(new_layout.hasDictOverflow()); 1219 EXPECT_EQ(layout.describedType(), new_layout.describedType()); 1220 1221 Layout new_layout2(&scope, runtime_->typeDictOnlyLayout( 1222 thread_, c, in_object_attributes_length)); 1223 EXPECT_NE(layout, new_layout2); 1224 EXPECT_TRUE(new_layout2.hasDictOverflow()); 1225 EXPECT_EQ(layout.describedType(), new_layout2.describedType()); 1226 1227 EXPECT_EQ(*new_layout, *new_layout2); 1228} 1229 1230TEST_F( 1231 RuntimeTest, 1232 TypeDictOnlyLayoutWithDunderClassAssignedInstanceReturnsLayoutBasedOnInObjectAttributesLength) { 1233 ASSERT_FALSE(runFromCStr(runtime_, R"( 1234class C: 1235 def __init__(self): 1236 self.x = 10 1237 self.y = 20 1238)") 1239 .isError()); 1240 HandleScope scope(thread_); 1241 Type type_c(&scope, mainModuleAt(runtime_, "C")); 1242 1243 Layout new_layout(&scope, runtime_->typeDictOnlyLayout(thread_, type_c, 3)); 1244 EXPECT_TRUE(new_layout.hasDictOverflow()); 1245 EXPECT_EQ(new_layout.dictOverflowOffset(), 24); 1246 EXPECT_EQ(new_layout.describedType(), *type_c); 1247 1248 // Using the same value of `in_object_attributes_length` returns the same 1249 // layout. 1250 Layout new_layout2(&scope, runtime_->typeDictOnlyLayout(thread_, type_c, 3)); 1251 EXPECT_EQ(new_layout, new_layout2); 1252 1253 // Create a new layout for the new value of `in_object_attributes_length`. 1254 Layout new_layout3(&scope, 1255 runtime_->typeDictOnlyLayout(thread_, type_c, 3 + 1)); 1256 EXPECT_NE(new_layout, new_layout3); 1257} 1258 1259TEST_F(RuntimeTest, HashCodeSizeCheck) { 1260 // Conspire based on knowledge of the random number generated to 1261 // create a high-magnitude result from Runtime::random 1262 // which is truncated to 0 for storage in the header and 1263 // replaced with "1" so no hash code has value 0. 1264 RandomState seed = randomStateFromSeed(0); 1265 uint64_t high = uword{1} << (8 * sizeof(uword) - 1); 1266 seed.state[0] = 0; 1267 seed.state[1] = high; 1268 1269 // Verify that our crafted random seed does indeed produce the number 1270 // we expect. 1271 runtime_->setRandomState(seed); 1272 EXPECT_EQ(runtime_->random(), high); 1273 1274 // Verify that large-magnitude random numbers are properly 1275 // truncated to something which fits in a SmallInt 1276 runtime_->setRandomState(seed); 1277 HandleScope scope(thread_); 1278 Layout layout(&scope, runtime_->layoutAt(LayoutId::kObject)); 1279 Object object(&scope, runtime_->newInstance(layout)); 1280 EXPECT_EQ(runtime_->hash(*object), 1); 1281} 1282 1283TEST_F(RuntimeTest, NewCapacity) { 1284 // ensure initial capacity 1285 EXPECT_GE(Runtime::newCapacity(1, 0), 16); 1286 1287 // grow by factor of 1.5, rounding down 1288 EXPECT_EQ(Runtime::newCapacity(20, 22), 30); 1289 EXPECT_EQ(Runtime::newCapacity(64, 77), 96); 1290 EXPECT_EQ(Runtime::newCapacity(25, 30), 37); 1291 1292 // ensure growth 1293 EXPECT_EQ(Runtime::newCapacity(20, 17), 30); 1294 EXPECT_EQ(Runtime::newCapacity(20, 20), 30); 1295 1296 // if factor of 1.5 is insufficient, grow exactly to minimum capacity 1297 EXPECT_EQ(Runtime::newCapacity(20, 40), 40); 1298 EXPECT_EQ(Runtime::newCapacity(20, 70), 70); 1299 1300 // capacity has ceiling of SmallInt::kMaxValue 1301 EXPECT_EQ(Runtime::newCapacity(SmallInt::kMaxValue - 1, SmallInt::kMaxValue), 1302 SmallInt::kMaxValue); 1303} 1304 1305TEST_F(RuntimeTest, InternLargeStr) { 1306 HandleScope scope(thread_); 1307 1308 // Creating an ordinary large string should not affect on the intern table. 1309 Str str1(&scope, runtime_->newStrFromCStr("hello, world")); 1310 ASSERT_TRUE(str1.isLargeStr()); 1311 EXPECT_FALSE(runtime_->isInternedStr(thread_, str1)); 1312 1313 // Interning the string should add it to the intern table and increase the 1314 // size of the intern table by one. 1315 Object sym1(&scope, Runtime::internStr(thread_, str1)); 1316 EXPECT_EQ(*sym1, *str1); 1317 EXPECT_TRUE(runtime_->isInternedStr(thread_, str1)); 1318 1319 Str str2(&scope, runtime_->newStrFromCStr("goodbye, world")); 1320 ASSERT_TRUE(str2.isLargeStr()); 1321 EXPECT_NE(*str1, *str2); 1322 1323 // Intern another string and make sure we get it back (as opposed to the 1324 // previously interned string). 1325 Object sym2(&scope, Runtime::internStr(thread_, str2)); 1326 EXPECT_EQ(*sym2, *str2); 1327 EXPECT_NE(*sym1, *sym2); 1328 1329 // Create a unique copy of a previously created string. 1330 Str str3(&scope, runtime_->newStrFromCStr("hello, world")); 1331 ASSERT_TRUE(str3.isLargeStr()); 1332 EXPECT_NE(*str1, *str3); 1333 EXPECT_FALSE(runtime_->isInternedStr(thread_, str3)); 1334 1335 // Interning a duplicate string should not affecct the intern table. 1336 Object sym3(&scope, Runtime::internStr(thread_, str3)); 1337 EXPECT_NE(*sym3, *str3); 1338 EXPECT_EQ(*sym3, *sym1); 1339} 1340 1341TEST_F(RuntimeTest, InternSmallStr) { 1342 HandleScope scope(thread_); 1343 1344 // Creating a small string should not affect the intern table. 1345 Str str(&scope, runtime_->newStrFromCStr("a")); 1346 ASSERT_TRUE(str.isSmallStr()); 1347 1348 // Interning a small string should have no affect on the intern table. 1349 Object sym(&scope, Runtime::internStr(thread_, str)); 1350 EXPECT_TRUE(sym.isSmallStr()); 1351 EXPECT_EQ(*sym, *str); 1352 EXPECT_TRUE(runtime_->isInternedStr(thread_, str)); 1353} 1354 1355TEST_F(RuntimeTest, InternCStr) { 1356 HandleScope scope(thread_); 1357 1358 Object sym(&scope, Runtime::internStrFromCStr(thread_, "hello, world")); 1359 EXPECT_TRUE(sym.isStr()); 1360 EXPECT_TRUE(runtime_->isInternedStr(thread_, sym)); 1361} 1362 1363TEST_F(RuntimeTest, IsInternWithInternedStrReturnsTrue) { 1364 HandleScope scope(thread_); 1365 Object str(&scope, Runtime::internStrFromCStr(thread_, "hello world")); 1366 EXPECT_TRUE(runtime_->isInternedStr(thread_, str)); 1367} 1368 1369TEST_F(RuntimeTest, IsInternWithStrReturnsFalse) { 1370 HandleScope scope(thread_); 1371 Str str(&scope, runtime_->newStrFromCStr("hello world")); 1372 EXPECT_FALSE(runtime_->isInternedStr(thread_, str)); 1373} 1374 1375TEST_F(RuntimeTest, CollectAttributes) { 1376 HandleScope scope(thread_); 1377 1378 Str foo(&scope, runtime_->newStrFromCStr("foo")); 1379 Str bar(&scope, runtime_->newStrFromCStr("bar")); 1380 Str baz(&scope, runtime_->newStrFromCStr("baz")); 1381 Tuple names(&scope, runtime_->newTupleWith3(foo, bar, baz)); 1382 1383 Object obj1(&scope, SmallInt::fromWord(100)); 1384 Object obj2(&scope, SmallInt::fromWord(200)); 1385 Object obj3(&scope, SmallInt::fromWord(300)); 1386 Object obj4(&scope, NoneType::object()); 1387 Tuple consts(&scope, runtime_->newTupleWith4(obj1, obj2, obj3, obj4)); 1388 1389 Locals locals; 1390 locals.argcount = 1; 1391 1392 // Bytecode for the snippet: 1393 // 1394 // def __init__(self): 1395 // self.foo = 100 1396 // self.foo = 200 1397 // 1398 // The assignment to self.foo is intentionally duplicated to ensure that we 1399 // only record a single attribute name. 1400 const byte bytecode0[] = {LOAD_CONST, 0, LOAD_FAST, 0, STORE_ATTR, 0, 1401 LOAD_CONST, 1, LOAD_FAST, 0, STORE_ATTR, 0, 1402 RETURN_VALUE, 0}; 1403 Code code0(&scope, newCodeWithBytesConstsNamesLocals(bytecode0, consts, names, 1404 &locals)); 1405 1406 Dict attributes(&scope, runtime_->newDict()); 1407 runtime_->collectAttributes(code0, attributes); 1408 1409 // We should have collected a single attribute: 'foo' 1410 EXPECT_EQ(attributes.numItems(), 1); 1411 1412 // Check that we collected 'foo' 1413 Object result(&scope, dictAtByStr(thread_, attributes, foo)); 1414 ASSERT_TRUE(result.isStr()); 1415 EXPECT_TRUE(Str::cast(*result).equals(*foo)); 1416 1417 // Bytecode for the snippet: 1418 // 1419 // def __init__(self): 1420 // self.bar = 200 1421 // self.baz = 300 1422 const byte bytecode1[] = {LOAD_CONST, 1, LOAD_FAST, 0, STORE_ATTR, 1, 1423 LOAD_CONST, 2, LOAD_FAST, 0, STORE_ATTR, 2, 1424 RETURN_VALUE, 0}; 1425 Code code1(&scope, newCodeWithBytesConstsNamesLocals(bytecode1, consts, names, 1426 &locals)); 1427 runtime_->collectAttributes(code1, attributes); 1428 1429 // We should have collected a two more attributes: 'bar' and 'baz' 1430 EXPECT_EQ(attributes.numItems(), 3); 1431 1432 // Check that we collected 'bar' 1433 result = dictAtByStr(thread_, attributes, bar); 1434 ASSERT_TRUE(result.isStr()); 1435 EXPECT_TRUE(Str::cast(*result).equals(*bar)); 1436 1437 // Check that we collected 'baz' 1438 result = dictAtByStr(thread_, attributes, baz); 1439 ASSERT_TRUE(result.isStr()); 1440 EXPECT_TRUE(Str::cast(*result).equals(*baz)); 1441 1442 // Bytecode for the snippet: 1443 // 1444 // def __init__(self): 1445 // self.foo = 100 1446 // 1447 // Manually add duplicate and useless EXTENDED_ARG intentionally to ensure 1448 // that collectAttributes can handle it. 1449 const byte bytecode2[] = {LOAD_CONST, 0, EXTENDED_ARG, 0, EXTENDED_ARG, 0, 1450 EXTENDED_ARG, 0, LOAD_FAST, 0, STORE_ATTR, 0, 1451 RETURN_VALUE, 0}; 1452 Code code2(&scope, newCodeWithBytesConstsNamesLocals(bytecode2, consts, names, 1453 &locals)); 1454 1455 attributes = runtime_->newDict(); 1456 runtime_->collectAttributes(code2, attributes); 1457 1458 // We should have collected a single attribute: 'foo' 1459 EXPECT_EQ(attributes.numItems(), 1); 1460 1461 // Check that we collected 'foo' 1462 result = dictAtByStr(thread_, attributes, foo); 1463 ASSERT_TRUE(result.isStr()); 1464 EXPECT_TRUE(Str::cast(*result).equals(*foo)); 1465} 1466 1467TEST_F(RuntimeTest, CollectAttributesWithExtendedArgAccumulates) { 1468 HandleScope scope(thread_); 1469 1470 Str foo(&scope, runtime_->newStrFromCStr("foo")); 1471 Str bar(&scope, runtime_->newStrFromCStr("bar")); 1472 Tuple names(&scope, runtime_->newTupleWith2(foo, bar)); 1473 1474 Object obj(&scope, NoneType::object()); 1475 Tuple consts(&scope, runtime_->newTupleWith1(obj)); 1476 1477 Locals locals; 1478 locals.argcount = 1; 1479 locals.varcount = 300; 1480 1481 // Bytecode for the snippet: 1482 // 1483 // def __init__(self): 1484 // self.foo = None 1485 const byte bytecode[] = {LOAD_CONST, 0, EXTENDED_ARG, 1, LOAD_FAST, 0, 1486 STORE_ATTR, 1, LOAD_CONST, 0, RETURN_VALUE, 0}; 1487 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names, 1488 &locals)); 1489 1490 Dict attributes(&scope, runtime_->newDict()); 1491 runtime_->collectAttributes(code, attributes); 1492 1493 // We should have collected no attributes because EXTENDED_ARG makes 0x0100 1494 EXPECT_EQ(attributes.numItems(), 0); 1495} 1496 1497TEST_F(RuntimeTest, GetTypeConstructor) { 1498 HandleScope scope(thread_); 1499 Type type(&scope, runtime_->newType()); 1500 1501 EXPECT_TRUE(runtime_->classConstructor(type).isErrorNotFound()); 1502 1503 Object func(&scope, makeTestFunction()); 1504 typeAtPutById(thread_, type, ID(__init__), func); 1505 1506 EXPECT_EQ(runtime_->classConstructor(type), *func); 1507} 1508 1509TEST_F(RuntimeTest, NewInstanceEmptyClass) { 1510 HandleScope scope(thread_); 1511 1512 ASSERT_FALSE(runFromCStr(runtime_, "class MyEmptyClass: pass").isError()); 1513 1514 Type type(&scope, mainModuleAt(runtime_, "MyEmptyClass")); 1515 Layout layout(&scope, type.instanceLayout()); 1516 EXPECT_EQ(layout.instanceSize(), 1 * kPointerSize); 1517 1518 Type cls(&scope, layout.describedType()); 1519 EXPECT_TRUE(isStrEqualsCStr(cls.name(), "MyEmptyClass")); 1520 1521 Instance instance(&scope, runtime_->newInstance(layout)); 1522 EXPECT_TRUE(instance.isInstance()); 1523 EXPECT_EQ(instance.header().layoutId(), layout.id()); 1524} 1525 1526TEST_F(RuntimeTest, NewInstanceManyAttributes) { 1527 HandleScope scope(thread_); 1528 1529 const char* src = R"( 1530class MyTypeWithAttributes(): 1531 def __init__(self): 1532 self.a = 1 1533 self.b = 2 1534 self.c = 3 1535)"; 1536 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 1537 1538 Type type(&scope, mainModuleAt(runtime_, "MyTypeWithAttributes")); 1539 Layout layout(&scope, type.instanceLayout()); 1540 ASSERT_EQ(layout.instanceSize(), 4 * kPointerSize); 1541 1542 Type cls(&scope, layout.describedType()); 1543 EXPECT_TRUE(isStrEqualsCStr(cls.name(), "MyTypeWithAttributes")); 1544 1545 Instance instance(&scope, runtime_->newInstance(layout)); 1546 EXPECT_TRUE(instance.isInstance()); 1547 EXPECT_EQ(instance.header().layoutId(), layout.id()); 1548} 1549 1550TEST_F(RuntimeTest, VerifySymbols) { 1551 HandleScope scope(thread_); 1552 Symbols* symbols = runtime_->symbols(); 1553 Str value(&scope, Str::empty()); 1554 for (int i = 0; i < static_cast<int>(SymbolId::kMaxId); i++) { 1555 SymbolId id = static_cast<SymbolId>(i); 1556 value = symbols->at(id); 1557 const char* expected = Symbols::predefinedSymbolAt(id); 1558 EXPECT_TRUE(runtime_->isInternedStr(thread_, value)) 1559 << "at symbol " << expected; 1560 EXPECT_TRUE(Str::cast(*value).equalsCStr(expected)) 1561 << "Incorrect symbol value for " << expected; 1562 } 1563} 1564 1565static RawStr className(Runtime* runtime, RawObject o) { 1566 auto cls = Type::cast(runtime->typeOf(o)); 1567 auto name = Str::cast(cls.name()); 1568 return name; 1569} 1570 1571TEST_F(RuntimeTest, TypeIds) { 1572 EXPECT_TRUE(isStrEqualsCStr(className(runtime_, Bool::trueObj()), "bool")); 1573 EXPECT_TRUE( 1574 isStrEqualsCStr(className(runtime_, NoneType::object()), "NoneType")); 1575 EXPECT_TRUE(isStrEqualsCStr( 1576 className(runtime_, runtime_->newStrFromCStr("abc")), "str")); 1577 for (word i = 0; i < 16; i++) { 1578 EXPECT_TRUE( 1579 isStrEqualsCStr(className(runtime_, SmallInt::fromWord(i)), "int")) 1580 << i; 1581 } 1582} 1583 1584TEST_F(RuntimeTest, CallRunTwice) { 1585 ASSERT_FALSE(runFromCStr(runtime_, "x = 42").isError()); 1586 ASSERT_FALSE(runFromCStr(runtime_, "y = 1764").isError()); 1587 1588 HandleScope scope(thread_); 1589 Object x(&scope, mainModuleAt(runtime_, "x")); 1590 EXPECT_TRUE(isIntEqualsWord(*x, 42)); 1591 Object y(&scope, mainModuleAt(runtime_, "y")); 1592 EXPECT_TRUE(isIntEqualsWord(*y, 1764)); 1593} 1594 1595TEST_F(RuntimeStrTest, StrConcat) { 1596 HandleScope scope(thread_); 1597 1598 Str str1(&scope, runtime_->newStrFromCStr("abc")); 1599 Str str2(&scope, runtime_->newStrFromCStr("def")); 1600 1601 // Large strings. 1602 Str str3(&scope, runtime_->newStrFromCStr("0123456789abcdef")); 1603 Str str4(&scope, runtime_->newStrFromCStr("fedbca9876543210")); 1604 1605 Object concat12(&scope, runtime_->strConcat(thread_, str1, str2)); 1606 Object concat34(&scope, runtime_->strConcat(thread_, str3, str4)); 1607 1608 Object concat13(&scope, runtime_->strConcat(thread_, str1, str3)); 1609 Object concat31(&scope, runtime_->strConcat(thread_, str3, str1)); 1610 1611 // Test that we don't make large strings when small srings would suffice. 1612 EXPECT_TRUE(isStrEqualsCStr(*concat12, "abcdef")); 1613 EXPECT_TRUE(isStrEqualsCStr(*concat34, "0123456789abcdeffedbca9876543210")); 1614 EXPECT_TRUE(isStrEqualsCStr(*concat13, "abc0123456789abcdef")); 1615 EXPECT_TRUE(isStrEqualsCStr(*concat31, "0123456789abcdefabc")); 1616 1617 EXPECT_TRUE(concat12.isSmallStr()); 1618 EXPECT_TRUE(concat34.isLargeStr()); 1619 EXPECT_TRUE(concat13.isLargeStr()); 1620 EXPECT_TRUE(concat31.isLargeStr()); 1621} 1622 1623TEST_F(RuntimeTypeCallTest, TypeCallNoInitMethod) { 1624 HandleScope scope(thread_); 1625 1626 const char* src = R"( 1627class MyTypeWithNoInitMethod(): 1628 def m(self): 1629 pass 1630 1631c = MyTypeWithNoInitMethod() 1632)"; 1633 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 1634 1635 Object instance(&scope, mainModuleAt(runtime_, "c")); 1636 ASSERT_TRUE(instance.isInstance()); 1637 LayoutId layout_id = instance.layoutId(); 1638 Layout layout(&scope, runtime_->layoutAt(layout_id)); 1639 EXPECT_EQ(layout.instanceSize(), 1 * kPointerSize); 1640 1641 Type cls(&scope, layout.describedType()); 1642 EXPECT_TRUE(isStrEqualsCStr(cls.name(), "MyTypeWithNoInitMethod")); 1643} 1644 1645TEST_F(RuntimeTypeCallTest, TypeCallEmptyInitMethod) { 1646 HandleScope scope(thread_); 1647 1648 const char* src = R"( 1649class MyTypeWithEmptyInitMethod(): 1650 def __init__(self): 1651 pass 1652 def m(self): 1653 pass 1654 1655c = MyTypeWithEmptyInitMethod() 1656)"; 1657 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 1658 1659 Object instance(&scope, mainModuleAt(runtime_, "c")); 1660 ASSERT_TRUE(instance.isInstance()); 1661 LayoutId layout_id = instance.layoutId(); 1662 Layout layout(&scope, runtime_->layoutAt(layout_id)); 1663 EXPECT_EQ(layout.instanceSize(), 1 * kPointerSize); 1664 1665 Type cls(&scope, layout.describedType()); 1666 EXPECT_TRUE(isStrEqualsCStr(cls.name(), "MyTypeWithEmptyInitMethod")); 1667} 1668 1669TEST_F(RuntimeTypeCallTest, TypeCallWithArguments) { 1670 HandleScope scope(thread_); 1671 1672 const char* src = R"( 1673class MyTypeWithAttributes(): 1674 def __init__(self, x): 1675 self.x = x 1676 def m(self): 1677 pass 1678 1679c = MyTypeWithAttributes(1) 1680)"; 1681 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 1682 1683 Type type(&scope, mainModuleAt(runtime_, "MyTypeWithAttributes")); 1684 Object instance(&scope, mainModuleAt(runtime_, "c")); 1685 ASSERT_TRUE(instance.isInstance()); 1686 LayoutId layout_id = instance.layoutId(); 1687 // Since this class has extra attributes, its layout id should be greater than 1688 // the layout id from the type. 1689 ASSERT_GT(layout_id, Layout::cast(type.instanceLayout()).id()); 1690 Layout layout(&scope, runtime_->layoutAt(layout_id)); 1691 ASSERT_EQ(layout.instanceSize(), 2 * kPointerSize); 1692 1693 Type cls(&scope, layout.describedType()); 1694 EXPECT_TRUE(isStrEqualsCStr(cls.name(), "MyTypeWithAttributes")); 1695 1696 Object name(&scope, Runtime::internStrFromCStr(thread_, "x")); 1697 Object value(&scope, runtime_->attributeAt(thread_, instance, name)); 1698 EXPECT_FALSE(value.isError()); 1699 EXPECT_EQ(*value, SmallInt::fromWord(1)); 1700} 1701 1702TEST_F(RuntimeTest, IsInstanceOf) { 1703 HandleScope scope(thread_); 1704 EXPECT_FALSE(runtime_->isInstanceOfInt(NoneType::object())); 1705 1706 Object i(&scope, runtime_->newInt(123)); 1707 EXPECT_TRUE(i.isInt()); 1708 EXPECT_FALSE(runtime_->isInstanceOfStr(*i)); 1709 1710 Object str(&scope, runtime_->newStrFromCStr("this is a long string")); 1711 EXPECT_TRUE(runtime_->isInstanceOfStr(*str)); 1712 EXPECT_FALSE(str.isInt()); 1713 1714 ASSERT_FALSE(runFromCStr(runtime_, R"( 1715class StopIterationSub(StopIteration): 1716 pass 1717stop_iteration = StopIterationSub() 1718 )") 1719 .isError()); 1720 Object stop_iteration(&scope, mainModuleAt(runtime_, "stop_iteration")); 1721 EXPECT_TRUE(runtime_->isInstanceOfStopIteration(*stop_iteration)); 1722 EXPECT_TRUE(runtime_->isInstanceOfBaseException(*stop_iteration)); 1723 EXPECT_FALSE(runtime_->isInstanceOfSystemExit(*stop_iteration)); 1724} 1725 1726TEST_F(RuntimeTest, IsInstanceOfBaseException) { 1727 ASSERT_FALSE(runFromCStr(runtime_, R"( 1728class M(type): 1729 pass 1730 1731class C(metaclass=M): 1732 pass 1733 1734class D(Exception, metaclass=M): 1735 pass 1736 1737class E(Exception): 1738 pass 1739 1740c = C() 1741d = D() 1742e = E() 1743)") 1744 .isError()); 1745 EXPECT_FALSE( 1746 runtime_->isInstanceOfBaseException(mainModuleAt(runtime_, "c"))); 1747 EXPECT_TRUE(runtime_->isInstanceOfBaseException(mainModuleAt(runtime_, "d"))); 1748 EXPECT_TRUE(runtime_->isInstanceOfBaseException(mainModuleAt(runtime_, "e"))); 1749} 1750 1751TEST_F(RuntimeTest, IsInstanceOfSetBase) { 1752 ASSERT_FALSE(runFromCStr(runtime_, R"( 1753class M(type): 1754 pass 1755 1756class C(metaclass=M): 1757 pass 1758 1759class D(set, metaclass=M): 1760 pass 1761 1762class E(set): 1763 pass 1764 1765class F(frozenset): 1766 pass 1767 1768c = C() 1769d = D() 1770e = E() 1771f = F() 1772)") 1773 .isError()); 1774 EXPECT_FALSE(runtime_->isInstanceOfSetBase(mainModuleAt(runtime_, "c"))); 1775 EXPECT_TRUE(runtime_->isInstanceOfSetBase(mainModuleAt(runtime_, "d"))); 1776 EXPECT_TRUE(runtime_->isInstanceOfSetBase(mainModuleAt(runtime_, "e"))); 1777 EXPECT_TRUE(runtime_->isInstanceOfSetBase(mainModuleAt(runtime_, "f"))); 1778} 1779 1780TEST_F(RuntimeTest, IsInstanceOfUserBaseAcceptsMetaclassInstances) { 1781 HandleScope scope(thread_); 1782 EXPECT_FALSE(runFromCStr(runtime_, R"( 1783class M(type): 1784 pass 1785class IS(int, metaclass=M): 1786 pass 1787i = IS() 1788)") 1789 .isError()); 1790 Object i(&scope, mainModuleAt(runtime_, "i")); 1791 EXPECT_TRUE(runtime_->isInstanceOfUserIntBase(*i)); 1792 EXPECT_FALSE(runtime_->isInstanceOfUserStrBase(*i)); 1793} 1794 1795TEST_F(RuntimeSetTest, EmptySetInvariants) { 1796 HandleScope scope(thread_); 1797 Set set(&scope, runtime_->newSet()); 1798 1799 EXPECT_EQ(set.numItems(), 0); 1800 ASSERT_TRUE(set.isSet()); 1801 ASSERT_TRUE(set.data().isTuple()); 1802 EXPECT_EQ(Tuple::cast(set.data()).length(), 0); 1803} 1804 1805TEST_F(RuntimeSetTest, Add) { 1806 HandleScope scope(thread_); 1807 Set set(&scope, runtime_->newSet()); 1808 Object value(&scope, SmallInt::fromWord(12345)); 1809 word hash = intHash(*value); 1810 1811 // Store a value 1812 setAdd(thread_, set, value, hash); 1813 EXPECT_EQ(set.numItems(), 1); 1814 1815 // Retrieve the stored value 1816 ASSERT_TRUE(setIncludes(thread_, set, value)); 1817 1818 // Add a new value 1819 Object new_value(&scope, SmallInt::fromWord(5555)); 1820 word new_value_hash = intHash(*new_value); 1821 setAdd(thread_, set, new_value, new_value_hash); 1822 EXPECT_EQ(set.numItems(), 2); 1823 1824 // Get the new value 1825 ASSERT_TRUE(setIncludes(thread_, set, new_value)); 1826 1827 // Add a existing value 1828 Object same_value(&scope, SmallInt::fromWord(12345)); 1829 word same_value_hash = intHash(*same_value); 1830 RawObject old_value = setAdd(thread_, set, same_value, same_value_hash); 1831 EXPECT_EQ(set.numItems(), 2); 1832 EXPECT_EQ(old_value, *value); 1833} 1834 1835TEST_F(RuntimeSetTest, Remove) { 1836 HandleScope scope(thread_); 1837 Set set(&scope, runtime_->newSet()); 1838 Object value(&scope, SmallInt::fromWord(12345)); 1839 word hash = intHash(*value); 1840 1841 // Removing a key that doesn't exist should fail 1842 EXPECT_FALSE(setRemove(thread_, set, value, hash)); 1843 1844 setHashAndAdd(thread_, set, value); 1845 EXPECT_EQ(set.numItems(), 1); 1846 1847 ASSERT_TRUE(setRemove(thread_, set, value, hash)); 1848 EXPECT_EQ(set.numItems(), 0); 1849 1850 // Looking up a key that was deleted should fail 1851 ASSERT_FALSE(setIncludes(thread_, set, value)); 1852} 1853 1854static RawObject makeKey(Runtime* runtime, int i) { 1855 byte text[]{"0123456789abcdeghiklmn"}; 1856 return runtime->newStrWithAll(View<byte>(text + i % 10, 10)); 1857} 1858 1859TEST_F(RuntimeSetTest, Grow) { 1860 HandleScope scope(thread_); 1861 Set set(&scope, runtime_->newSet()); 1862 1863 // Fill up the dict - we insert an initial key to force the allocation of the 1864 // backing Tuple. 1865 Object init_key(&scope, SmallInt::fromWord(0)); 1866 setHashAndAdd(thread_, set, init_key); 1867 ASSERT_TRUE(set.data().isTuple()); 1868 word init_data_size = Tuple::cast(set.data()).length(); 1869 1870 // Fill in one fewer keys than would require growing the underlying object 1871 // array again 1872 word num_keys = Runtime::kInitialSetCapacity; 1873 for (int i = 1; i < num_keys; i++) { 1874 Object key(&scope, makeKey(runtime_, i)); 1875 setHashAndAdd(thread_, set, key); 1876 } 1877 1878 // Add another key which should force us to double the capacity 1879 Object straw(&scope, makeKey(runtime_, num_keys)); 1880 setHashAndAdd(thread_, set, straw); 1881 ASSERT_TRUE(set.data().isTuple()); 1882 word new_data_size = Tuple::cast(set.data()).length(); 1883 EXPECT_EQ(new_data_size, Runtime::kSetGrowthFactor * init_data_size); 1884 1885 // Make sure we can still read all the stored keys 1886 for (int i = 1; i <= num_keys; i++) { 1887 Object key(&scope, makeKey(runtime_, i)); 1888 bool found = setIncludes(thread_, set, key); 1889 ASSERT_TRUE(found); 1890 } 1891} 1892 1893TEST_F(RuntimeSetTest, UpdateSet) { 1894 HandleScope scope(thread_); 1895 Set set(&scope, runtime_->newSet()); 1896 Set set1(&scope, runtime_->newSet()); 1897 Object set1_handle(&scope, *set1); 1898 for (word i = 0; i < 8; i++) { 1899 Object value(&scope, SmallInt::fromWord(i)); 1900 setHashAndAdd(thread_, set, value); 1901 } 1902 ASSERT_FALSE(setUpdate(thread_, set, set1_handle).isError()); 1903 ASSERT_EQ(set.numItems(), 8); 1904 for (word i = 4; i < 12; i++) { 1905 Object value(&scope, SmallInt::fromWord(i)); 1906 setHashAndAdd(thread_, set1, value); 1907 } 1908 ASSERT_FALSE(setUpdate(thread_, set, set1_handle).isError()); 1909 ASSERT_EQ(set.numItems(), 12); 1910 ASSERT_FALSE(setUpdate(thread_, set, set1_handle).isError()); 1911 ASSERT_EQ(set.numItems(), 12); 1912} 1913 1914TEST_F(RuntimeSetTest, UpdateList) { 1915 HandleScope scope(thread_); 1916 List list(&scope, runtime_->newList()); 1917 Set set(&scope, runtime_->newSet()); 1918 for (word i = 0; i < 8; i++) { 1919 Object value(&scope, SmallInt::fromWord(i)); 1920 runtime_->listAdd(thread_, list, value); 1921 } 1922 for (word i = 4; i < 12; i++) { 1923 Object value(&scope, SmallInt::fromWord(i)); 1924 setHashAndAdd(thread_, set, value); 1925 } 1926 ASSERT_EQ(set.numItems(), 8); 1927 Object list_handle(&scope, *list); 1928 ASSERT_FALSE(setUpdate(thread_, set, list_handle).isError()); 1929 ASSERT_EQ(set.numItems(), 12); 1930 ASSERT_FALSE(setUpdate(thread_, set, list_handle).isError()); 1931 ASSERT_EQ(set.numItems(), 12); 1932} 1933 1934TEST_F(RuntimeSetTest, UpdateListIterator) { 1935 HandleScope scope(thread_); 1936 List list(&scope, runtime_->newList()); 1937 Set set(&scope, runtime_->newSet()); 1938 for (word i = 0; i < 8; i++) { 1939 Object value(&scope, SmallInt::fromWord(i)); 1940 runtime_->listAdd(thread_, list, value); 1941 } 1942 for (word i = 4; i < 12; i++) { 1943 Object value(&scope, SmallInt::fromWord(i)); 1944 setHashAndAdd(thread_, set, value); 1945 } 1946 ASSERT_EQ(set.numItems(), 8); 1947 Object list_handle(&scope, *list); 1948 Object list_iterator(&scope, runtime_->newListIterator(list_handle)); 1949 ASSERT_FALSE(setUpdate(thread_, set, list_iterator).isError()); 1950 ASSERT_EQ(set.numItems(), 12); 1951} 1952 1953TEST_F(RuntimeSetTest, UpdateTuple) { 1954 HandleScope scope(thread_); 1955 MutableTuple object_array(&scope, runtime_->newMutableTuple(8)); 1956 Set set(&scope, runtime_->newSet()); 1957 for (word i = 0; i < 8; i++) { 1958 object_array.atPut(i, SmallInt::fromWord(i)); 1959 } 1960 for (word i = 4; i < 12; i++) { 1961 Object value(&scope, SmallInt::fromWord(i)); 1962 setHashAndAdd(thread_, set, value); 1963 } 1964 ASSERT_EQ(set.numItems(), 8); 1965 Object object_array_handle(&scope, object_array.becomeImmutable()); 1966 ASSERT_FALSE(setUpdate(thread_, set, object_array_handle).isError()); 1967 ASSERT_EQ(set.numItems(), 12); 1968} 1969 1970TEST_F(RuntimeSetTest, UpdateIterator) { 1971 HandleScope scope(thread_); 1972 Set set(&scope, runtime_->newSet()); 1973 Int one(&scope, SmallInt::fromWord(1)); 1974 Int four(&scope, SmallInt::fromWord(4)); 1975 Object iterable(&scope, runtime_->newRange(one, four, one)); 1976 ASSERT_FALSE(setUpdate(thread_, set, iterable).isError()); 1977 1978 ASSERT_EQ(set.numItems(), 3); 1979} 1980 1981TEST_F(RuntimeSetTest, UpdateWithNonIterable) { 1982 HandleScope scope(thread_); 1983 Set set(&scope, runtime_->newSet()); 1984 Object non_iterable(&scope, NoneType::object()); 1985 Object result(&scope, setUpdate(thread_, set, non_iterable)); 1986 ASSERT_TRUE(result.isError()); 1987} 1988 1989TEST_F(RuntimeSetTest, EmptySetItersectionReturnsEmptySet) { 1990 HandleScope scope(thread_); 1991 Set set(&scope, runtime_->newSet()); 1992 Set set1(&scope, runtime_->newSet()); 1993 1994 // set() & set() 1995 Object result(&scope, setIntersection(thread_, set, set1)); 1996 ASSERT_TRUE(result.isSet()); 1997 EXPECT_EQ(Set::cast(*result).numItems(), 0); 1998} 1999 2000TEST_F(RuntimeSetTest, ItersectionWithEmptySetReturnsEmptySet) { 2001 HandleScope scope(thread_); 2002 Set set(&scope, runtime_->newSet()); 2003 Set set1(&scope, runtime_->newSet()); 2004 2005 for (word i = 0; i < 8; i++) { 2006 Object value(&scope, SmallInt::fromWord(i)); 2007 setHashAndAdd(thread_, set1, value); 2008 } 2009 2010 // set() & {0, 1, 2, 3, 4, 5, 6, 7} 2011 Object result(&scope, setIntersection(thread_, set, set1)); 2012 ASSERT_TRUE(result.isSet()); 2013 EXPECT_EQ(Set::cast(*result).numItems(), 0); 2014 2015 // {0, 1, 2, 3, 4, 5, 6, 7} & set() 2016 Object result1(&scope, setIntersection(thread_, set1, set)); 2017 ASSERT_TRUE(result1.isSet()); 2018 EXPECT_EQ(Set::cast(*result1).numItems(), 0); 2019} 2020 2021TEST_F(RuntimeSetTest, IntersectionReturnsSetWithCommonElements) { 2022 HandleScope scope(thread_); 2023 Set set(&scope, runtime_->newSet()); 2024 Set set1(&scope, runtime_->newSet()); 2025 Object key(&scope, NoneType::object()); 2026 2027 for (word i = 0; i < 8; i++) { 2028 Object value(&scope, SmallInt::fromWord(i)); 2029 setHashAndAdd(thread_, set1, value); 2030 } 2031 2032 for (word i = 0; i < 4; i++) { 2033 Object value(&scope, SmallInt::fromWord(i)); 2034 setHashAndAdd(thread_, set, value); 2035 } 2036 2037 // {0, 1, 2, 3} & {0, 1, 2, 3, 4, 5, 6, 7} 2038 Set result(&scope, setIntersection(thread_, set, set1)); 2039 EXPECT_EQ(Set::cast(*result).numItems(), 4); 2040 key = SmallInt::fromWord(0); 2041 EXPECT_TRUE(setIncludes(thread_, result, key)); 2042 key = SmallInt::fromWord(1); 2043 EXPECT_TRUE(setIncludes(thread_, result, key)); 2044 key = SmallInt::fromWord(2); 2045 EXPECT_TRUE(setIncludes(thread_, result, key)); 2046 key = SmallInt::fromWord(3); 2047 EXPECT_TRUE(setIncludes(thread_, result, key)); 2048 2049 // {0, 1, 2, 3, 4, 5, 6, 7} & {0, 1, 2, 3} 2050 Set result1(&scope, setIntersection(thread_, set, set1)); 2051 EXPECT_EQ(Set::cast(*result1).numItems(), 4); 2052 key = SmallInt::fromWord(0); 2053 EXPECT_TRUE(setIncludes(thread_, result1, key)); 2054 key = SmallInt::fromWord(1); 2055 EXPECT_TRUE(setIncludes(thread_, result1, key)); 2056 key = SmallInt::fromWord(2); 2057 EXPECT_TRUE(setIncludes(thread_, result1, key)); 2058 key = SmallInt::fromWord(3); 2059 EXPECT_TRUE(setIncludes(thread_, result1, key)); 2060} 2061 2062TEST_F(RuntimeSetTest, IntersectIterator) { 2063 HandleScope scope(thread_); 2064 Set set(&scope, runtime_->newSet()); 2065 Int one(&scope, SmallInt::fromWord(1)); 2066 Int four(&scope, SmallInt::fromWord(4)); 2067 Object iterable(&scope, runtime_->newRange(one, four, one)); 2068 Set result(&scope, setIntersection(thread_, set, iterable)); 2069 EXPECT_EQ(result.numItems(), 0); 2070 2071 Object key(&scope, SmallInt::fromWord(1)); 2072 setHashAndAdd(thread_, set, key); 2073 key = SmallInt::fromWord(2); 2074 setHashAndAdd(thread_, set, key); 2075 Set result1(&scope, setIntersection(thread_, set, iterable)); 2076 EXPECT_EQ(result1.numItems(), 2); 2077 EXPECT_TRUE(setIncludes(thread_, result1, key)); 2078 key = SmallInt::fromWord(1); 2079 EXPECT_TRUE(setIncludes(thread_, result1, key)); 2080} 2081 2082TEST_F(RuntimeSetTest, IntersectWithNonIterable) { 2083 HandleScope scope(thread_); 2084 Set set(&scope, runtime_->newSet()); 2085 Object non_iterable(&scope, NoneType::object()); 2086 2087 Object result(&scope, setIntersection(thread_, set, non_iterable)); 2088 ASSERT_TRUE(result.isError()); 2089} 2090 2091// Attribute tests 2092 2093// Set an attribute defined in __init__ 2094TEST_F(RuntimeAttributeTest, SetInstanceAttribute) { 2095 const char* src = R"( 2096class Foo: 2097 def __init__(self): 2098 self.attr = 'testing 123' 2099 2100def test(x): 2101 result = [] 2102 Foo.__init__(x) 2103 result.append(x.attr) 2104 x.attr = '321 testing' 2105 result.append(x.attr) 2106 return result 2107)"; 2108 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2109 2110 // Create the instance 2111 HandleScope scope(thread_); 2112 Type type(&scope, mainModuleAt(runtime_, "Foo")); 2113 Layout layout(&scope, type.instanceLayout()); 2114 Object instance(&scope, runtime_->newInstance(layout)); 2115 2116 // Run __init__ then RMW the attribute 2117 Function test(&scope, mainModuleAt(runtime_, "test")); 2118 Object result(&scope, Interpreter::call1(thread_, test, instance)); 2119 EXPECT_PYLIST_EQ(result, {"testing 123", "321 testing"}); 2120} 2121 2122TEST_F(RuntimeAttributeTest, AddOverflowAttributes) { 2123 const char* src = R"( 2124class Foo: 2125 pass 2126 2127def test(x): 2128 result = [] 2129 x.foo = 100 2130 x.bar = 200 2131 x.baz = 'hello' 2132 result.append(x.foo) 2133 result.append(x.bar) 2134 result.append(x.baz) 2135 2136 x.foo = 'aaa' 2137 x.bar = 'bbb' 2138 x.baz = 'ccc' 2139 result.append(x.foo) 2140 result.append(x.bar) 2141 result.append(x.baz) 2142 return result 2143)"; 2144 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2145 2146 // Create an instance of Foo 2147 HandleScope scope(thread_); 2148 Type type(&scope, mainModuleAt(runtime_, "Foo")); 2149 Layout layout(&scope, type.instanceLayout()); 2150 Instance foo1(&scope, runtime_->newInstance(layout)); 2151 LayoutId original_layout_id = layout.id(); 2152 2153 // Add overflow attributes that should force layout transitions 2154 Function test(&scope, mainModuleAt(runtime_, "test")); 2155 Object result0(&scope, Interpreter::call1(thread_, test, foo1)); 2156 EXPECT_PYLIST_EQ(result0, {100, 200, "hello", "aaa", "bbb", "ccc"}); 2157 EXPECT_NE(foo1.layoutId(), original_layout_id); 2158 2159 // Add the same set of attributes to a new instance, should arrive at the 2160 // same layout 2161 Instance foo2(&scope, runtime_->newInstance(layout)); 2162 Object result1(&scope, Interpreter::call1(thread_, test, foo2)); 2163 EXPECT_PYLIST_EQ(result1, {100, 200, "hello", "aaa", "bbb", "ccc"}); 2164} 2165 2166TEST_F(RuntimeAttributeTest, ManipulateMultipleAttributes) { 2167 const char* src = R"( 2168class Foo: 2169 def __init__(self): 2170 self.foo = 'foo' 2171 self.bar = 'bar' 2172 self.baz = 'baz' 2173 2174def test(x): 2175 result = [] 2176 Foo.__init__(x) 2177 result.append(x.foo) 2178 result.append(x.bar) 2179 result.append(x.baz) 2180 x.foo = 'aaa' 2181 x.bar = 'bbb' 2182 x.baz = 'ccc' 2183 result.append(x.foo) 2184 result.append(x.bar) 2185 result.append(x.baz) 2186 return result 2187)"; 2188 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2189 2190 // Create the instance 2191 HandleScope scope(thread_); 2192 Type type(&scope, mainModuleAt(runtime_, "Foo")); 2193 Layout layout(&scope, type.instanceLayout()); 2194 Object instance(&scope, runtime_->newInstance(layout)); 2195 2196 // Run the test 2197 Function test(&scope, mainModuleAt(runtime_, "test")); 2198 Object result(&scope, Interpreter::call1(thread_, test, instance)); 2199 EXPECT_PYLIST_EQ(result, {"foo", "bar", "baz", "aaa", "bbb", "ccc"}); 2200} 2201 2202TEST_F(RuntimeAttributeTest, FetchConditionalInstanceAttribute) { 2203 const char* src = R"( 2204def false(): 2205 return False 2206 2207class Foo: 2208 def __init__(self): 2209 self.foo = 'foo' 2210 if false(): 2211 self.bar = 'bar' 2212 2213foo = Foo() 2214print(foo.bar) 2215)"; 2216 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), 2217 LayoutId::kAttributeError, 2218 "'Foo' object has no attribute 'bar'")); 2219} 2220 2221TEST_F(RuntimeAttributeTest, DunderNewOnInstance) { 2222 const char* src = R"( 2223result = [] 2224class Foo: 2225 def __new__(cls): 2226 result.append("New") 2227 return object.__new__(cls) 2228 def __init__(self): 2229 result.append("Init") 2230Foo() 2231)"; 2232 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2233 HandleScope scope(thread_); 2234 Object result(&scope, mainModuleAt(runtime_, "result")); 2235 EXPECT_PYLIST_EQ(result, {"New", "Init"}); 2236} 2237 2238TEST_F(RuntimeAttributeTest, NoInstanceDictReturnsClassAttribute) { 2239 HandleScope scope(thread_); 2240 Object immediate(&scope, SmallInt::fromWord(-1)); 2241 RawObject attr = runtime_->attributeAtById(thread_, immediate, ID(__neg__)); 2242 ASSERT_TRUE(attr.isBoundMethod()); 2243} 2244 2245TEST_F(RuntimeAttributeTest, DeleteKnownAttribute) { 2246 ASSERT_FALSE(runFromCStr(runtime_, R"( 2247class Foo: 2248 def __init__(self): 2249 self.foo = 'foo' 2250 self.bar = 'bar' 2251 2252def test(): 2253 foo = Foo() 2254 del foo.bar 2255)") 2256 .isError()); 2257 HandleScope scope(thread_); 2258 Function test(&scope, mainModuleAt(runtime_, "test")); 2259 Tuple args(&scope, runtime_->emptyTuple()); 2260 Object result(&scope, callFunction(test, args)); 2261 EXPECT_EQ(*result, NoneType::object()); 2262} 2263 2264TEST_F(RuntimeAttributeTest, DeleteDescriptor) { 2265 ASSERT_FALSE(runFromCStr(runtime_, R"( 2266result = None 2267 2268class DeleteDescriptor: 2269 def __delete__(self, instance): 2270 global result 2271 result = self, instance 2272descr = DeleteDescriptor() 2273 2274class Foo: 2275 bar = descr 2276 2277foo = Foo() 2278del foo.bar 2279)") 2280 .isError()); 2281 HandleScope scope(thread_); 2282 Object data(&scope, mainModuleAt(runtime_, "result")); 2283 ASSERT_TRUE(data.isTuple()); 2284 2285 Tuple result(&scope, *data); 2286 ASSERT_EQ(result.length(), 2); 2287 2288 Object descr(&scope, mainModuleAt(runtime_, "descr")); 2289 EXPECT_EQ(result.at(0), *descr); 2290 2291 Object foo(&scope, mainModuleAt(runtime_, "foo")); 2292 EXPECT_EQ(result.at(1), *foo); 2293} 2294 2295TEST_F(RuntimeAttributeTest, DeleteUnknownAttribute) { 2296 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 2297class Foo: 2298 pass 2299 2300foo = Foo() 2301del foo.bar 2302)"), 2303 LayoutId::kAttributeError, 2304 "'Foo' object has no attribute 'bar'")); 2305} 2306 2307TEST_F(RuntimeAttributeTest, DeleteAttributeWithDunderDelattr) { 2308 HandleScope scope(thread_); 2309 const char* src = R"( 2310result = None 2311 2312class Foo: 2313 def __delattr__(self, name): 2314 global result 2315 result = self, name 2316 2317foo = Foo() 2318del foo.bar 2319)"; 2320 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2321 Object data(&scope, mainModuleAt(runtime_, "result")); 2322 ASSERT_TRUE(data.isTuple()); 2323 2324 Tuple result(&scope, *data); 2325 ASSERT_EQ(result.length(), 2); 2326 2327 Object foo(&scope, mainModuleAt(runtime_, "foo")); 2328 EXPECT_EQ(result.at(0), *foo); 2329 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "bar")); 2330} 2331 2332TEST_F(RuntimeAttributeTest, DeleteAttributeWithDunderDelattrOnSuperclass) { 2333 ASSERT_FALSE(runFromCStr(runtime_, R"( 2334result = None 2335 2336class Foo: 2337 def __delattr__(self, name): 2338 global result 2339 result = self, name 2340 2341class Bar(Foo): 2342 pass 2343 2344bar = Bar() 2345del bar.baz 2346)") 2347 .isError()); 2348 HandleScope scope(thread_); 2349 Object data(&scope, mainModuleAt(runtime_, "result")); 2350 ASSERT_TRUE(data.isTuple()); 2351 2352 Tuple result(&scope, *data); 2353 ASSERT_EQ(result.length(), 2); 2354 2355 Object bar(&scope, mainModuleAt(runtime_, "bar")); 2356 EXPECT_EQ(result.at(0), *bar); 2357 EXPECT_TRUE(isStrEqualsCStr(result.at(1), "baz")); 2358} 2359 2360TEST_F(RuntimeClassAttrTest, DeleteKnownAttribute) { 2361 ASSERT_FALSE(runFromCStr(runtime_, R"( 2362class Foo: 2363 foo = 'foo' 2364 bar = 'bar' 2365 2366def test(): 2367 del Foo.bar 2368)") 2369 .isError()); 2370 HandleScope scope(thread_); 2371 Function test(&scope, mainModuleAt(runtime_, "test")); 2372 Tuple args(&scope, runtime_->emptyTuple()); 2373 Object result(&scope, callFunction(test, args)); 2374 EXPECT_EQ(*result, NoneType::object()); 2375} 2376 2377TEST_F(RuntimeAttributeTest, DeleteDescriptorOnMetaclass) { 2378 HandleScope scope(thread_); 2379 const char* src = R"( 2380args = None 2381 2382class DeleteDescriptor: 2383 def __delete__(self, instance): 2384 global args 2385 args = (self, instance) 2386 2387descr = DeleteDescriptor() 2388 2389class FooMeta(type): 2390 attr = descr 2391 2392class Foo(metaclass=FooMeta): 2393 pass 2394 2395del Foo.attr 2396)"; 2397 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2398 Object data(&scope, mainModuleAt(runtime_, "args")); 2399 ASSERT_TRUE(data.isTuple()); 2400 2401 Tuple args(&scope, *data); 2402 ASSERT_EQ(args.length(), 2); 2403 2404 Object descr(&scope, mainModuleAt(runtime_, "descr")); 2405 EXPECT_EQ(args.at(0), *descr); 2406 2407 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2408 EXPECT_EQ(args.at(1), *foo); 2409} 2410 2411TEST_F(RuntimeAttributeTest, DeleteUnknownClassAttribute) { 2412 const char* src = R"( 2413class Foo: 2414 pass 2415 2416del Foo.bar 2417)"; 2418 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), 2419 LayoutId::kAttributeError, 2420 "type object 'Foo' has no attribute 'bar'")); 2421} 2422 2423TEST_F(RuntimeAttributeTest, DeleteClassAttributeWithDunderDelattrOnMetaclass) { 2424 HandleScope scope(thread_); 2425 const char* src = R"( 2426args = None 2427 2428class FooMeta(type): 2429 def __delattr__(self, name): 2430 global args 2431 args = self, name 2432 2433class Foo(metaclass=FooMeta): 2434 pass 2435 2436del Foo.bar 2437)"; 2438 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2439 Object data(&scope, mainModuleAt(runtime_, "args")); 2440 ASSERT_TRUE(data.isTuple()); 2441 2442 Tuple args(&scope, *data); 2443 ASSERT_EQ(args.length(), 2); 2444 2445 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2446 EXPECT_EQ(args.at(0), *foo); 2447 2448 Object attr(&scope, Runtime::internStrFromCStr(thread_, "bar")); 2449 EXPECT_EQ(args.at(1), *attr); 2450} 2451 2452TEST_F( 2453 RuntimeTest, 2454 DeleteClassAttributeWithUnimplementedCacheInvalidationTerminatesPyroWhenCacheIsEnabled) { 2455 EXPECT_FALSE(runFromCStr(runtime_, R"( 2456class C: 2457 def __len__(self): return 4 2458 2459del C.__len__ 2460)") 2461 .isError()); 2462 ASSERT_DEATH(static_cast<void>(runFromCStr(runtime_, R"( 2463class C: 2464 def __setattr__(self, other): return 4 2465 2466del C.__setattr__ 2467)")), 2468 "unimplemented cache invalidation for type.__setattr__ update"); 2469} 2470 2471TEST_F(RuntimeModuleAttrTest, DeleteUnknownAttribute) { 2472 HandleScope scope(thread_); 2473 const char* src = R"( 2474def test(module): 2475 del module.foo 2476)"; 2477 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2478 Function test(&scope, mainModuleAt(runtime_, "test")); 2479 Object obj(&scope, findMainModule(runtime_)); 2480 Tuple args(&scope, runtime_->newTupleWith1(obj)); 2481 EXPECT_TRUE(raised(callFunction(test, args), LayoutId::kAttributeError)); 2482} 2483 2484TEST_F(RuntimeModuleAttrTest, DeleteKnownAttribute) { 2485 ASSERT_FALSE(runFromCStr(runtime_, R"( 2486foo = 'testing 123' 2487 2488def test(module): 2489 del module.foo 2490 return 123 2491)") 2492 .isError()); 2493 HandleScope scope(thread_); 2494 Function test(&scope, mainModuleAt(runtime_, "test")); 2495 Object obj(&scope, findMainModule(runtime_)); 2496 Tuple args(&scope, runtime_->newTupleWith1(obj)); 2497 EXPECT_EQ(callFunction(test, args), SmallInt::fromWord(123)); 2498 2499 Object attr(&scope, Runtime::internStrFromCStr(thread_, "foo")); 2500 Object module(&scope, findMainModule(runtime_)); 2501 EXPECT_TRUE(runtime_->attributeAt(thread_, module, attr).isError()); 2502} 2503 2504TEST_F(RuntimeIntTest, NewLargeIntWithDigits) { 2505 HandleScope scope(thread_); 2506 2507 word negative_large_int = RawSmallInt::kMinValue - 1; 2508 uword digit = static_cast<uword>(negative_large_int); 2509 Int negative_largeint( 2510 &scope, runtime_->newLargeIntWithDigits(View<uword>(&digit, 1))); 2511 EXPECT_TRUE(isIntEqualsWord(*negative_largeint, negative_large_int)); 2512 2513 word positive_large_int = RawSmallInt::kMaxValue + 1; 2514 digit = static_cast<uword>(positive_large_int); 2515 Int positive_largeint( 2516 &scope, runtime_->newLargeIntWithDigits(View<uword>(&digit, 1))); 2517 EXPECT_TRUE(isIntEqualsWord(*positive_largeint, positive_large_int)); 2518} 2519 2520TEST_F(RuntimeIntTest, BinaryAndWithSmallInts) { 2521 HandleScope scope(thread_); 2522 Int left(&scope, SmallInt::fromWord(0xEA)); // 0b11101010 2523 Int right(&scope, SmallInt::fromWord(0xDC)); // 0b11011100 2524 Object result(&scope, runtime_->intBinaryAnd(thread_, left, right)); 2525 EXPECT_TRUE(isIntEqualsWord(*result, 0xC8)); // 0b11001000 2526} 2527 2528TEST_F(RuntimeIntTest, BinaryAndWithLargeInts) { 2529 HandleScope scope(thread_); 2530 // {0b00001111, 0b00110000, 0b00000001} 2531 const uword digits_left[] = {0x0F, 0x30, 0x1}; 2532 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left)); 2533 // {0b00000011, 0b11110000, 0b00000010, 0b00000111} 2534 const uword digits_right[] = {0x03, 0xF0, 0x2, 0x7}; 2535 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right)); 2536 Object result(&scope, runtime_->intBinaryAnd(thread_, left, right)); 2537 // {0b00000111, 0b01110000} 2538 const uword expected_digits[] = {0x03, 0x30}; 2539 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 2540 2541 Object result_commuted(&scope, runtime_->intBinaryAnd(thread_, right, left)); 2542 EXPECT_TRUE(isIntEqualsDigits(*result_commuted, expected_digits)); 2543} 2544 2545TEST_F(RuntimeIntTest, BinaryAndWithNegativeLargeInts) { 2546 HandleScope scope(thread_); 2547 2548 Int left(&scope, SmallInt::fromWord(-42)); // 0b11010110 2549 const uword digits[] = {static_cast<uword>(-1), 0xF0, 0x2, 0x7}; 2550 Int right(&scope, runtime_->newLargeIntWithDigits(digits)); 2551 Object result(&scope, runtime_->intBinaryAnd(thread_, left, right)); 2552 const uword expected_digits[] = {static_cast<uword>(-42), 0xF0, 0x2, 0x7}; 2553 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 2554} 2555 2556TEST_F(RuntimeIntTest, BinaryOrWithSmallInts) { 2557 HandleScope scope(thread_); 2558 Int left(&scope, SmallInt::fromWord(0xAA)); // 0b10101010 2559 Int right(&scope, SmallInt::fromWord(0x9C)); // 0b10011100 2560 Object result(&scope, runtime_->intBinaryOr(thread_, left, right)); 2561 EXPECT_TRUE(isIntEqualsWord(*result, 0xBE)); // 0b10111110 2562} 2563 2564TEST_F(RuntimeIntTest, BinaryOrWithLargeInts) { 2565 HandleScope scope(thread_); 2566 // {0b00001100, 0b00110000, 0b00000001} 2567 const uword digits_left[] = {0x0C, 0x30, 0x1}; 2568 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left)); 2569 // {0b00000011, 0b11010000, 0b00000010, 0b00000111} 2570 const uword digits_right[] = {0x03, 0xD0, 0x2, 0x7}; 2571 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right)); 2572 Object result(&scope, runtime_->intBinaryOr(thread_, left, right)); 2573 // {0b00001111, 0b11110000, 0b00000011, 0b00000111} 2574 const uword expected_digits[] = {0x0F, 0xF0, 0x3, 0x7}; 2575 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 2576 2577 Object result_commuted(&scope, runtime_->intBinaryOr(thread_, right, left)); 2578 EXPECT_TRUE(isIntEqualsDigits(*result_commuted, expected_digits)); 2579} 2580 2581TEST_F(RuntimeIntTest, BinaryOrWithNegativeLargeInts) { 2582 HandleScope scope(thread_); 2583 2584 Int left(&scope, SmallInt::fromWord(-42)); // 0b11010110 2585 const uword digits[] = {static_cast<uword>(-4), 0xF0, 0x2, 2586 static_cast<uword>(-1)}; 2587 Int right(&scope, runtime_->newLargeIntWithDigits(digits)); 2588 Object result(&scope, runtime_->intBinaryOr(thread_, left, right)); 2589 EXPECT_TRUE(isIntEqualsWord(*result, -2)); 2590} 2591 2592TEST_F(RuntimeIntTest, BinaryXorWithSmallInts) { 2593 HandleScope scope(thread_); 2594 Int left(&scope, SmallInt::fromWord(0xAA)); // 0b10101010 2595 Int right(&scope, SmallInt::fromWord(0x9C)); // 0b10011100 2596 Object result(&scope, runtime_->intBinaryXor(thread_, left, right)); 2597 EXPECT_TRUE(isIntEqualsWord(*result, 0x36)); // 0b00110110 2598} 2599 2600TEST_F(RuntimeIntTest, BinaryXorWithLargeInts) { 2601 HandleScope scope(thread_); 2602 // {0b00001100, 0b00110000, 0b00000001} 2603 const uword digits_left[] = {0x0C, 0x30, 0x1}; 2604 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left)); 2605 // {0b00000011, 0b11010000, 0b00000010, 0b00000111} 2606 const uword digits_right[] = {0x03, 0xD0, 0x2, 0x7}; 2607 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right)); 2608 Object result(&scope, runtime_->intBinaryXor(thread_, left, right)); 2609 // {0b00001111, 0b11100000, 0b00000011, 0b00000111} 2610 const uword expected_digits[] = {0x0F, 0xE0, 0x3, 0x7}; 2611 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 2612 2613 Object result_commuted(&scope, runtime_->intBinaryXor(thread_, right, left)); 2614 EXPECT_TRUE(isIntEqualsDigits(*result_commuted, expected_digits)); 2615} 2616 2617TEST_F(RuntimeIntTest, BinaryXorWithNegativeLargeInts) { 2618 HandleScope scope(thread_); 2619 2620 Int left(&scope, SmallInt::fromWord(-42)); // 0b11010110 2621 const uword digits[] = {static_cast<uword>(-1), 0xf0, 0x2, 2622 static_cast<uword>(-1)}; 2623 Int right(&scope, runtime_->newLargeIntWithDigits(digits)); 2624 Object result(&scope, runtime_->intBinaryXor(thread_, left, right)); 2625 const uword expected_digits[] = {0x29, ~uword{0xF0}, ~uword{0x2}, 0}; 2626 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 2627} 2628 2629TEST_F(RuntimeIntTest, NormalizeLargeIntToSmallInt) { 2630 HandleScope scope(thread_); 2631 2632 const uword digits[] = {42}; 2633 LargeInt lint_42(&scope, newLargeIntWithDigits(digits)); 2634 Object norm_42(&scope, runtime_->normalizeLargeInt(thread_, lint_42)); 2635 EXPECT_TRUE(isIntEqualsWord(*norm_42, 42)); 2636 2637 const uword digits2[] = {uword(-1)}; 2638 LargeInt lint_neg1(&scope, newLargeIntWithDigits(digits2)); 2639 Object norm_neg1(&scope, runtime_->normalizeLargeInt(thread_, lint_neg1)); 2640 EXPECT_TRUE(isIntEqualsWord(*norm_neg1, -1)); 2641 2642 const uword digits3[] = {uword(RawSmallInt::kMinValue)}; 2643 LargeInt lint_min(&scope, newLargeIntWithDigits(digits3)); 2644 Object norm_min(&scope, runtime_->normalizeLargeInt(thread_, lint_min)); 2645 EXPECT_TRUE(isIntEqualsWord(*norm_min, RawSmallInt::kMinValue)); 2646 2647 const uword digits4[] = {RawSmallInt::kMaxValue}; 2648 LargeInt lint_max(&scope, newLargeIntWithDigits(digits4)); 2649 Object norm_max(&scope, runtime_->normalizeLargeInt(thread_, lint_max)); 2650 EXPECT_TRUE(isIntEqualsWord(*norm_max, RawSmallInt::kMaxValue)); 2651 2652 const uword digits5[] = {uword(-4), kMaxUword}; 2653 LargeInt lint_sext_neg_4(&scope, newLargeIntWithDigits(digits5)); 2654 Object norm_neg_4(&scope, 2655 runtime_->normalizeLargeInt(thread_, lint_sext_neg_4)); 2656 EXPECT_TRUE(isIntEqualsWord(*norm_neg_4, -4)); 2657 2658 const uword digits6[] = {uword(-13), kMaxUword, kMaxUword, kMaxUword}; 2659 LargeInt lint_sext_neg_13(&scope, newLargeIntWithDigits(digits6)); 2660 Object norm_neg_13(&scope, 2661 runtime_->normalizeLargeInt(thread_, lint_sext_neg_13)); 2662 EXPECT_TRUE(isIntEqualsWord(*norm_neg_13, -13)); 2663 2664 const uword digits7[] = {66, 0}; 2665 LargeInt lint_zext_66(&scope, newLargeIntWithDigits(digits7)); 2666 Object norm_66(&scope, runtime_->normalizeLargeInt(thread_, lint_zext_66)); 2667 EXPECT_TRUE(isIntEqualsWord(*norm_66, 66)); 2668} 2669 2670TEST_F(RuntimeIntTest, NormalizeLargeIntToLargeInt) { 2671 HandleScope scope(thread_); 2672 2673 const uword digits[] = {kMaxWord}; 2674 LargeInt lint_max(&scope, newLargeIntWithDigits(digits)); 2675 Object norm_max(&scope, runtime_->normalizeLargeInt(thread_, lint_max)); 2676 EXPECT_TRUE(isIntEqualsWord(*norm_max, kMaxWord)); 2677 2678 const uword digits2[] = {uword(kMinWord)}; 2679 LargeInt lint_min(&scope, newLargeIntWithDigits(digits2)); 2680 Object norm_min(&scope, runtime_->normalizeLargeInt(thread_, lint_min)); 2681 EXPECT_TRUE(isIntEqualsWord(*norm_min, kMinWord)); 2682 2683 const uword digits3[] = {kMaxWord - 7, 0, 0}; 2684 LargeInt lint_max_sub_7_zext(&scope, newLargeIntWithDigits(digits3)); 2685 Object norm_max_sub_7( 2686 &scope, runtime_->normalizeLargeInt(thread_, lint_max_sub_7_zext)); 2687 EXPECT_TRUE(isIntEqualsWord(*norm_max_sub_7, kMaxWord - 7)); 2688 2689 const uword digits4[] = {uword(kMinWord) + 9, kMaxUword}; 2690 LargeInt lint_min_plus_9_sext(&scope, newLargeIntWithDigits(digits4)); 2691 Object norm_min_plus_9( 2692 &scope, runtime_->normalizeLargeInt(thread_, lint_min_plus_9_sext)); 2693 EXPECT_TRUE(isIntEqualsWord(*norm_min_plus_9, kMinWord + 9)); 2694 2695 const uword digits5[] = {0, kMaxUword}; 2696 LargeInt lint_no_sext(&scope, newLargeIntWithDigits(digits5)); 2697 Object norm_no_sext(&scope, 2698 runtime_->normalizeLargeInt(thread_, lint_no_sext)); 2699 const uword expected_digits1[] = {0, kMaxUword}; 2700 EXPECT_TRUE(isIntEqualsDigits(*norm_no_sext, expected_digits1)); 2701 2702 const uword digits6[] = {kMaxUword, 0}; 2703 LargeInt lint_no_zext(&scope, newLargeIntWithDigits(digits6)); 2704 Object norm_no_zext(&scope, 2705 runtime_->normalizeLargeInt(thread_, lint_no_zext)); 2706 const uword expected_digits2[] = {kMaxUword, 0}; 2707 EXPECT_TRUE(isIntEqualsDigits(*norm_no_zext, expected_digits2)); 2708} 2709 2710TEST_F(RuntimeTest, ClassWithTypeMetaclassIsConcreteType) { 2711 const char* src = R"( 2712# This is equivalent to `class Foo(type)` 2713class Foo(type, metaclass=type): 2714 pass 2715 2716class Bar(Foo): 2717 pass 2718)"; 2719 HandleScope scope(thread_); 2720 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2721 2722 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2723 EXPECT_TRUE(foo.isType()); 2724 2725 Object bar(&scope, mainModuleAt(runtime_, "Bar")); 2726 EXPECT_TRUE(bar.isType()); 2727} 2728 2729TEST_F(RuntimeTest, ClassWithCustomMetaclassIsntConcreteType) { 2730 const char* src = R"( 2731class MyMeta(type): 2732 pass 2733 2734class Foo(type, metaclass=MyMeta): 2735 pass 2736)"; 2737 HandleScope scope(thread_); 2738 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2739 2740 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2741 EXPECT_FALSE(foo.isType()); 2742} 2743 2744TEST_F(RuntimeTest, ClassWithTypeMetaclassIsInstanceOfType) { 2745 const char* src = R"( 2746class Foo(type): 2747 pass 2748 2749class Bar(Foo): 2750 pass 2751)"; 2752 HandleScope scope(thread_); 2753 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2754 2755 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2756 EXPECT_TRUE(runtime_->isInstanceOfType(*foo)); 2757 2758 Object bar(&scope, mainModuleAt(runtime_, "Bar")); 2759 EXPECT_TRUE(runtime_->isInstanceOfType(*bar)); 2760} 2761 2762TEST_F(RuntimeTest, ClassWithCustomMetaclassIsInstanceOfType) { 2763 const char* src = R"( 2764class MyMeta(type): 2765 pass 2766 2767class Foo(type, metaclass=MyMeta): 2768 pass 2769)"; 2770 HandleScope scope(thread_); 2771 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2772 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2773 EXPECT_TRUE(runtime_->isInstanceOfType(*foo)); 2774} 2775 2776TEST_F(RuntimeTest, VerifyMetaclassHierarchy) { 2777 const char* src = R"( 2778class GrandMeta(type): 2779 pass 2780 2781class ParentMeta(type, metaclass=GrandMeta): 2782 pass 2783 2784class ChildMeta(type, metaclass=ParentMeta): 2785 pass 2786)"; 2787 HandleScope scope(thread_); 2788 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2789 Object type(&scope, runtime_->typeAt(LayoutId::kType)); 2790 2791 Object grand_meta(&scope, mainModuleAt(runtime_, "GrandMeta")); 2792 EXPECT_EQ(runtime_->typeOf(*grand_meta), *type); 2793 2794 Object parent_meta(&scope, mainModuleAt(runtime_, "ParentMeta")); 2795 EXPECT_EQ(runtime_->typeOf(*parent_meta), *grand_meta); 2796 2797 Object child_meta(&scope, mainModuleAt(runtime_, "ChildMeta")); 2798 EXPECT_EQ(runtime_->typeOf(*child_meta), *parent_meta); 2799} 2800 2801TEST_F(RuntimeMetaclassTest, CallMetaclass) { 2802 const char* src = R"( 2803class MyMeta(type): 2804 pass 2805 2806Foo = MyMeta('Foo', (), {}) 2807)"; 2808 HandleScope scope(thread_); 2809 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2810 Object mymeta(&scope, mainModuleAt(runtime_, "MyMeta")); 2811 Object foo(&scope, mainModuleAt(runtime_, "Foo")); 2812 EXPECT_EQ(runtime_->typeOf(*foo), *mymeta); 2813 EXPECT_FALSE(foo.isType()); 2814 EXPECT_TRUE(runtime_->isInstanceOfType(*foo)); 2815} 2816 2817TEST_F(RuntimeTest, SubclassBuiltinSubclass) { 2818 const char* src = R"( 2819class Test(Exception): 2820 pass 2821)"; 2822 HandleScope scope(thread_); 2823 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2824 Object value(&scope, mainModuleAt(runtime_, "Test")); 2825 ASSERT_TRUE(value.isType()); 2826 2827 Type type(&scope, *value); 2828 ASSERT_TRUE(type.mro().isTuple()); 2829 2830 Tuple mro(&scope, type.mro()); 2831 ASSERT_EQ(mro.length(), 4); 2832 EXPECT_EQ(mro.at(0), *type); 2833 EXPECT_EQ(mro.at(1), runtime_->typeAt(LayoutId::kException)); 2834 EXPECT_EQ(mro.at(2), runtime_->typeAt(LayoutId::kBaseException)); 2835 EXPECT_EQ(mro.at(3), runtime_->typeAt(LayoutId::kObject)); 2836} 2837 2838TEST_F(RuntimeTest, GeneratorFrameCreate) { 2839 const char* src = R"( 2840def gen(): 2841 yield 12 2842)"; 2843 2844 HandleScope scope(thread_); 2845 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 2846 Object gen_obj(&scope, mainModuleAt(runtime_, "gen")); 2847 ASSERT_TRUE(gen_obj.isFunction()); 2848 Function gen(&scope, *gen_obj); 2849 Object frame_obj(&scope, runtime_->newGeneratorFrame(gen)); 2850 ASSERT_TRUE(frame_obj.isGeneratorFrame()); 2851 GeneratorFrame generator_frame(&scope, *frame_obj); 2852 EXPECT_EQ(generator_frame.maxStackSize(), 2853 SmallInt::cast(gen.stacksizeOrBuiltin()).value()); 2854} 2855 2856TEST_F(RuntimeModuleTest, ImportModuleFromInitTab) { 2857 ASSERT_FALSE(runFromCStr(runtime_, "import _empty").isError()); 2858 HandleScope scope(thread_); 2859 Object mod(&scope, mainModuleAt(runtime_, "_empty")); 2860 EXPECT_TRUE(mod.isModule()); 2861} 2862 2863TEST_F(RuntimeModuleTest, NewModuleSetsDictValuesAndModuleProxy) { 2864 HandleScope scope(thread_); 2865 2866 // Create Module 2867 Object name(&scope, runtime_->newStrFromCStr("mymodule")); 2868 Module module(&scope, runtime_->newModule(name)); 2869 Object modules(&scope, runtime_->modules()); 2870 ASSERT_FALSE( 2871 objectSetItem(thread_, modules, name, module).isErrorException()); 2872 2873 Str mod_name(&scope, moduleAtByCStr(runtime_, "mymodule", "__name__")); 2874 EXPECT_TRUE(mod_name.equalsCStr("mymodule")); 2875 EXPECT_EQ(moduleAtByCStr(runtime_, "mymodule", "__doc__"), 2876 NoneType::object()); 2877 EXPECT_EQ(moduleAtByCStr(runtime_, "mymodule", "__package__"), 2878 NoneType::object()); 2879 EXPECT_EQ(moduleAtByCStr(runtime_, "mymodule", "__loader__"), 2880 NoneType::object()); 2881 EXPECT_EQ(moduleAtByCStr(runtime_, "mymodule", "__spec__"), 2882 NoneType::object()); 2883 2884 ModuleProxy module_proxy(&scope, module.moduleProxy()); 2885 EXPECT_EQ(module_proxy.module(), *module); 2886} 2887 2888TEST_F(RuntimeFunctionAttrTest, SetAttribute) { 2889 ASSERT_FALSE(runFromCStr(runtime_, R"( 2890def foo(): pass 2891foo.x = 3 2892)") 2893 .isError()); 2894 HandleScope scope(thread_); 2895 Function function(&scope, mainModuleAt(runtime_, "foo")); 2896 Dict function_dict(&scope, function.dict()); 2897 Str name(&scope, runtime_->newStrFromCStr("x")); 2898 Object value(&scope, dictAtByStr(thread_, function_dict, name)); 2899 EXPECT_TRUE(isIntEqualsWord(*value, 3)); 2900} 2901 2902TEST_F(RuntimeTest, NotMatchingCellAndVarNamesSetsCell2ArgToNone) { 2903 HandleScope scope(thread_); 2904 word argcount = 3; 2905 word kwargcount = 0; 2906 word nlocals = 3; 2907 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 2908 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 2909 Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); 2910 Tuple varnames(&scope, runtime_->newTupleWith3(foo, bar, baz)); 2911 Object foobar(&scope, Runtime::internStrFromCStr(thread_, "foobar")); 2912 Object foobaz(&scope, Runtime::internStrFromCStr(thread_, "foobaz")); 2913 Tuple cellvars(&scope, runtime_->newTupleWith2(foobar, foobaz)); 2914 Object code_code(&scope, Bytes::empty()); 2915 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 2916 Object empty_bytes(&scope, Bytes::empty()); 2917 Object empty_str(&scope, Str::empty()); 2918 Code code(&scope, 2919 runtime_->newCode(argcount, /*posonlyargcount=*/0, kwargcount, 2920 nlocals, /*stacksize=*/0, /*flags=*/0, code_code, 2921 empty_tuple, empty_tuple, varnames, empty_tuple, 2922 cellvars, empty_str, empty_str, 0, empty_bytes)); 2923 EXPECT_TRUE(code.cell2arg().isNoneType()); 2924} 2925 2926TEST_F(RuntimeTest, MatchingCellAndVarNamesCreatesCell2Arg) { 2927 HandleScope scope(thread_); 2928 word argcount = 3; 2929 word kwargcount = 0; 2930 word nlocals = 3; 2931 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 2932 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 2933 Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); 2934 Tuple varnames(&scope, runtime_->newTupleWith3(foo, bar, baz)); 2935 Object foobar(&scope, Runtime::internStrFromCStr(thread_, "foobar")); 2936 Tuple cellvars(&scope, runtime_->newTupleWith2(baz, foobar)); 2937 Object code_code(&scope, Bytes::empty()); 2938 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 2939 Object empty_bytes(&scope, Bytes::empty()); 2940 Object empty_str(&scope, Str::empty()); 2941 Code code(&scope, 2942 runtime_->newCode(argcount, /*posonlyargcount=*/0, kwargcount, 2943 nlocals, /*stacksize=*/0, /*flags=*/0, code_code, 2944 empty_tuple, empty_tuple, varnames, empty_tuple, 2945 cellvars, empty_str, empty_str, 0, empty_bytes)); 2946 ASSERT_FALSE(code.cell2arg().isNoneType()); 2947 Tuple cell2arg(&scope, code.cell2arg()); 2948 ASSERT_EQ(cell2arg.length(), 2); 2949 2950 Object cell2arg_value(&scope, cell2arg.at(0)); 2951 EXPECT_TRUE(isIntEqualsWord(*cell2arg_value, 2)); 2952 EXPECT_EQ(cell2arg.at(1), NoneType::object()); 2953} 2954 2955TEST_F(RuntimeTest, NewCodeWithCellvarsTurnsOffNofreeFlag) { 2956 HandleScope scope(thread_); 2957 word argcount = 3; 2958 word nlocals = 3; 2959 Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); 2960 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); 2961 Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); 2962 Tuple varnames(&scope, runtime_->newTupleWith3(foo, bar, baz)); 2963 Object foobar(&scope, Runtime::internStrFromCStr(thread_, "foobar")); 2964 Tuple cellvars(&scope, runtime_->newTupleWith2(baz, foobar)); 2965 Object code_code(&scope, Bytes::empty()); 2966 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 2967 Object empty_bytes(&scope, Bytes::empty()); 2968 Object empty_str(&scope, Str::empty()); 2969 Code code(&scope, runtime_->newCode( 2970 argcount, /*posonlyargcount=*/0, /*kwonlyargcount=*/0, 2971 nlocals, /*stacksize=*/0, /*flags=*/0, code_code, 2972 empty_tuple, empty_tuple, varnames, empty_tuple, 2973 cellvars, empty_str, empty_str, 0, empty_bytes)); 2974 EXPECT_FALSE(code.flags() & Code::Flags::kNofree); 2975} 2976 2977TEST_F(RuntimeTest, NewCodeWithNoFreevarsOrCellvarsSetsNofreeFlag) { 2978 HandleScope scope(thread_); 2979 Object foobar(&scope, runtime_->newStrFromCStr("foobar")); 2980 Tuple varnames(&scope, runtime_->newTupleWith1(foobar)); 2981 Object code_code(&scope, Bytes::empty()); 2982 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 2983 Object empty_bytes(&scope, Bytes::empty()); 2984 Object empty_str(&scope, Str::empty()); 2985 Object code_obj( 2986 &scope, runtime_->newCode( 2987 /*argcount=*/0, /*posonlyargcount=*/0, /*kwonlyargcount=*/0, 2988 /*nlocals=*/0, /*stacksize=*/0, /*flags=*/0, code_code, 2989 empty_tuple, empty_tuple, varnames, empty_tuple, empty_tuple, 2990 empty_str, empty_str, 0, empty_bytes)); 2991 ASSERT_TRUE(code_obj.isCode()); 2992 Code code(&scope, *code_obj); 2993 EXPECT_TRUE(code.flags() & Code::Flags::kNofree); 2994} 2995 2996TEST_F(RuntimeTest, 2997 NewCodeWithArgcountGreaterThanVarnamesLengthRaisesValueError) { 2998 HandleScope scope(thread_); 2999 Tuple varnames(&scope, newTupleWithNone(1)); 3000 Tuple cellvars(&scope, newTupleWithNone(2)); 3001 Object code_code(&scope, Bytes::empty()); 3002 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 3003 Object empty_bytes(&scope, Bytes::empty()); 3004 Object empty_str(&scope, Str::empty()); 3005 EXPECT_TRUE(raisedWithStr( 3006 runtime_->newCode(/*argcount=*/10, /*posonlyargcount=*/0, 3007 /*kwonlyargcount=*/0, /*nlocals=*/0, /*stacksize=*/0, 3008 /*flags=*/0, code_code, empty_tuple, empty_tuple, 3009 varnames, empty_tuple, cellvars, empty_str, empty_str, 3010 0, empty_bytes), 3011 LayoutId::kValueError, "code: varnames is too small")); 3012} 3013 3014TEST_F(RuntimeTest, 3015 NewCodeWithKwonlyargcountGreaterThanVarnamesLengthRaisesValueError) { 3016 HandleScope scope(thread_); 3017 Tuple varnames(&scope, newTupleWithNone(1)); 3018 Tuple cellvars(&scope, newTupleWithNone(2)); 3019 Object code_code(&scope, Bytes::empty()); 3020 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 3021 Object empty_bytes(&scope, Bytes::empty()); 3022 Object empty_str(&scope, Str::empty()); 3023 EXPECT_TRUE(raisedWithStr( 3024 runtime_->newCode(/*argcount=*/0, /*posonlyargcount=*/0, 3025 /*kwonlyargcount=*/10, /*nlocals=*/0, /*stacksize=*/0, 3026 /*flags=*/0, code_code, empty_tuple, empty_tuple, 3027 varnames, empty_tuple, cellvars, empty_str, empty_str, 3028 0, empty_bytes), 3029 LayoutId::kValueError, "code: varnames is too small")); 3030} 3031 3032TEST_F(RuntimeTest, 3033 NewCodeWithTotalArgsGreaterThanVarnamesLengthRaisesValueError) { 3034 HandleScope scope(thread_); 3035 Tuple varnames(&scope, newTupleWithNone(1)); 3036 Tuple cellvars(&scope, newTupleWithNone(2)); 3037 Object code_code(&scope, Bytes::empty()); 3038 Tuple empty_tuple(&scope, runtime_->emptyTuple()); 3039 Object empty_bytes(&scope, Bytes::empty()); 3040 Object empty_str(&scope, Str::empty()); 3041 EXPECT_TRUE(raisedWithStr( 3042 runtime_->newCode(/*argcount=*/1, /*posonlyargcount=*/0, 3043 /*kwonlyargcount=*/1, /*nlocals=*/0, /*stacksize=*/0, 3044 /*flags=*/0, code_code, empty_tuple, empty_tuple, 3045 varnames, empty_tuple, cellvars, empty_str, empty_str, 3046 0, empty_bytes), 3047 LayoutId::kValueError, "code: varnames is too small")); 3048} 3049 3050TEST_F(RuntimeTest, NewWeakLink) { 3051 HandleScope scope(thread_); 3052 3053 Object referent(&scope, runtime_->newList()); 3054 Object prev(&scope, runtime_->newInt(2)); 3055 Object next(&scope, runtime_->newInt(3)); 3056 WeakLink link(&scope, runtime_->newWeakLink(thread_, referent, prev, next)); 3057 EXPECT_EQ(link.referent(), *referent); 3058 EXPECT_EQ(link.prev(), *prev); 3059 EXPECT_EQ(link.next(), *next); 3060} 3061 3062// Set is not special except that it is a builtin type with sealed attributes. 3063TEST_F(RuntimeTest, SetHasSameSizeCreatedTwoDifferentWays) { 3064 HandleScope scope(thread_); 3065 Layout layout(&scope, runtime_->layoutAt(LayoutId::kSet)); 3066 Set set1(&scope, runtime_->newInstance(layout)); 3067 Set set2(&scope, runtime_->newSet()); 3068 EXPECT_EQ(set1.size(), set2.size()); 3069} 3070 3071// Set is not special except that it is a builtin type with sealed attributes. 3072TEST_F(RuntimeTest, SealedClassLayoutDoesNotHaveSpaceForOverflowAttributes) { 3073 HandleScope scope(thread_); 3074 Layout layout(&scope, runtime_->layoutAt(LayoutId::kSet)); 3075 EXPECT_TRUE(layout.isSealed()); 3076 word expected_set_size = kPointerSize * layout.numInObjectAttributes(); 3077 EXPECT_EQ(layout.instanceSize(), expected_set_size); 3078} 3079 3080TEST_F(RuntimeTest, SettingNewAttributeOnSealedClassRaisesAttributeError) { 3081 HandleScope scope(thread_); 3082 Set set(&scope, runtime_->newSet()); 3083 Str attr(&scope, runtime_->newStrFromCStr("attr")); 3084 Str value(&scope, runtime_->newStrFromCStr("value")); 3085 Object result(&scope, instanceSetAttr(thread_, set, attr, value)); 3086 EXPECT_TRUE(raised(*result, LayoutId::kAttributeError)); 3087} 3088 3089TEST_F(RuntimeTest, InstanceAtPutWithReadOnlyAttributeRaisesAttributeError) { 3090 HandleScope scope(thread_); 3091 3092 LayoutId layout_id = LayoutId::kUserWarning; 3093 Object previous_layout(&scope, runtime_->layoutAt(layout_id)); 3094 BuiltinAttribute attrs[] = { 3095 {ID(__globals__), 0, AttributeFlags::kReadOnly}, 3096 }; 3097 Type type(&scope, addBuiltinType(thread_, ID(UserWarning), layout_id, 3098 LayoutId::kObject, attrs, 3099 /*size=*/kPointerSize, 3100 /*basetype=*/true)); 3101 Layout layout(&scope, type.instanceLayout()); 3102 runtime_->layoutAtPut(layout_id, *layout); 3103 Instance instance(&scope, runtime_->newInstance(layout)); 3104 Str attribute_name(&scope, 3105 Runtime::internStrFromCStr(thread_, "__globals__")); 3106 Object value(&scope, NoneType::object()); 3107 EXPECT_TRUE( 3108 raisedWithStr(instanceSetAttr(thread_, instance, attribute_name, value), 3109 LayoutId::kAttributeError, 3110 "'UserWarning.__globals__' attribute is read-only")); 3111 runtime_->layoutAtPut(layout_id, *previous_layout); 3112} 3113 3114// Exception attributes can be set on the fly. 3115TEST_F(RuntimeTest, NonSealedClassHasSpaceForOverflowAttrbutes) { 3116 HandleScope scope(thread_); 3117 Layout layout(&scope, runtime_->layoutAt(LayoutId::kMemoryError)); 3118 EXPECT_TRUE(layout.hasTupleOverflow()); 3119 EXPECT_EQ(layout.instanceSize(), 3120 (layout.numInObjectAttributes() + 1) * kPointerSize); // 1=overflow 3121} 3122 3123// User-defined class attributes can be set on the fly. 3124TEST_F(RuntimeTest, UserCanSetOverflowAttributeOnUserDefinedClass) { 3125 HandleScope scope(thread_); 3126 ASSERT_FALSE(runFromCStr(runtime_, R"( 3127class C(): pass 3128a = C() 3129)") 3130 .isError()); 3131 Instance a(&scope, mainModuleAt(runtime_, "a")); 3132 Str attr(&scope, runtime_->newStrFromCStr("attr")); 3133 Str value(&scope, runtime_->newStrFromCStr("value")); 3134 Object result(&scope, instanceSetAttr(thread_, a, attr, value)); 3135 ASSERT_FALSE(result.isError()); 3136 EXPECT_EQ(instanceGetAttribute(thread_, a, attr), *value); 3137} 3138 3139TEST_F(RuntimeTest, IsMappingReturnsFalseOnSet) { 3140 HandleScope scope(thread_); 3141 Set set(&scope, runtime_->newSet()); 3142 EXPECT_FALSE(runtime_->isMapping(thread_, set)); 3143} 3144 3145TEST_F(RuntimeTest, IsMappingReturnsTrueOnDict) { 3146 HandleScope scope(thread_); 3147 Dict dict(&scope, runtime_->newDict()); 3148 EXPECT_TRUE(runtime_->isMapping(thread_, dict)); 3149} 3150 3151TEST_F(RuntimeTest, IsMappingReturnsTrueOnList) { 3152 HandleScope scope(thread_); 3153 List list(&scope, runtime_->newList()); 3154 EXPECT_TRUE(runtime_->isMapping(thread_, list)); 3155} 3156 3157TEST_F(RuntimeTest, IsMappingReturnsTrueOnCustomClassWithMethod) { 3158 ASSERT_FALSE(runFromCStr(runtime_, R"( 3159class C(): 3160 def __getitem__(self, key): 3161 pass 3162o = C() 3163)") 3164 .isError()); 3165 HandleScope scope(thread_); 3166 Object obj(&scope, mainModuleAt(runtime_, "o")); 3167 EXPECT_TRUE(runtime_->isMapping(thread_, obj)); 3168} 3169 3170TEST_F(RuntimeTest, IsMappingWithClassAttrNotCallableReturnsTrue) { 3171 ASSERT_FALSE(runFromCStr(runtime_, R"( 3172class C(): 3173 __getitem__ = 4 3174o = C() 3175)") 3176 .isError()); 3177 HandleScope scope(thread_); 3178 Object obj(&scope, mainModuleAt(runtime_, "o")); 3179 EXPECT_TRUE(runtime_->isMapping(thread_, obj)); 3180} 3181 3182TEST_F(RuntimeTest, IsMappingReturnsFalseOnCustomClassWithoutMethod) { 3183 ASSERT_FALSE(runFromCStr(runtime_, R"( 3184class C(): 3185 pass 3186o = C() 3187)") 3188 .isError()); 3189 HandleScope scope(thread_); 3190 Object obj(&scope, mainModuleAt(runtime_, "o")); 3191 EXPECT_FALSE(runtime_->isMapping(thread_, obj)); 3192} 3193 3194TEST_F(RuntimeTest, IsMappingWithInstanceAttrReturnsFalse) { 3195 ASSERT_FALSE(runFromCStr(runtime_, R"( 3196class C(): 3197 pass 3198o = C() 3199o.__getitem__ = 4 3200)") 3201 .isError()); 3202 HandleScope scope(thread_); 3203 Object obj(&scope, mainModuleAt(runtime_, "o")); 3204 EXPECT_FALSE(runtime_->isMapping(thread_, obj)); 3205} 3206 3207TEST_F(RuntimeTest, ModuleBuiltinsExists) { 3208 ASSERT_FALSE(moduleAtByCStr(runtime_, "builtins", "__name__").isError()); 3209} 3210 3211TEST_F(RuntimeTest, ObjectEqualsWithSameObjectReturnsTrue) { 3212 ASSERT_FALSE(runFromCStr(runtime_, R"( 3213class C(): 3214 def __eq__(self, other): 3215 return False 3216i = C() 3217)") 3218 .isError()); 3219 HandleScope scope(thread_); 3220 Object i(&scope, mainModuleAt(runtime_, "i")); 3221 EXPECT_EQ(Runtime::objectEquals(thread_, *i, *i), Bool::trueObj()); 3222} 3223 3224TEST_F(RuntimeTest, ObjectEqualsWithBoolAndSmallInt) { 3225 EXPECT_EQ( 3226 Runtime::objectEquals(thread_, Bool::trueObj(), SmallInt::fromWord(1)), 3227 Bool::trueObj()); 3228 EXPECT_EQ( 3229 Runtime::objectEquals(thread_, Bool::trueObj(), SmallInt::fromWord(0)), 3230 Bool::falseObj()); 3231 EXPECT_EQ( 3232 Runtime::objectEquals(thread_, Bool::trueObj(), SmallInt::fromWord(100)), 3233 Bool::falseObj()); 3234 EXPECT_EQ( 3235 Runtime::objectEquals(thread_, Bool::falseObj(), SmallInt::fromWord(0)), 3236 Bool::trueObj()); 3237 EXPECT_EQ( 3238 Runtime::objectEquals(thread_, Bool::falseObj(), SmallInt::fromWord(1)), 3239 Bool::falseObj()); 3240 EXPECT_EQ( 3241 Runtime::objectEquals(thread_, Bool::falseObj(), SmallInt::fromWord(100)), 3242 Bool::falseObj()); 3243} 3244 3245TEST_F(RuntimeTest, ObjectEqualsWithSmallIntAndBool) { 3246 EXPECT_EQ( 3247 Runtime::objectEquals(thread_, SmallInt::fromWord(1), Bool::trueObj()), 3248 Bool::trueObj()); 3249 EXPECT_EQ( 3250 Runtime::objectEquals(thread_, SmallInt::fromWord(0), Bool::trueObj()), 3251 Bool::falseObj()); 3252 EXPECT_EQ( 3253 Runtime::objectEquals(thread_, SmallInt::fromWord(100), Bool::trueObj()), 3254 Bool::falseObj()); 3255 EXPECT_EQ( 3256 Runtime::objectEquals(thread_, SmallInt::fromWord(0), Bool::falseObj()), 3257 Bool::trueObj()); 3258 EXPECT_EQ( 3259 Runtime::objectEquals(thread_, SmallInt::fromWord(1), Bool::falseObj()), 3260 Bool::falseObj()); 3261 EXPECT_EQ( 3262 Runtime::objectEquals(thread_, SmallInt::fromWord(100), Bool::falseObj()), 3263 Bool::falseObj()); 3264} 3265 3266TEST_F(RuntimeTest, ObjectEqualsCallsDunderEq) { 3267 ASSERT_FALSE(runFromCStr(runtime_, R"( 3268class C: 3269 def __eq__(self, other): 3270 return True 3271i = C() 3272)") 3273 .isError()); 3274 HandleScope scope(thread_); 3275 Object i(&scope, mainModuleAt(runtime_, "i")); 3276 EXPECT_EQ(Runtime::objectEquals(thread_, *i, NoneType::object()), 3277 Bool::trueObj()); 3278 EXPECT_EQ(Runtime::objectEquals(thread_, *i, SmallStr::fromCStr("foo")), 3279 Bool::trueObj()); 3280 EXPECT_EQ(Runtime::objectEquals(thread_, *i, Bool::falseObj()), 3281 Bool::trueObj()); 3282} 3283 3284TEST_F(RuntimeTest, ObjectEqualsCallsStrSubclassDunderEq) { 3285 ASSERT_FALSE(runFromCStr(runtime_, R"( 3286class StrSub(str): 3287 def __eq__(self, other): 3288 return True 3289i = StrSub("foo") 3290)") 3291 .isError()); 3292 3293 HandleScope scope(thread_); 3294 Object i(&scope, mainModuleAt(runtime_, "i")); 3295 EXPECT_EQ(Runtime::objectEquals(thread_, Str::empty(), *i), Bool::trueObj()); 3296 EXPECT_EQ(Runtime::objectEquals(thread_, *i, Str::empty()), Bool::trueObj()); 3297 LargeStr large_str(&scope, runtime_->newStrFromCStr("foobarbazbumbam")); 3298 EXPECT_EQ(Runtime::objectEquals(thread_, *large_str, *i), Bool::trueObj()); 3299 EXPECT_EQ(Runtime::objectEquals(thread_, *i, *large_str), Bool::trueObj()); 3300 EXPECT_EQ(Runtime::objectEquals(thread_, SmallInt::fromWord(0), *i), 3301 Bool::trueObj()); 3302 EXPECT_EQ(Runtime::objectEquals(thread_, *i, SmallInt::fromWord(0)), 3303 Bool::trueObj()); 3304} 3305 3306TEST_F(RuntimeTest, ObjectEqualsCallsIntSubclassDunderEq) { 3307 ASSERT_FALSE(runFromCStr(runtime_, R"( 3308class IntSub(int): 3309 def __eq__(self, other): 3310 return True 3311i = IntSub(7) 3312)") 3313 .isError()); 3314 HandleScope scope(thread_); 3315 Object i(&scope, mainModuleAt(runtime_, "i")); 3316 EXPECT_EQ(Runtime::objectEquals(thread_, SmallInt::fromWord(1), *i), 3317 Bool::trueObj()); 3318 EXPECT_EQ(Runtime::objectEquals(thread_, *i, SmallInt::fromWord(1)), 3319 Bool::trueObj()); 3320 const uword digits[] = {1, 2}; 3321 LargeInt large_int(&scope, runtime_->newLargeIntWithDigits(digits)); 3322 EXPECT_EQ(Runtime::objectEquals(thread_, *i, *large_int), Bool::trueObj()); 3323 EXPECT_EQ(Runtime::objectEquals(thread_, *large_int, *i), Bool::trueObj()); 3324 EXPECT_EQ(Runtime::objectEquals(thread_, *i, Bool::trueObj()), 3325 Bool::trueObj()); 3326 EXPECT_EQ(Runtime::objectEquals(thread_, NoneType::object(), *i), 3327 Bool::trueObj()); 3328 EXPECT_EQ(Runtime::objectEquals(thread_, *i, NoneType::object()), 3329 Bool::trueObj()); 3330 EXPECT_EQ(Runtime::objectEquals(thread_, Bool::trueObj(), *i), 3331 Bool::falseObj()); 3332} 3333 3334TEST_F(RuntimeTest, ObjectEqualsWithSmallStrReturnsBool) { 3335 RawSmallStr s0 = SmallStr::empty(); 3336 RawSmallStr s1 = SmallStr::fromCStr("foo"); 3337 EXPECT_EQ(Runtime::objectEquals(thread_, s0, s0), Bool::trueObj()); 3338 EXPECT_EQ(Runtime::objectEquals(thread_, s0, s1), Bool::falseObj()); 3339 EXPECT_EQ(Runtime::objectEquals(thread_, s1, s0), Bool::falseObj()); 3340 EXPECT_EQ(Runtime::objectEquals(thread_, s1, s1), Bool::trueObj()); 3341 EXPECT_EQ(Runtime::objectEquals(thread_, NoneType::object(), s0), 3342 Bool::falseObj()); 3343 EXPECT_EQ(Runtime::objectEquals(thread_, s0, NoneType::object()), 3344 Bool::falseObj()); 3345} 3346 3347TEST_F(RuntimeTest, ObjectEqualsWithLargeStrReturnsBool) { 3348 HandleScope scope(thread_); 3349 LargeStr large_str0(&scope, runtime_->newStrFromCStr("foobarbazbumbam")); 3350 LargeStr large_str1(&scope, runtime_->newStrFromCStr("foobarbazbumbam")); 3351 ASSERT_NE(large_str0, large_str1); 3352 EXPECT_EQ(Runtime::objectEquals(thread_, *large_str0, *large_str1), 3353 Bool::trueObj()); 3354 EXPECT_EQ(Runtime::objectEquals(thread_, *large_str0, 3355 runtime_->newStrFromCStr("hello world!")), 3356 Bool::falseObj()); 3357} 3358 3359TEST_F(RuntimeTest, ObjectEqualsWithImmediatesReturnsBool) { 3360 EXPECT_EQ( 3361 Runtime::objectEquals(thread_, NoneType::object(), NoneType::object()), 3362 Bool::trueObj()); 3363 EXPECT_EQ(Runtime::objectEquals(thread_, SmallInt::fromWord(-88), 3364 SmallInt::fromWord(-88)), 3365 Bool::trueObj()); 3366 EXPECT_EQ(Runtime::objectEquals(thread_, NoneType::object(), 3367 NotImplementedType::object()), 3368 Bool::falseObj()); 3369 EXPECT_EQ(Runtime::objectEquals(thread_, SmallInt::fromWord(11), 3370 SmallInt::fromWord(-11)), 3371 Bool::falseObj()); 3372} 3373 3374TEST_F(RuntimeTest, ObjectEqualsWithIntAndBoolReturnsBool) { 3375 EXPECT_EQ( 3376 Runtime::objectEquals(thread_, SmallInt::fromWord(0), Bool::falseObj()), 3377 Bool::trueObj()); 3378 EXPECT_EQ( 3379 Runtime::objectEquals(thread_, SmallInt::fromWord(1), Bool::trueObj()), 3380 Bool::trueObj()); 3381 EXPECT_EQ( 3382 Runtime::objectEquals(thread_, Bool::falseObj(), SmallInt::fromWord(0)), 3383 Bool::trueObj()); 3384 EXPECT_EQ( 3385 Runtime::objectEquals(thread_, Bool::trueObj(), SmallInt::fromWord(1)), 3386 Bool::trueObj()); 3387 EXPECT_EQ( 3388 Runtime::objectEquals(thread_, Bool::falseObj(), SmallInt::fromWord(1)), 3389 Bool::falseObj()); 3390 EXPECT_EQ( 3391 Runtime::objectEquals(thread_, SmallInt::fromWord(0), Bool::trueObj()), 3392 Bool::falseObj()); 3393} 3394 3395static ALIGN_16 RawObject testPrintTraceback(Thread* thread, Arguments) { 3396 TemporaryDirectory tempdir; 3397 std::string temp = tempdir.path + "traceback"; 3398 int fd = File::open(temp.c_str(), File::kCreate | File::kWriteOnly, 0777); 3399 DCHECK(fd != -1, "error opening file"); 3400 3401 thread->runtime()->printTraceback(thread, fd); 3402 DCHECK(File::close(fd) == 0, "error closing file"); 3403 3404 word length; 3405 FILE* fp = std::fopen(temp.c_str(), "r"); 3406 unique_c_ptr<byte> traceback(OS::readFile(fp, &length)); 3407 std::fclose(fp); 3408 3409 return thread->runtime()->newStrWithAll(View<byte>(traceback.get(), length)); 3410} 3411 3412TEST_F(RuntimeTest, PrintTracebackPrintsToFileDescriptor) { 3413 addBuiltin("traceback", testPrintTraceback, {nullptr, 0}, 0); 3414 ASSERT_FALSE(runFromCStr(runtime_, R"( 3415def foo(x, y): 3416 # emptyline 3417 result = bar(y, x) 3418 return result 3419def bar(y, x): 3420 local = 42 3421 return traceback() 3422result = foo('a', 99) 3423)") 3424 .isError()); 3425 3426 const char* expected = R"(Stack (most recent call first): 3427 File "", line ??? in traceback 3428 File "<test string>", line 8 in bar 3429 File "<test string>", line 4 in foo 3430 File "<test string>", line 9 in <module> 3431)"; 3432 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), expected)); 3433} 3434 3435TEST_F(RuntimeStrTest, StrJoinWithStrSubclassReturnsJoinedString) { 3436 ASSERT_FALSE(runFromCStr(runtime_, R"( 3437class C(str): 3438 pass 3439elts = (C("a"), C("b"), C("c")) 3440)") 3441 .isError()); 3442 HandleScope scope(thread_); 3443 Str sep(&scope, runtime_->newStrFromCStr(",")); 3444 Tuple elts(&scope, mainModuleAt(runtime_, "elts")); 3445 Object result(&scope, runtime_->strJoin(thread_, sep, elts, elts.length())); 3446 EXPECT_TRUE(isStrEqualsCStr(*result, "a,b,c")); 3447} 3448 3449TEST_F(RuntimeStrTest, StrReplaceWithSmallStrResult) { 3450 HandleScope scope(thread_); 3451 Str str(&scope, runtime_->newStrFromCStr("1212")); 3452 Str old(&scope, runtime_->newStrFromCStr("2")); 3453 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3454 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3455 EXPECT_TRUE(isStrEqualsCStr(*result, "1*1*")); 3456} 3457 3458TEST_F(RuntimeStrTest, StrReplaceWithSmallStrAndNegativeReplacesAll) { 3459 HandleScope scope(thread_); 3460 Str str(&scope, runtime_->newStrFromCStr("122")); 3461 Str old(&scope, runtime_->newStrFromCStr("2")); 3462 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3463 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3464 EXPECT_TRUE(isStrEqualsCStr(*result, "1**")); 3465} 3466 3467TEST_F(RuntimeStrTest, StrReplaceWithLargeStrAndNegativeReplacesAll) { 3468 HandleScope scope(thread_); 3469 Str str(&scope, runtime_->newStrFromCStr("111111121111111111211")); 3470 Str old(&scope, runtime_->newStrFromCStr("2")); 3471 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3472 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3473 EXPECT_TRUE(isStrEqualsCStr(*result, "1111111*1111111111*11")); 3474} 3475 3476TEST_F(RuntimeStrTest, StrReplaceWithLargeStrAndCountReplacesSome) { 3477 HandleScope scope(thread_); 3478 Str str(&scope, runtime_->newStrFromCStr("11112111111111111211")); 3479 Str old(&scope, runtime_->newStrFromCStr("2")); 3480 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3481 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, 1)); 3482 EXPECT_TRUE(isStrEqualsCStr(*result, "1111*111111111111211")); 3483} 3484 3485TEST_F(RuntimeStrTest, StrReplaceWithSameLengthReplacesSubstr) { 3486 HandleScope scope(thread_); 3487 Str str(&scope, runtime_->newStrFromCStr("12")); 3488 Str old(&scope, runtime_->newStrFromCStr("2")); 3489 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3490 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3491 EXPECT_TRUE(isStrEqualsCStr(*result, "1*")); 3492} 3493 3494TEST_F(RuntimeStrTest, StrReplaceWithLongerNewReturnsLonger) { 3495 HandleScope scope(thread_); 3496 Str str(&scope, runtime_->newStrFromCStr("12")); 3497 Str old(&scope, runtime_->newStrFromCStr("2")); 3498 Str newstr(&scope, runtime_->newStrFromCStr("**")); 3499 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3500 EXPECT_TRUE(isStrEqualsCStr(*result, "1**")); 3501} 3502 3503TEST_F(RuntimeStrTest, StrReplaceWithShorterNewReturnsShorter) { 3504 HandleScope scope(thread_); 3505 Str str(&scope, runtime_->newStrFromCStr("12")); 3506 Str old(&scope, runtime_->newStrFromCStr("12")); 3507 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3508 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3509 EXPECT_TRUE(isStrEqualsCStr(*result, "*")); 3510} 3511 3512TEST_F(RuntimeStrTest, StrReplaceWithPrefixReplacesBeginning) { 3513 HandleScope scope(thread_); 3514 Str str(&scope, runtime_->newStrFromCStr("12")); 3515 Str old(&scope, runtime_->newStrFromCStr("1")); 3516 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3517 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3518 EXPECT_TRUE(isStrEqualsCStr(*result, "*2")); 3519} 3520 3521TEST_F(RuntimeStrTest, StrReplaceWithInfixReplacesMiddle) { 3522 HandleScope scope(thread_); 3523 Str str(&scope, runtime_->newStrFromCStr("121")); 3524 Str old(&scope, runtime_->newStrFromCStr("2")); 3525 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3526 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3527 EXPECT_TRUE(isStrEqualsCStr(*result, "1*1")); 3528} 3529 3530TEST_F(RuntimeStrTest, StrReplaceWithPostfixReplacesEnd) { 3531 HandleScope scope(thread_); 3532 Str str(&scope, runtime_->newStrFromCStr("112")); 3533 Str old(&scope, runtime_->newStrFromCStr("2")); 3534 Str newstr(&scope, runtime_->newStrFromCStr("*")); 3535 Object result(&scope, runtime_->strReplace(thread_, str, old, newstr, -1)); 3536 EXPECT_TRUE(isStrEqualsCStr(*result, "11*")); 3537} 3538 3539TEST_F(RuntimeStrTest, StrSliceASCII) { 3540 HandleScope scope(thread_); 3541 Str str(&scope, runtime_->newStrFromCStr("hello world goodbye world")); 3542 Object slice(&scope, runtime_->strSlice(thread_, str, 2, 10, 2)); 3543 EXPECT_TRUE(isStrEqualsCStr(*slice, "lowr")); 3544} 3545 3546TEST_F(RuntimeStrTest, StrSliceUnicode) { 3547 HandleScope scope(thread_); 3548 Str str(&scope, 3549 runtime_->newStrFromCStr( 3550 u8"\u05d0\u05e0\u05d9 \u05dc\u05d0 \u05d0\u05d5\u05d4\u05d1 " 3551 u8"\u05e0\u05d7\u05e9\u05d9\u05dd")); 3552 Str slice(&scope, runtime_->strSlice(thread_, str, 2, 10, 2)); 3553 EXPECT_TRUE(isStrEqualsCStr(*slice, u8"\u05d9\u05dc \u05d5")); 3554} 3555 3556TEST_F(RuntimeStrTest, StrSliceUnicodeWithLargeResult) { 3557 HandleScope scope(thread_); 3558 Str str(&scope, 3559 runtime_->newStrFromCStr( 3560 u8"\u05d0\u05e0\u05d9 \u05dc\u05d0 \u05d0\u05d5\u05d4\u05d1 " 3561 u8"\u05e0\u05d7\u05e9\u05d9\u05dd")); 3562 Str slice(&scope, runtime_->strSlice(thread_, str, 2, 13, 2)); 3563 EXPECT_TRUE(isStrEqualsCStr(*slice, u8"\u05d9\u05dc \u05d5\u05d1\u05e0")); 3564} 3565 3566TEST_F(RuntimeStrTest, StrSliceUnicodeWithStepOne) { 3567 HandleScope scope(thread_); 3568 Str str(&scope, 3569 runtime_->newStrFromCStr(u8"\u05d0\u05e0\u05d9 \u05dc\u05d0 ")); 3570 Str slice(&scope, runtime_->strSlice(thread_, str, 2, 5, 1)); 3571 EXPECT_TRUE(isStrEqualsCStr(*slice, u8"\u05d9 \u05dc")); 3572} 3573 3574TEST_F(RuntimeTest, BuiltinBaseOfNonEmptyTypeIsTypeItself) { 3575 HandleScope scope(thread_); 3576 3577 LayoutId layout_id = LayoutId::kUserWarning; 3578 Object previous_layout(&scope, runtime_->layoutAt(layout_id)); 3579 BuiltinAttribute attrs[] = { 3580 {ID(__globals__), 0, AttributeFlags::kReadOnly}, 3581 }; 3582 Type type(&scope, addBuiltinType(thread_, ID(UserWarning), layout_id, 3583 LayoutId::kObject, attrs, 3584 /*size=*/kPointerSize, /*basetype=*/true)); 3585 EXPECT_EQ(type.builtinBase(), layout_id); 3586 runtime_->layoutAtPut(layout_id, *previous_layout); 3587} 3588 3589TEST_F(RuntimeTest, BuiltinBaseOfEmptyTypeIsSuperclass) { 3590 HandleScope scope(thread_); 3591 3592 LayoutId layout_id = LayoutId::kUserWarning; 3593 Object previous_layout(&scope, runtime_->layoutAt(layout_id)); 3594 Type type(&scope, addBuiltinType(thread_, ID(UserWarning), layout_id, 3595 LayoutId::kObject, kNoAttributes, 3596 HeapObject::kSize, /*basetype=*/true)); 3597 EXPECT_EQ(type.builtinBase(), LayoutId::kObject); 3598 runtime_->layoutAtPut(layout_id, *previous_layout); 3599} 3600 3601TEST_F(RuntimeTest, NonModuleInModulesDoesNotCrash) { 3602 HandleScope scope(thread_); 3603 Object not_a_module(&scope, runtime_->newInt(42)); 3604 Str name(&scope, runtime_->newStrFromCStr("a_valid_module_name")); 3605 Dict modules(&scope, runtime_->modules()); 3606 dictAtPutByStr(thread_, modules, name, not_a_module); 3607 3608 Object result(&scope, runtime_->findModule(name)); 3609 EXPECT_EQ(result, not_a_module); 3610} 3611 3612TEST_F(RuntimeStrArrayTest, AddCodePointAppendsValidUTF8) { 3613 HandleScope scope(thread_); 3614 3615 StrArray array(&scope, runtime_->newStrArray()); 3616 runtime_->strArrayAddCodePoint(thread_, array, 'a'); 3617 runtime_->strArrayAddCodePoint(thread_, array, ' '); 3618 runtime_->strArrayAddCodePoint(thread_, array, 0xe9); 3619 runtime_->strArrayAddCodePoint(thread_, array, ' '); 3620 runtime_->strArrayAddCodePoint(thread_, array, 0x2cc0); 3621 runtime_->strArrayAddCodePoint(thread_, array, ' '); 3622 runtime_->strArrayAddCodePoint(thread_, array, 0x1f192); 3623 3624 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), 3625 "a \u00e9 \u2cc0 \U0001f192")); 3626} 3627 3628TEST_F(RuntimeStrArrayTest, NewStrArrayReturnsEmptyStrArray) { 3629 HandleScope scope(thread_); 3630 Object obj(&scope, runtime_->newStrArray()); 3631 ASSERT_TRUE(obj.isStrArray()); 3632 StrArray str_arr(&scope, *obj); 3633 EXPECT_EQ(str_arr.numItems(), 0); 3634 EXPECT_EQ(str_arr.capacity(), 0); 3635} 3636 3637TEST_F(RuntimeStrArrayTest, EnsureCapacitySetsProperCapacity) { 3638 HandleScope scope(thread_); 3639 3640 StrArray array(&scope, runtime_->newStrArray()); 3641 word length = 1; 3642 word expected_capacity = 16; 3643 runtime_->strArrayEnsureCapacity(thread_, array, length); 3644 EXPECT_EQ(array.capacity(), expected_capacity); 3645 3646 length = 17; 3647 expected_capacity = 24; 3648 runtime_->strArrayEnsureCapacity(thread_, array, length); 3649 EXPECT_EQ(array.capacity(), expected_capacity); 3650 3651 length = 40; 3652 expected_capacity = 40; 3653 runtime_->strArrayEnsureCapacity(thread_, array, length); 3654 EXPECT_EQ(array.capacity(), expected_capacity); 3655} 3656 3657TEST_F(RuntimeStrArrayTest, NewStrFromEmptyStrArrayReturnsEmptyStr) { 3658 HandleScope scope(thread_); 3659 3660 StrArray array(&scope, runtime_->newStrArray()); 3661 EXPECT_EQ(runtime_->strFromStrArray(array), Str::empty()); 3662} 3663 3664TEST_F(RuntimeStrArrayTest, AppendStrAppendsValidUTF8) { 3665 HandleScope scope(thread_); 3666 3667 StrArray array(&scope, runtime_->newStrArray()); 3668 Str one(&scope, runtime_->newStrFromCStr("a\xC3\xA9")); 3669 Str two(&scope, runtime_->newStrFromCStr("\xE2\xB3\x80\xF0\x9F\x86\x92")); 3670 runtime_->strArrayAddStr(thread_, array, one); 3671 runtime_->strArrayAddStr(thread_, array, two); 3672 EXPECT_EQ(array.numItems(), 10); 3673 3674 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), 3675 "a\xC3\xA9\xE2\xB3\x80\xF0\x9F\x86\x92")); 3676} 3677 3678TEST_F(RuntimeStrArrayTest, AddStrArrayAppendsValidUTF8) { 3679 HandleScope scope(thread_); 3680 3681 StrArray array(&scope, runtime_->newStrArray()); 3682 StrArray one(&scope, runtime_->newStrArray()); 3683 Str one_contents(&scope, runtime_->newStrFromCStr("a\xC3\xA9")); 3684 runtime_->strArrayAddStr(thread_, one, one_contents); 3685 StrArray two(&scope, runtime_->newStrArray()); 3686 Str two_contents(&scope, 3687 runtime_->newStrFromCStr("\xE2\xB3\x80\xF0\x9F\x86\x92")); 3688 runtime_->strArrayAddStr(thread_, two, two_contents); 3689 3690 runtime_->strArrayAddStrArray(thread_, array, one); 3691 runtime_->strArrayAddStrArray(thread_, array, two); 3692 EXPECT_EQ(array.numItems(), 10); 3693 3694 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), 3695 "a\xC3\xA9\xE2\xB3\x80\xF0\x9F\x86\x92")); 3696} 3697 3698TEST_F(RuntimeStrArrayTest, AddASCIIAppendsASCII) { 3699 HandleScope scope(thread_); 3700 3701 StrArray array(&scope, runtime_->newStrArray()); 3702 runtime_->strArrayAddASCII(thread_, array, 'h'); 3703 runtime_->strArrayAddASCII(thread_, array, 'i'); 3704 EXPECT_EQ(array.numItems(), 2); 3705 EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(array), "hi")); 3706} 3707 3708TEST(RuntimeTestNoFixture, DestructorRestoresSignalHandlers) { 3709 Runtime* runtime = createTestRuntime(); 3710 EXPECT_NE(OS::signalHandler(SIGINT), SIG_DFL); 3711 delete runtime; 3712 EXPECT_EQ(OS::signalHandler(SIGINT), SIG_DFL); 3713} 3714 3715TEST_F(RuntimeTest, AllocateForMachineCodeReturnsTrue) { 3716 uword address = 0; 3717 EXPECT_TRUE(runtime_->allocateForMachineCode(1 * kKiB, &address)); 3718 EXPECT_NE(address, uword{0}); 3719} 3720 3721TEST_F(RuntimeTest, AllocateForMachineCodeReturnsSequentialAddresses) { 3722 uword address = 0; 3723 runtime_->allocateForMachineCode(1 * kKiB, &address); 3724 EXPECT_NE(address, uword{0}); 3725 uword address2 = 0; 3726 runtime_->allocateForMachineCode(2 * kKiB, &address2); 3727 EXPECT_EQ(address2, address + 1 * kKiB); 3728} 3729 3730} // namespace testing 3731} // namespace py