this repo has no description
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