this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "thread.h"
3
4#include <memory>
5
6#include "gtest/gtest.h"
7
8#include "builtins-module.h"
9#include "bytecode.h"
10#include "compile-utils.h"
11#include "dict-builtins.h"
12#include "frame.h"
13#include "globals.h"
14#include "interpreter.h"
15#include "marshal.h"
16#include "module-builtins.h"
17#include "modules.h"
18#include "runtime.h"
19#include "test-utils.h"
20#include "type-builtins.h"
21
22namespace py {
23namespace testing {
24
25using BuildSlice = RuntimeFixture;
26using BuildString = RuntimeFixture;
27using FormatTest = RuntimeFixture;
28using ListAppendTest = RuntimeFixture;
29using ListInsertTest = RuntimeFixture;
30using ListIterTest = RuntimeFixture;
31using ThreadTest = RuntimeFixture;
32using UnpackList = RuntimeFixture;
33using UnpackSeq = RuntimeFixture;
34
35TEST_F(ThreadTest, CheckMainThreadRuntime) {
36 ASSERT_EQ(thread_->runtime(), runtime_);
37}
38
39TEST_F(ThreadTest, RunEmptyFunction) {
40 HandleScope scope(thread_);
41
42 Object none(&scope, NoneType::object());
43 Tuple consts(&scope, runtime_->newTupleWith1(none));
44 const byte bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0};
45 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
46
47 Thread thread2(runtime_, 1 * kKiB);
48 runtime_->interpreter()->setupThread(&thread2);
49 Thread::setCurrentThread(&thread2);
50 EXPECT_TRUE(runCode(code).isNoneType());
51
52 // Avoid assertion in runtime destructor.
53 Thread::setCurrentThread(thread_);
54}
55
56TEST_F(ThreadTest, ModuleBodyCallsHelloWorldFunction) {
57 ASSERT_FALSE(runFromCStr(runtime_, R"(
58def hello():
59 return 'hello, world'
60result = hello()
61)")
62 .isError());
63 EXPECT_TRUE(
64 isStrEqualsCStr(mainModuleAt(runtime_, "result"), "hello, world"));
65}
66
67TEST_F(ThreadTest, DunderCallInstance) {
68 HandleScope scope(thread_);
69
70 const char* src = R"(
71class C:
72 def __init__(self, x, y):
73 self.value = x + y
74 def __call__(self, y):
75 return self.value * y
76c = C(10, 2)
77g = c(3)
78)";
79
80 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
81
82 Object global(&scope, mainModuleAt(runtime_, "g"));
83 EXPECT_TRUE(isIntEqualsWord(*global, 36));
84}
85
86TEST_F(ThreadTest, DunderCallInstanceWithDescriptor) {
87 HandleScope scope(thread_);
88 const char* src = R"(
89result = None
90
91def stage2(x):
92 global result
93 result = x
94
95class Stage1:
96 def __get__(self, instance, owner):
97 return stage2
98
99class Stage0:
100 __call__ = Stage1()
101
102c = Stage0()
103c(1111)
104)";
105 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
106 Object result(&scope, mainModuleAt(runtime_, "result"));
107 EXPECT_TRUE(isIntEqualsWord(*result, 1111));
108}
109
110TEST_F(ThreadTest, DunderCallInstanceKw) {
111 HandleScope scope(thread_);
112 const char* src = R"(
113class C:
114 def __init__(self):
115 self.value = None
116
117 def __call__(self, y):
118 return y
119
120c = C()
121result = c(y=3)
122)";
123 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
124
125 Object result(&scope, mainModuleAt(runtime_, "result"));
126 EXPECT_TRUE(isIntEqualsWord(*result, 3));
127}
128
129TEST_F(ThreadTest, DunderCallInstanceSplatArgs) {
130 HandleScope scope(thread_);
131 const char* src = R"(
132class C:
133 def __call__(self, y):
134 return y
135
136c = C()
137args = (3,)
138result = c(*args)
139)";
140 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
141
142 Object result(&scope, mainModuleAt(runtime_, "result"));
143 EXPECT_TRUE(isIntEqualsWord(*result, 3));
144}
145
146TEST_F(ThreadTest, DunderCallInstanceSplatKw) {
147 HandleScope scope(thread_);
148 const char* src = R"(
149class C:
150 def __call__(self, y):
151 return y
152
153c = C()
154kwargs = {'y': 3}
155result = c(**kwargs)
156)";
157 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
158
159 Object result(&scope, mainModuleAt(runtime_, "result"));
160 EXPECT_TRUE(isIntEqualsWord(*result, 3));
161}
162
163TEST_F(ThreadTest, DunderCallInstanceSplatArgsAndKw) {
164 HandleScope scope(thread_);
165 const char* src = R"(
166result_x = None
167result_y = None
168class C:
169 def __call__(self, x, y):
170 global result_x
171 global result_y
172 result_x = x
173 result_y = y
174
175c = C()
176args = (1,)
177kwargs = {'y': 3}
178c(*args, **kwargs)
179)";
180 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
181
182 Object result_x(&scope, mainModuleAt(runtime_, "result_x"));
183 EXPECT_TRUE(isIntEqualsWord(*result_x, 1));
184 Object result_y(&scope, mainModuleAt(runtime_, "result_y"));
185 EXPECT_TRUE(isIntEqualsWord(*result_y, 3));
186}
187
188TEST_F(ThreadTest, OverlappingFrames) {
189 HandleScope scope(thread_);
190
191 // Push a frame for a code object with space for 3 items on the value stack
192 Object name(&scope, Str::empty());
193 Code caller_code(&scope, newCodeWithBytes(View<byte>(nullptr, 0)));
194 caller_code.setStacksize(3);
195
196 Module module(&scope, findMainModule(runtime_));
197 Function caller(&scope, runtime_->newFunctionWithCode(thread_, name,
198 caller_code, module));
199
200 thread_->stackPush(*caller);
201 thread_->pushCallFrame(*caller);
202
203 // Push a frame for a code object that expects 3 arguments and needs space
204 // for 3 local variables
205 Locals locals;
206 locals.argcount = 3;
207 Tuple consts(&scope, runtime_->emptyTuple());
208 Tuple names(&scope, runtime_->emptyTuple());
209 Code code(&scope, newCodeWithBytesConstsNamesLocals(View<byte>(nullptr, 0),
210 consts, names, &locals));
211
212 Function function(&scope,
213 runtime_->newFunctionWithCode(thread_, name, code, module));
214
215 // Push args on the stack in the sequence generated by CPython
216 thread_->stackPush(*function);
217 thread_->stackPush(runtime_->newInt(1111));
218 thread_->stackPush(runtime_->newInt(2222));
219 thread_->stackPush(runtime_->newInt(3333));
220 Frame* frame = thread_->pushCallFrame(*function);
221
222 // Make sure we can read the args from the frame
223 EXPECT_TRUE(isIntEqualsWord(frame->local(0), 1111));
224 EXPECT_TRUE(isIntEqualsWord(frame->local(1), 2222));
225 EXPECT_TRUE(isIntEqualsWord(frame->local(2), 3333));
226}
227
228TEST_F(ThreadTest, EncodeTryBlock) {
229 TryBlock block(TryBlock::kExceptHandler, 200, 300);
230 EXPECT_EQ(block.kind(), TryBlock::kExceptHandler);
231 EXPECT_EQ(block.handler(), 200);
232 EXPECT_EQ(block.level(), 300);
233
234 TryBlock decoded(block.asSmallInt());
235 EXPECT_EQ(decoded.kind(), block.kind());
236 EXPECT_EQ(decoded.handler(), block.handler());
237 EXPECT_EQ(decoded.level(), block.level());
238}
239
240TEST_F(ThreadTest, PushPopFrame) {
241 HandleScope scope(thread_);
242
243 Tuple consts(&scope, runtime_->emptyTuple());
244 Tuple names(&scope, runtime_->emptyTuple());
245 Locals locals;
246 locals.varcount = 2;
247 Code code(&scope, newCodeWithBytesConstsNamesLocals(View<byte>(nullptr, 0),
248 consts, names, &locals));
249
250 Module module(&scope, findMainModule(runtime_));
251 Object name(&scope, Str::empty());
252 Function function(&scope,
253 runtime_->newFunctionWithCode(thread_, name, code, module));
254
255 RawObject* prev_sp = thread_->stackPointer();
256 thread_->stackPush(*function);
257 Frame* frame = thread_->pushCallFrame(*function);
258
259 // Verify frame invariants post-push
260 EXPECT_TRUE(frame->previousFrame()->isSentinel());
261 EXPECT_EQ(thread_->stackPointer(), reinterpret_cast<RawObject*>(frame));
262 EXPECT_EQ(thread_->valueStackBase(), thread_->stackPointer());
263
264 // Make sure we restore the thread's stack pointer back to its previous
265 // location
266 thread_->popFrame();
267 EXPECT_EQ(thread_->stackPointer(), prev_sp);
268}
269
270TEST_F(ThreadTest, PushFrameWithNoCellVars) {
271 HandleScope scope(thread_);
272
273 Code code(&scope, newCodeWithBytes(View<byte>(nullptr, 0)));
274 Module module(&scope, findMainModule(runtime_));
275 Object name(&scope, Str::empty());
276 Function function(&scope,
277 runtime_->newFunctionWithCode(thread_, name, code, module));
278 thread_->stackPush(*function);
279 byte* prev_sp = reinterpret_cast<byte*>(thread_->stackPointer());
280 thread_->pushCallFrame(*function);
281
282 EXPECT_EQ(reinterpret_cast<byte*>(thread_->stackPointer()),
283 prev_sp - Frame::kSize);
284}
285
286TEST_F(ThreadTest, PushFrameWithNoFreeVars) {
287 HandleScope scope(thread_);
288
289 Code code(&scope, newCodeWithBytes(View<byte>(nullptr, 0)));
290 Module module(&scope, findMainModule(runtime_));
291 Object name(&scope, Str::empty());
292 Function function(&scope,
293 runtime_->newFunctionWithCode(thread_, name, code, module));
294 thread_->stackPush(*function);
295 byte* prev_sp = reinterpret_cast<byte*>(thread_->stackPointer());
296 thread_->pushCallFrame(*function);
297
298 EXPECT_EQ(reinterpret_cast<byte*>(thread_->stackPointer()),
299 prev_sp - Frame::kSize);
300}
301
302TEST_F(ThreadTest, ManipulateValueStack) {
303 // Push 3 items on the value stack
304 RawObject* sp = thread_->stackPointer();
305 *--sp = SmallInt::fromWord(1111);
306 *--sp = SmallInt::fromWord(2222);
307 *--sp = SmallInt::fromWord(3333);
308 thread_->setStackPointer(sp);
309 ASSERT_EQ(thread_->stackPointer(), sp);
310
311 // Verify the value stack is laid out as we expect
312 EXPECT_TRUE(isIntEqualsWord(thread_->stackPeek(0), 3333));
313 EXPECT_TRUE(isIntEqualsWord(thread_->stackPeek(1), 2222));
314 EXPECT_TRUE(isIntEqualsWord(thread_->stackPeek(2), 1111));
315
316 // Pop 2 items off the stack and check the stack is still as we expect
317 thread_->setStackPointer(sp + 2);
318 EXPECT_TRUE(isIntEqualsWord(thread_->stackPeek(0), 1111));
319}
320
321TEST_F(ThreadTest, ManipulateBlockStack) {
322 Frame* frame = thread_->currentFrame();
323
324 TryBlock pushed1(TryBlock::kFinally, 100, 10);
325 frame->blockStackPush(pushed1);
326
327 TryBlock pushed2(TryBlock::kExceptHandler, 200, 20);
328 frame->blockStackPush(pushed2);
329
330 TryBlock popped2 = frame->blockStackPop();
331 EXPECT_EQ(popped2.kind(), pushed2.kind());
332 EXPECT_EQ(popped2.handler(), pushed2.handler());
333 EXPECT_EQ(popped2.level(), pushed2.level());
334
335 TryBlock popped1 = frame->blockStackPop();
336 EXPECT_EQ(popped1.kind(), pushed1.kind());
337 EXPECT_EQ(popped1.handler(), pushed1.handler());
338 EXPECT_EQ(popped1.level(), pushed1.level());
339}
340
341TEST_F(ThreadTest, CallFunction) {
342 HandleScope scope(thread_);
343
344 // Build the code object for the following function
345 //
346 // def noop(arg0, arg1):
347 // return 2222
348 //
349 Locals locals;
350 locals.argcount = 2;
351 Object obj(&scope, runtime_->newInt(2222));
352 Tuple callee_consts(&scope, runtime_->newTupleWith1(obj));
353 Tuple names(&scope, runtime_->emptyTuple());
354 const byte callee_bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0};
355 Code callee_code(&scope, newCodeWithBytesConstsNamesLocals(
356 callee_bytecode, callee_consts, names, &locals));
357
358 // Create the function object and bind it to the code object
359 Object qualname(&scope, Str::empty());
360 Module module(&scope, findMainModule(runtime_));
361 Function callee(&scope, runtime_->newFunctionWithCode(thread_, qualname,
362 callee_code, module));
363
364 // Build a code object to call the function defined above
365 Object obj1(&scope, SmallInt::fromWord(1111));
366 Object obj2(&scope, SmallInt::fromWord(2222));
367 Tuple caller_consts(&scope, runtime_->newTupleWith3(callee, obj1, obj2));
368 const byte caller_bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1,
369 LOAD_CONST, 2, CALL_FUNCTION, 2,
370 RETURN_VALUE, 0};
371 Code caller_code(&scope,
372 newCodeWithBytesConsts(caller_bytecode, caller_consts));
373
374 // Execute the caller and make sure we get back the expected result
375 EXPECT_TRUE(isIntEqualsWord(runCode(caller_code), 2222));
376}
377
378TEST_F(ThreadTest, ExtendedArg) {
379 HandleScope scope(thread_);
380
381 const word num_consts = 258;
382 const byte bytecode[] = {EXTENDED_ARG, 1, LOAD_CONST, 1, RETURN_VALUE, 0};
383
384 MutableTuple constants(&scope, runtime_->newMutableTuple(num_consts));
385
386 auto zero = SmallInt::fromWord(0);
387 auto non_zero = SmallInt::fromWord(0xDEADBEEF);
388 for (word i = 0; i < num_consts - 2; i++) {
389 constants.atPut(i, zero);
390 }
391 constants.atPut(num_consts - 1, non_zero);
392 Tuple consts(&scope, constants.becomeImmutable());
393 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
394
395 EXPECT_TRUE(isIntEqualsWord(runCode(code), 0xDEADBEEF));
396}
397
398TEST_F(ThreadTest, ExecuteDupTop) {
399 HandleScope scope(thread_);
400
401 Object obj(&scope, SmallInt::fromWord(1111));
402 Tuple consts(&scope, runtime_->newTupleWith1(obj));
403 const byte bytecode[] = {LOAD_CONST, 0, DUP_TOP, 0, RETURN_VALUE, 0};
404 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
405
406 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
407}
408
409TEST_F(ThreadTest, ExecuteDupTopTwo) {
410 HandleScope scope(thread_);
411
412 Object obj1(&scope, SmallInt::fromWord(1111));
413 Object obj2(&scope, SmallInt::fromWord(2222));
414 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
415 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1,
416 DUP_TOP_TWO, 0, RETURN_VALUE, 0};
417 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
418
419 EXPECT_TRUE(isIntEqualsWord(runCode(code), 2222));
420}
421
422TEST_F(ThreadTest, ExecuteRotTwo) {
423 HandleScope scope(thread_);
424
425 Object obj1(&scope, SmallInt::fromWord(1111));
426 Object obj2(&scope, SmallInt::fromWord(2222));
427 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
428 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1,
429 ROT_TWO, 0, RETURN_VALUE, 0};
430 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
431
432 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
433}
434
435TEST_F(ThreadTest, ExecuteRotThree) {
436 HandleScope scope(thread_);
437
438 Object obj1(&scope, SmallInt::fromWord(1111));
439 Object obj2(&scope, SmallInt::fromWord(2222));
440 Object obj3(&scope, SmallInt::fromWord(3333));
441 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3));
442 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2,
443 ROT_THREE, 0, RETURN_VALUE, 0};
444 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
445
446 EXPECT_TRUE(isIntEqualsWord(runCode(code), 2222));
447}
448
449TEST_F(ThreadTest, ExecuteRotFour) {
450 HandleScope scope(thread_);
451
452 Object obj1(&scope, SmallInt::fromWord(1111));
453 Object obj2(&scope, SmallInt::fromWord(2222));
454 Object obj3(&scope, SmallInt::fromWord(3333));
455 Object obj4(&scope, SmallInt::fromWord(4444));
456 Tuple consts(&scope, runtime_->newTupleWith4(obj1, obj2, obj3, obj4));
457 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2,
458 LOAD_CONST, 3, ROT_FOUR, 0, RETURN_VALUE, 0};
459 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
460
461 EXPECT_TRUE(isIntEqualsWord(runCode(code), 3333));
462}
463
464TEST_F(ThreadTest, ExecuteJumpAbsolute) {
465 HandleScope scope(thread_);
466
467 Object obj1(&scope, SmallInt::fromWord(1111));
468 Object obj2(&scope, SmallInt::fromWord(2222));
469 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
470 const byte bytecode[] = {JUMP_ABSOLUTE, 4, LOAD_CONST, 0,
471 LOAD_CONST, 1, RETURN_VALUE, 0};
472 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
473
474 EXPECT_TRUE(isIntEqualsWord(runCode(code), 2222));
475}
476
477TEST_F(ThreadTest, ExecuteJumpForward) {
478 HandleScope scope(thread_);
479
480 Object obj1(&scope, SmallInt::fromWord(1111));
481 Object obj2(&scope, SmallInt::fromWord(2222));
482 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
483 const byte bytecode[] = {JUMP_FORWARD, 2, LOAD_CONST, 0,
484 LOAD_CONST, 1, RETURN_VALUE, 0};
485 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
486
487 EXPECT_TRUE(isIntEqualsWord(runCode(code), 2222));
488}
489
490TEST_F(ThreadTest, ExecuteStoreLoadFast) {
491 HandleScope scope(thread_);
492
493 Object obj(&scope, SmallInt::fromWord(1111));
494 Tuple consts(&scope, runtime_->newTupleWith1(obj));
495 Tuple names(&scope, runtime_->emptyTuple());
496 Locals locals;
497 locals.varcount = 2;
498 const byte bytecode[] = {LOAD_CONST, 0, STORE_FAST, 1,
499 LOAD_FAST, 1, RETURN_VALUE, 0};
500 Code code(&scope, newCodeWithBytesConstsNamesLocals(bytecode, consts, names,
501 &locals));
502
503 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
504}
505
506TEST_F(ThreadTest, LoadGlobal) {
507 HandleScope scope(thread_);
508
509 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
510 Tuple names(&scope, runtime_->newTupleWith1(name));
511 Tuple consts(&scope, runtime_->emptyTuple());
512 const byte bytecode[] = {LOAD_GLOBAL, 0, RETURN_VALUE, 0};
513 Code code(&scope,
514 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
515
516 Module module(&scope, findMainModule(runtime_));
517 Object value(&scope, runtime_->newInt(1234));
518 moduleAtPut(thread_, module, name, value);
519
520 Object none(&scope, NoneType::object());
521 EXPECT_TRUE(isIntEqualsWord(thread_->exec(code, module, none), 1234));
522}
523
524TEST_F(ThreadTest, StoreGlobalCreateValueCell) {
525 HandleScope scope(thread_);
526
527 Object obj(&scope, SmallInt::fromWord(42));
528 Tuple consts(&scope, runtime_->newTupleWith1(obj));
529 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
530 Tuple names(&scope, runtime_->newTupleWith1(name));
531 const byte bytecode[] = {LOAD_CONST, 0, STORE_GLOBAL, 0,
532 LOAD_CONST, 0, RETURN_VALUE, 0};
533 Code code(&scope,
534 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
535
536 Module module(&scope, findMainModule(runtime_));
537 Object none(&scope, NoneType::object());
538 EXPECT_TRUE(isIntEqualsWord(thread_->exec(code, module, none), 42));
539 EXPECT_TRUE(isIntEqualsWord(moduleAt(module, name), 42));
540}
541
542TEST_F(ThreadTest, StoreGlobalReuseValueCell) {
543 HandleScope scope(thread_);
544
545 Object obj(&scope, SmallInt::fromWord(42));
546 Tuple consts(&scope, runtime_->newTupleWith1(obj));
547 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
548 Tuple names(&scope, runtime_->newTupleWith1(name));
549 const byte bytecode[] = {LOAD_CONST, 0, STORE_GLOBAL, 0,
550 LOAD_CONST, 0, RETURN_VALUE, 0};
551 Code code(&scope,
552 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
553
554 Module module(&scope, findMainModule(runtime_));
555 Object value(&scope, runtime_->newInt(99));
556 moduleAtPut(thread_, module, name, value);
557 Object none(&scope, NoneType::object());
558 EXPECT_TRUE(isIntEqualsWord(thread_->exec(code, module, none), 42));
559 EXPECT_TRUE(isIntEqualsWord(moduleAt(module, name), 42));
560}
561
562TEST_F(ThreadTest, LoadNameInModuleBodyFromBuiltins) {
563 HandleScope scope(thread_);
564
565 Tuple consts(&scope, runtime_->emptyTuple());
566 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
567 Tuple names(&scope, runtime_->newTupleWith1(name));
568 const byte bytecode[] = {LOAD_NAME, 0, RETURN_VALUE, 0};
569 Code code(&scope,
570 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
571
572 Object builtins_name(&scope, runtime_->symbols()->at(ID(builtins)));
573 Module builtins(&scope, runtime_->newModule(builtins_name));
574 Module module(&scope, findMainModule(runtime_));
575 moduleAtPutById(thread_, module, ID(__builtins__), builtins);
576 Object value(&scope, runtime_->newInt(123));
577 moduleAtPut(thread_, builtins, name, value);
578 Dict locals(&scope, runtime_->newDict());
579 EXPECT_TRUE(isIntEqualsWord(thread_->exec(code, module, locals), 123));
580}
581
582TEST_F(ThreadTest, LoadNameFromGlobals) {
583 HandleScope scope(thread_);
584
585 Tuple consts(&scope, runtime_->emptyTuple());
586 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
587 Tuple names(&scope, runtime_->newTupleWith1(name));
588 const byte bytecode[] = {LOAD_NAME, 0, RETURN_VALUE, 0};
589 Code code(&scope,
590 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
591
592 Module module(&scope, findMainModule(runtime_));
593 Object value(&scope, runtime_->newInt(321));
594 moduleAtPut(thread_, module, name, value);
595 Dict locals(&scope, runtime_->newDict());
596
597 EXPECT_TRUE(isIntEqualsWord(thread_->exec(code, module, locals), 321));
598}
599
600TEST_F(ThreadTest, LoadNameFromLocals) {
601 HandleScope scope(thread_);
602
603 Tuple consts(&scope, runtime_->emptyTuple());
604 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
605 Tuple names(&scope, runtime_->newTupleWith1(name));
606 const byte bytecode[] = {LOAD_NAME, 0, RETURN_VALUE, 0};
607 Code code(&scope,
608 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
609
610 Module module(&scope, findMainModule(runtime_));
611 Object globals_value(&scope, runtime_->newInt(456));
612 moduleAtPut(thread_, module, name, globals_value);
613 Dict locals(&scope, runtime_->newDict());
614 Object locals_value(&scope, runtime_->newInt(654));
615 dictAtPutByStr(thread_, locals, name, locals_value);
616 EXPECT_TRUE(isIntEqualsWord(thread_->exec(code, module, locals), 654));
617}
618
619TEST_F(ThreadTest, MakeFunction) {
620 HandleScope scope(thread_);
621
622 Code func_code(&scope, newCodeWithBytes(View<byte>(nullptr, 0)));
623 func_code.setName(runtime_->newStrFromCStr("hello"));
624
625 Object obj1(&scope, runtime_->newStrFromCStr("hello_qualname"));
626 Object obj2(&scope, NoneType::object());
627 Tuple consts(&scope, runtime_->newTupleWith3(func_code, obj1, obj2));
628
629 Object name(&scope, runtime_->newStrFromCStr("hello"));
630 Tuple names(&scope, runtime_->newTupleWith1(name));
631
632 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1, MAKE_FUNCTION, 0,
633 STORE_NAME, 0, LOAD_CONST, 2, RETURN_VALUE, 0};
634 Code code(&scope,
635 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
636
637 Module module(&scope, findMainModule(runtime_));
638 Dict locals(&scope, runtime_->newDict());
639 ASSERT_TRUE(thread_->exec(code, module, locals).isNoneType());
640
641 Object function_obj(&scope, dictAtByStr(thread_, locals, name));
642 ASSERT_TRUE(function_obj.isFunction());
643 Function function(&scope, *function_obj);
644 EXPECT_EQ(function.code(), func_code);
645 EXPECT_TRUE(isStrEqualsCStr(function.name(), "hello"));
646 EXPECT_TRUE(isStrEqualsCStr(function.qualname(), "hello_qualname"));
647 EXPECT_EQ(function.entry(), &interpreterTrampoline);
648}
649
650TEST_F(ThreadTest, BuildList) {
651 HandleScope scope(thread_);
652
653 Object obj1(&scope, SmallInt::fromWord(111));
654 Object obj2(&scope, runtime_->newStrFromCStr("qqq"));
655 Object obj3(&scope, NoneType::object());
656 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3));
657
658 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2,
659 BUILD_LIST, 3, RETURN_VALUE, 0};
660 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
661
662 Object result_obj(&scope, runCode(code));
663 ASSERT_TRUE(result_obj.isList());
664 List list(&scope, *result_obj);
665 EXPECT_EQ(list.numItems(), 3);
666 EXPECT_TRUE(isIntEqualsWord(list.at(0), 111));
667 EXPECT_TRUE(isStrEqualsCStr(list.at(1), "qqq"));
668 EXPECT_TRUE(list.at(2).isNoneType());
669}
670
671TEST_F(ThreadTest, BuildSetEmpty) {
672 HandleScope scope(thread_);
673
674 const byte bytecode[] = {BUILD_SET, 0, RETURN_VALUE, 0};
675 Code code(&scope, newCodeWithBytes(bytecode));
676
677 Object result_obj(&scope, runCode(code));
678 ASSERT_TRUE(result_obj.isSet());
679 Set result(&scope, *result_obj);
680 EXPECT_EQ(result.numItems(), 0);
681}
682
683TEST_F(ThreadTest, BuildSetWithOneItem) {
684 HandleScope scope(thread_);
685
686 Object obj(&scope, runtime_->newInt(111));
687 Tuple consts(&scope, runtime_->newTupleWith2(obj, obj)); // dup
688 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1,
689 BUILD_SET, 2, RETURN_VALUE, 0};
690 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
691
692 Object result_obj(&scope, runCode(code));
693 ASSERT_TRUE(result_obj.isSet());
694 Set result(&scope, *result_obj);
695 EXPECT_EQ(result.numItems(), 1);
696 Object int_val(&scope, SmallInt::fromWord(111));
697 EXPECT_TRUE(setIncludes(thread_, result, int_val));
698}
699
700TEST_F(ThreadTest, BuildSet) {
701 HandleScope scope(thread_);
702
703 Object obj1(&scope, runtime_->newInt(111));
704 Object obj2(&scope, runtime_->newStrFromCStr("qqq"));
705 Object obj3(&scope, NoneType::object());
706 Tuple consts(&scope, runtime_->newTupleWith4(obj1, obj1, obj2, obj3)); // dup
707 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2,
708 LOAD_CONST, 3, BUILD_SET, 4, RETURN_VALUE, 0};
709 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
710
711 Object result_obj(&scope, runCode(code));
712 ASSERT_TRUE(result_obj.isSet());
713 Set result(&scope, *result_obj);
714 EXPECT_EQ(result.numItems(), 3);
715 Object int_val(&scope, runtime_->newInt(111));
716 EXPECT_TRUE(setIncludes(thread_, result, int_val));
717 Object str(&scope, runtime_->newStrFromCStr("qqq"));
718 EXPECT_TRUE(setIncludes(thread_, result, str));
719 Object none(&scope, NoneType::object());
720 EXPECT_TRUE(setIncludes(thread_, result, none));
721}
722
723TEST_F(ThreadTest, PopJumpIfFalseWithTruthy) {
724 HandleScope scope(thread_);
725
726 Object obj1(&scope, Bool::trueObj());
727 Object obj2(&scope, SmallInt::fromWord(1111));
728 Object obj3(&scope, SmallInt::fromWord(2222));
729 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3));
730 // Bytecode for the snippet:
731 // if x:
732 // return 1111
733 // return 2222
734 const byte bytecode[] = {LOAD_CONST, 0, POP_JUMP_IF_FALSE, 8,
735 LOAD_CONST, 1, RETURN_VALUE, 0,
736 LOAD_CONST, 2, RETURN_VALUE, 0};
737 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
738
739 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
740}
741
742TEST_F(ThreadTest, PopJumpIfFalseWithFalsey) {
743 HandleScope scope(thread_);
744
745 Object obj1(&scope, Bool::falseObj());
746 Object obj2(&scope, SmallInt::fromWord(1111));
747 Object obj3(&scope, SmallInt::fromWord(2222));
748 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3));
749 // Bytecode for the snippet:
750 // if x:
751 // return 1111
752 // return 2222
753 const byte bytecode[] = {LOAD_CONST, 0, POP_JUMP_IF_FALSE, 8,
754 LOAD_CONST, 1, RETURN_VALUE, 0,
755 LOAD_CONST, 2, RETURN_VALUE, 0};
756 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
757
758 EXPECT_TRUE(isIntEqualsWord(runCode(code), 2222));
759}
760
761TEST_F(ThreadTest, PopJumpIfTrueWithFalsey) {
762 HandleScope scope(thread_);
763
764 Object obj1(&scope, Bool::falseObj());
765 Object obj2(&scope, SmallInt::fromWord(1111));
766 Object obj3(&scope, SmallInt::fromWord(2222));
767 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3));
768 // Bytecode for the snippet:
769 // if not x:
770 // return 1111
771 // return 2222
772 const byte bytecode[] = {LOAD_CONST, 0, POP_JUMP_IF_TRUE, 8,
773 LOAD_CONST, 1, RETURN_VALUE, 0,
774 LOAD_CONST, 2, RETURN_VALUE, 0};
775 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
776
777 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
778}
779
780TEST_F(ThreadTest, PopJumpIfTrueWithTruthy) {
781 HandleScope scope(thread_);
782
783 Object obj1(&scope, Bool::trueObj());
784 Object obj2(&scope, SmallInt::fromWord(1111));
785 Object obj3(&scope, SmallInt::fromWord(2222));
786 Tuple consts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3));
787 // Bytecode for the snippet:
788 // if not x:
789 // return 1111
790 // return 2222
791 const byte bytecode[] = {LOAD_CONST, 0, POP_JUMP_IF_TRUE, 8,
792 LOAD_CONST, 1, RETURN_VALUE, 0,
793 LOAD_CONST, 2, RETURN_VALUE, 0};
794 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
795
796 EXPECT_TRUE(isIntEqualsWord(runCode(code), 2222));
797}
798
799TEST_F(ThreadTest, JumpIfFalseOrPopWithFalsey) {
800 HandleScope scope(thread_);
801
802 Object obj1(&scope, Bool::falseObj());
803 Object obj2(&scope, SmallInt::fromWord(1111));
804 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
805 const byte bytecode[] = {LOAD_CONST, 0, JUMP_IF_FALSE_OR_POP, 6,
806 LOAD_CONST, 1, RETURN_VALUE, 0};
807 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
808
809 // If the condition is false, we should return the top of the stack, which is
810 // the condition itself
811 EXPECT_EQ(runCode(code), Bool::falseObj());
812}
813
814TEST_F(ThreadTest, JumpIfFalseOrPopWithTruthy) {
815 HandleScope scope(thread_);
816
817 Object obj1(&scope, Bool::trueObj());
818 Object obj2(&scope, SmallInt::fromWord(1111));
819 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
820 const byte bytecode[] = {LOAD_CONST, 0, JUMP_IF_FALSE_OR_POP, 6,
821 LOAD_CONST, 1, RETURN_VALUE, 0};
822 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
823
824 // If the condition is true, we should pop the top of the stack (the
825 // condition) and continue execution. In our case that loads a const and
826 // returns it.
827 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
828}
829
830TEST_F(ThreadTest, JumpIfTrueOrPopWithTruthy) {
831 HandleScope scope(thread_);
832
833 Object obj1(&scope, Bool::trueObj());
834 Object obj2(&scope, SmallInt::fromWord(1111));
835 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
836 const byte bytecode[] = {LOAD_CONST, 0, JUMP_IF_TRUE_OR_POP, 6,
837 LOAD_CONST, 1, RETURN_VALUE, 0};
838 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
839
840 // If the condition is true, we should return the top of the stack, which is
841 // the condition itself
842 EXPECT_EQ(runCode(code), Bool::trueObj());
843}
844
845TEST_F(ThreadTest, JumpIfTrueOrPopWithFalsey) {
846 HandleScope scope(thread_);
847
848 Object obj1(&scope, Bool::falseObj());
849 Object obj2(&scope, SmallInt::fromWord(1111));
850 Tuple consts(&scope, runtime_->newTupleWith2(obj1, obj2));
851 const byte bytecode[] = {LOAD_CONST, 0, JUMP_IF_TRUE_OR_POP, 6,
852 LOAD_CONST, 1, RETURN_VALUE, 0};
853 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
854
855 // If the condition is false, we should pop the top of the stack (the
856 // condition) and continue execution. In our case that loads a const and
857 // returns it.
858 EXPECT_TRUE(isIntEqualsWord(runCode(code), 1111));
859}
860
861TEST_F(ThreadTest, UnaryNotWithTruthy) {
862 HandleScope scope(thread_);
863
864 Object obj(&scope, Bool::trueObj());
865 Tuple consts(&scope, runtime_->newTupleWith1(obj));
866 // Bytecode for the snippet:
867 // return not x
868 const byte bytecode[] = {LOAD_CONST, 0, UNARY_NOT, 0, RETURN_VALUE, 0};
869 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
870
871 // If the condition is true, we should return false
872 EXPECT_EQ(runCode(code), Bool::falseObj());
873}
874
875TEST_F(ThreadTest, UnaryNotWithFalsey) {
876 HandleScope scope(thread_);
877
878 Object obj(&scope, Bool::falseObj());
879 Tuple consts(&scope, runtime_->newTupleWith1(obj));
880 // Bytecode for the snippet:
881 // return not x
882 const byte bytecode[] = {LOAD_CONST, 0, UNARY_NOT, 0, RETURN_VALUE, 0};
883 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
884
885 // If the condition is false, we should return true
886 EXPECT_EQ(runCode(code), Bool::trueObj());
887}
888
889TEST_F(ThreadTest, LoadBuildTypeEmptyType) {
890 HandleScope scope(thread_);
891
892 ASSERT_FALSE(runFromCStr(runtime_, R"(
893class C:
894 pass
895)")
896 .isError());
897
898 Type cls(&scope, mainModuleAt(runtime_, "C"));
899 ASSERT_TRUE(cls.name().isSmallStr());
900 EXPECT_EQ(cls.name(), SmallStr::fromCStr("C"));
901
902 Tuple mro(&scope, cls.mro());
903 EXPECT_EQ(mro.length(), 2);
904 EXPECT_EQ(mro.at(0), *cls);
905 EXPECT_EQ(mro.at(1), runtime_->typeAt(LayoutId::kObject));
906}
907
908TEST_F(ThreadTest, LoadBuildTypeTypeWithInit) {
909 HandleScope scope(thread_);
910
911 ASSERT_FALSE(runFromCStr(runtime_, R"(
912class C:
913 def __init__(self):
914 pass
915)")
916 .isError());
917
918 Module mod(&scope, findMainModule(runtime_));
919 ASSERT_TRUE(mod.isModule());
920
921 Str cls_name(&scope, Runtime::internStrFromCStr(thread_, "C"));
922 Object value(&scope, moduleAt(mod, cls_name));
923 ASSERT_TRUE(value.isType());
924 Type cls(&scope, *value);
925
926 // Check class MRO
927 Tuple mro(&scope, cls.mro());
928 EXPECT_EQ(mro.length(), 2);
929 EXPECT_EQ(mro.at(0), *cls);
930 EXPECT_EQ(mro.at(1), runtime_->typeAt(LayoutId::kObject));
931
932 // Check class name
933 ASSERT_TRUE(cls.name().isSmallStr());
934 EXPECT_EQ(cls.name(), SmallStr::fromCStr("C"));
935
936 // Check for the __init__ method name in the dict
937 value = typeAtById(thread_, cls, ID(__init__));
938 ASSERT_FALSE(value.isError());
939 EXPECT_TRUE(value.isFunction());
940}
941
942static ALIGN_16 RawObject nativeExceptionTest(Thread* thread, Arguments) {
943 HandleScope scope(thread);
944 Str msg(&scope,
945 Str::cast(thread->runtime()->newStrFromCStr("test exception")));
946 return thread->raise(LayoutId::kRuntimeError, *msg);
947}
948
949TEST_F(ThreadTest, NativeExceptions) {
950 HandleScope scope(thread_);
951
952 Object name(&scope, runtime_->newStrFromCStr("fn"));
953 Object empty_tuple(&scope, runtime_->emptyTuple());
954 Code fn_code(&scope, runtime_->newBuiltinCode(
955 /*argcount=*/0, /*posonlyargcount=*/0,
956 /*kwonlyargcount=*/0, /*flags=*/0,
957 nativeExceptionTest, empty_tuple, name));
958 Module module(&scope, findMainModule(runtime_));
959 Function fn(&scope,
960 runtime_->newFunctionWithCode(thread_, name, fn_code, module));
961
962 Tuple consts(&scope, runtime_->newTupleWith1(fn));
963 // Call the native fn and check that a pending exception is left in the
964 // Thread.
965 const byte bytecode[] = {LOAD_CONST, 0, CALL_FUNCTION, 0, RETURN_VALUE, 0};
966 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
967
968 EXPECT_TRUE(raised(runCode(code), LayoutId::kRuntimeError));
969 Object value(&scope, thread_->pendingExceptionValue());
970 ASSERT_TRUE(value.isStr());
971 Str str(&scope, *value);
972 EXPECT_TRUE(str.equalsCStr("test exception"));
973}
974
975TEST_F(ThreadTest, PendingStopIterationValueInspectsTuple) {
976 HandleScope scope(thread_);
977
978 Object obj1(&scope, runtime_->newInt(123));
979 Object obj2(&scope, runtime_->newInt(456));
980 Tuple tuple(&scope, runtime_->newTupleWith2(obj1, obj2));
981 thread_->raise(LayoutId::kStopIteration, *tuple);
982
983 ASSERT_TRUE(thread_->hasPendingStopIteration());
984 EXPECT_TRUE(isIntEqualsWord(thread_->pendingStopIterationValue(), 123));
985}
986
987TEST_F(ThreadTest,
988 RaiseStopIterationWithTupleReturnedByPendingStopIterationValue) {
989 HandleScope scope(thread_);
990
991 Object obj1(&scope, runtime_->newInt(123));
992 Object obj2(&scope, runtime_->newInt(456));
993 Tuple tuple(&scope, runtime_->newTupleWith2(obj1, obj2));
994 thread_->raiseStopIterationWithValue(tuple);
995
996 ASSERT_TRUE(thread_->hasPendingStopIteration());
997 EXPECT_EQ(thread_->pendingStopIterationValue(), tuple);
998}
999
1000TEST_F(ThreadTest,
1001 RaiseStopIterationWithStopIterationReturnedByPendingStopIterationValue) {
1002 HandleScope scope(thread_);
1003
1004 Object obj1(&scope, runtime_->newInt(123));
1005 Type stop_iteration_type(&scope, runtime_->typeAt(LayoutId::kStopIteration));
1006 Object stop_iteration(&scope,
1007 Interpreter::call1(thread_, stop_iteration_type, obj1));
1008 thread_->raiseStopIterationWithValue(stop_iteration);
1009
1010 ASSERT_TRUE(thread_->hasPendingStopIteration());
1011 EXPECT_EQ(thread_->pendingStopIterationValue(), stop_iteration);
1012}
1013
1014TEST_F(ThreadTest,
1015 RaiseStopIterationWithIntReturnedByPendingStopIterationValue) {
1016 HandleScope scope(thread_);
1017
1018 Object obj1(&scope, runtime_->newInt(123));
1019 thread_->raiseStopIterationWithValue(obj1);
1020
1021 ASSERT_TRUE(thread_->hasPendingStopIteration());
1022 EXPECT_EQ(thread_->pendingStopIterationValue(), obj1);
1023}
1024
1025TEST_F(ThreadTest, RaiseWithTypePreservesTraceback) {
1026 HandleScope scope(thread_);
1027 Layout layout(&scope, runtime_->layoutAt(LayoutId::kBaseException));
1028 BaseException exc(&scope, runtime_->newInstance(layout));
1029 Object tb(&scope, runtime_->newTraceback());
1030 exc.setTraceback(*tb);
1031 thread_->raiseWithType(runtime_->typeOf(*exc), *exc);
1032 Object pending_exc_tb(&scope, thread_->pendingExceptionTraceback());
1033 EXPECT_EQ(tb, pending_exc_tb);
1034}
1035
1036// MRO tests
1037
1038TEST_F(ThreadTest, LoadBuildTypeVerifyMro) {
1039 HandleScope scope(thread_);
1040
1041 ASSERT_FALSE(runFromCStr(runtime_, R"(
1042class A: pass
1043class B: pass
1044class C(A,B): pass
1045)")
1046 .isError());
1047
1048 Object a(&scope, mainModuleAt(runtime_, "A"));
1049 Object b(&scope, mainModuleAt(runtime_, "B"));
1050 Type c(&scope, mainModuleAt(runtime_, "C"));
1051 Object object(&scope, moduleAtByCStr(runtime_, "builtins", "object"));
1052 Tuple mro(&scope, c.mro());
1053 ASSERT_EQ(mro.length(), 4);
1054 EXPECT_EQ(mro.at(0), c);
1055 EXPECT_EQ(mro.at(1), a);
1056 EXPECT_EQ(mro.at(2), b);
1057 EXPECT_EQ(mro.at(3), object);
1058}
1059
1060TEST_F(ThreadTest, LoadBuildTypeVerifyMroInheritance) {
1061 HandleScope scope(thread_);
1062
1063 ASSERT_FALSE(runFromCStr(runtime_, R"(
1064class A: pass
1065class B(A): pass
1066class C(B): pass
1067)")
1068 .isError());
1069
1070 Object a(&scope, mainModuleAt(runtime_, "A"));
1071 Object b(&scope, mainModuleAt(runtime_, "B"));
1072 Type c(&scope, mainModuleAt(runtime_, "C"));
1073 Object object(&scope, moduleAtByCStr(runtime_, "builtins", "object"));
1074 Tuple mro(&scope, c.mro());
1075 ASSERT_EQ(mro.length(), 4);
1076 EXPECT_EQ(mro.at(0), c);
1077 EXPECT_EQ(mro.at(1), b);
1078 EXPECT_EQ(mro.at(2), a);
1079 EXPECT_EQ(mro.at(3), object);
1080}
1081
1082TEST_F(ThreadTest, LoadBuildTypeVerifyMroMultiInheritance) {
1083 HandleScope scope(thread_);
1084
1085 ASSERT_FALSE(runFromCStr(runtime_, R"(
1086class A: pass
1087class B(A): pass
1088class C: pass
1089class D(B,C): pass
1090)")
1091 .isError());
1092
1093 Object a(&scope, mainModuleAt(runtime_, "A"));
1094 Object b(&scope, mainModuleAt(runtime_, "B"));
1095 Object c(&scope, mainModuleAt(runtime_, "C"));
1096 Type d(&scope, mainModuleAt(runtime_, "D"));
1097 Object object(&scope, moduleAtByCStr(runtime_, "builtins", "object"));
1098 Tuple mro(&scope, d.mro());
1099 ASSERT_EQ(mro.length(), 5);
1100 EXPECT_EQ(mro.at(0), d);
1101 EXPECT_EQ(mro.at(1), b);
1102 EXPECT_EQ(mro.at(2), a);
1103 EXPECT_EQ(mro.at(3), c);
1104 EXPECT_EQ(mro.at(4), object);
1105}
1106
1107TEST_F(ThreadTest, LoadBuildTypeVerifyMroDiamond) {
1108 HandleScope scope(thread_);
1109
1110 ASSERT_FALSE(runFromCStr(runtime_, R"(
1111class A: pass
1112class B(A): pass
1113class C(A): pass
1114class D(B,C): pass
1115)")
1116 .isError());
1117
1118 Object a(&scope, mainModuleAt(runtime_, "A"));
1119 Object b(&scope, mainModuleAt(runtime_, "B"));
1120 Object c(&scope, mainModuleAt(runtime_, "C"));
1121 Type d(&scope, mainModuleAt(runtime_, "D"));
1122 Object object(&scope, moduleAtByCStr(runtime_, "builtins", "object"));
1123 Tuple mro(&scope, d.mro());
1124 ASSERT_EQ(mro.length(), 5);
1125 EXPECT_EQ(mro.at(0), d);
1126 EXPECT_EQ(mro.at(1), b);
1127 EXPECT_EQ(mro.at(2), c);
1128 EXPECT_EQ(mro.at(3), a);
1129 EXPECT_EQ(mro.at(4), object);
1130}
1131
1132TEST_F(ThreadTest, LoadBuildTypeVerifyMroError) {
1133 const char* src = R"(
1134class A: pass
1135class B(A): pass
1136class C(A, B): pass
1137)";
1138
1139 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
1140 "Cannot create a consistent method resolution "
1141 "order (MRO) for bases A, B"));
1142}
1143
1144// iteration
1145
1146TEST_F(ThreadTest, RaiseVarargs) {
1147 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "raise 1"),
1148 LayoutId::kTypeError,
1149 "exceptions must derive from BaseException"));
1150}
1151
1152TEST_F(ThreadTest, InheritFromObject) {
1153 HandleScope scope(thread_);
1154 const char* src = R"(
1155class Foo(object):
1156 pass
1157)";
1158 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1159
1160 // Look up the class Foo
1161 Object main_obj(&scope, findMainModule(runtime_));
1162 ASSERT_TRUE(main_obj.isModule());
1163 Object foo_obj(&scope, mainModuleAt(runtime_, "Foo"));
1164 ASSERT_TRUE(foo_obj.isType());
1165 Type foo(&scope, *foo_obj);
1166
1167 // Check that its MRO is itself and object
1168 ASSERT_TRUE(foo.mro().isTuple());
1169 Tuple mro(&scope, foo.mro());
1170 ASSERT_EQ(mro.length(), 2);
1171 EXPECT_EQ(mro.at(0), *foo);
1172 EXPECT_EQ(mro.at(1), runtime_->typeAt(LayoutId::kObject));
1173}
1174
1175// imports
1176
1177TEST_F(ThreadTest, ImportTest) {
1178 HandleScope scope(thread_);
1179 Object module_src(&scope, runtime_->newStrFromCStr(R"(
1180def say_hello():
1181 return "hello"
1182)"));
1183 Object filename(&scope, runtime_->newStrFromCStr("<test string>"));
1184 const char* main_src = R"(
1185import hello
1186result = hello.say_hello()
1187)";
1188
1189 // Pre-load the hello module so is cached.
1190 Code code(&scope, compile(thread_, module_src, filename, ID(exec),
1191 /*flags=*/0, /*optimize=*/0));
1192 Object name(&scope, runtime_->newStrFromCStr("hello"));
1193 ASSERT_FALSE(executeModuleFromCode(thread_, code, name).isError());
1194 ASSERT_FALSE(runFromCStr(runtime_, main_src).isError());
1195 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "hello"));
1196}
1197
1198TEST_F(ThreadTest, FailedImportTest) {
1199 const char* main_src = R"(
1200import hello
1201hello.say_hello()
1202)";
1203
1204 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, main_src),
1205 LayoutId::kModuleNotFoundError,
1206 "No module named 'hello'"));
1207}
1208
1209TEST_F(ThreadTest, ImportMissingAttributeTest) {
1210 HandleScope scope(thread_);
1211 Object module_src(&scope, runtime_->newStrFromCStr(R"(
1212def say_hello():
1213 print("hello");
1214)"));
1215 Object filename(&scope, runtime_->newStrFromCStr("<test string>"));
1216 const char* main_src = R"(
1217import hello
1218hello.foo()
1219)";
1220
1221 // Pre-load the hello module so is cached.
1222 Code code(&scope, compile(thread_, module_src, filename, ID(exec),
1223 /*flags=*/0, /*optimize=*/0));
1224 Object name(&scope, runtime_->newStrFromCStr("hello"));
1225 ASSERT_FALSE(executeModuleFromCode(thread_, code, name).isError());
1226
1227 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, main_src),
1228 LayoutId::kAttributeError,
1229 "module 'hello' has no attribute 'foo'"));
1230}
1231
1232TEST_F(ThreadTest, ModuleSetAttrTest) {
1233 HandleScope scope(thread_);
1234 Object module_src(&scope, runtime_->newStrFromCStr(R"(
1235def say_hello():
1236 return "hello"
1237)"));
1238 Object filename(&scope, runtime_->newStrFromCStr("<test string>"));
1239 const char* main_src = R"(
1240import hello
1241def goodbye():
1242 return "goodbye"
1243hello.say_hello = goodbye
1244result = hello.say_hello()
1245)";
1246
1247 // Pre-load the hello module so is cached.
1248 Code code(&scope, compile(thread_, module_src, filename, ID(exec),
1249 /*flags=*/0, /*optimize=*/0));
1250 Object name(&scope, runtime_->newStrFromCStr("hello"));
1251 ASSERT_FALSE(executeModuleFromCode(thread_, code, name).isError());
1252 ASSERT_FALSE(runFromCStr(runtime_, main_src).isError());
1253 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "goodbye"));
1254}
1255
1256TEST_F(ThreadTest, StoreFastStackEffect) {
1257 const char* src = R"(
1258def printit(x, y, z):
1259 return (x, y, z)
1260
1261def test():
1262 x = 1
1263 y = 2
1264 z = 3
1265 return printit(x, y, z)
1266
1267result = test()
1268)";
1269 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1270 HandleScope scope(thread_);
1271 Object result(&scope, mainModuleAt(runtime_, "result"));
1272 ASSERT_TRUE(result.isTuple());
1273 Tuple tuple(&scope, *result);
1274 ASSERT_EQ(tuple.length(), 3);
1275 EXPECT_TRUE(isIntEqualsWord(tuple.at(0), 1));
1276 EXPECT_TRUE(isIntEqualsWord(tuple.at(1), 2));
1277 EXPECT_TRUE(isIntEqualsWord(tuple.at(2), 3));
1278}
1279
1280TEST_F(ThreadTest, Closure) {
1281 const char* src = R"(
1282result = []
1283def f():
1284 a = 1
1285 def g():
1286 b = 2
1287 def h():
1288 result.append(b)
1289 result.append(a)
1290 h()
1291 b = 3
1292 h()
1293 g()
1294f()
1295)";
1296 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1297 HandleScope scope(thread_);
1298 Object result(&scope, mainModuleAt(runtime_, "result"));
1299 EXPECT_PYLIST_EQ(result, {1, 2, 3});
1300}
1301
1302TEST_F(ThreadTest, StackOverflowRaisesRecursionError) {
1303 // TODO(T59724033): Not using binop doesn't raise RecursionError, which
1304 // signifies that our recursion depth checking is problematic.
1305 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1306def foo(x):
1307 return foo(x + 1)
1308
1309foo(1.0)
1310)"),
1311 LayoutId::kRecursionError,
1312 "maximum recursion depth exceeded"));
1313}
1314
1315TEST_F(FormatTest, NoConvEmpty) {
1316 const char* src = R"(
1317result = f''
1318)";
1319 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1320 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), ""));
1321}
1322
1323TEST_F(FormatTest, NoConvOneElement) {
1324 const char* src = R"(
1325a = "hello"
1326result = f'a={a}'
1327)";
1328 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1329 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "a=hello"));
1330}
1331
1332TEST_F(FormatTest, NoConvMultiElements) {
1333 const char* src = R"(
1334a = "hello"
1335b = "world"
1336c = "python"
1337result = f'{a} {b} {c}'
1338)";
1339 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1340 EXPECT_TRUE(
1341 isStrEqualsCStr(mainModuleAt(runtime_, "result"), "hello world python"));
1342}
1343
1344TEST_F(FormatTest, NoConvMultiElementsLarge) {
1345 const char* src = R"(
1346a = "Python"
1347b = "is"
1348c = "an interpreted high-level programming language for general-purpose programming."
1349result = f'{a} {b} {c}'
1350)";
1351 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1352 EXPECT_TRUE(isStrEqualsCStr(
1353 mainModuleAt(runtime_, "result"),
1354 "Python is an interpreted high-level programming language for "
1355 "general-purpose programming."));
1356}
1357
1358TEST_F(ThreadTest, BuildTupleUnpack) {
1359 HandleScope scope(thread_);
1360 const char* src = R"(
1361t = (*[0], *[1, 2], *[], *[3, 4, 5])
1362t1 = (*(0,), *(1, 2), *(), *(3, 4, 5))
1363)";
1364 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1365
1366 Object t(&scope, mainModuleAt(runtime_, "t"));
1367 EXPECT_TRUE(t.isTuple());
1368 Tuple tuple_t(&scope, *t);
1369 EXPECT_EQ(tuple_t.length(), 6);
1370 for (word i = 0; i < tuple_t.length(); i++) {
1371 EXPECT_TRUE(isIntEqualsWord(tuple_t.at(i), i));
1372 }
1373
1374 Object t1(&scope, mainModuleAt(runtime_, "t1"));
1375 EXPECT_TRUE(t1.isTuple());
1376 Tuple tuple_t1(&scope, *t1);
1377 EXPECT_EQ(tuple_t1.length(), 6);
1378 EXPECT_TRUE(isIntEqualsWord(tuple_t1.at(0), 0));
1379 EXPECT_TRUE(isIntEqualsWord(tuple_t1.at(1), 1));
1380 EXPECT_TRUE(isIntEqualsWord(tuple_t1.at(2), 2));
1381 EXPECT_TRUE(isIntEqualsWord(tuple_t1.at(3), 3));
1382 EXPECT_TRUE(isIntEqualsWord(tuple_t1.at(4), 4));
1383 EXPECT_TRUE(isIntEqualsWord(tuple_t1.at(5), 5));
1384}
1385
1386TEST_F(ThreadTest, BuildListUnpack) {
1387 HandleScope scope(thread_);
1388 const char* src = R"(
1389l = [*[0], *[1, 2], *[], *[3, 4, 5]]
1390)";
1391 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1392
1393 Object l(&scope, mainModuleAt(runtime_, "l"));
1394 EXPECT_TRUE(l.isList());
1395 List list_l(&scope, *l);
1396 EXPECT_EQ(list_l.numItems(), 6);
1397 EXPECT_TRUE(isIntEqualsWord(list_l.at(0), 0));
1398 EXPECT_TRUE(isIntEqualsWord(list_l.at(1), 1));
1399 EXPECT_TRUE(isIntEqualsWord(list_l.at(2), 2));
1400 EXPECT_TRUE(isIntEqualsWord(list_l.at(3), 3));
1401 EXPECT_TRUE(isIntEqualsWord(list_l.at(4), 4));
1402 EXPECT_TRUE(isIntEqualsWord(list_l.at(5), 5));
1403}
1404
1405TEST_F(ThreadTest, BuildSetUnpack) {
1406 HandleScope scope(thread_);
1407 const char* src = R"(
1408s = {*[0, 1], *{2, 3}, *(4, 5), *[]}
1409)";
1410 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1411
1412 Object s(&scope, mainModuleAt(runtime_, "s"));
1413 EXPECT_TRUE(s.isSet());
1414 Set set_s(&scope, *s);
1415 EXPECT_EQ(set_s.numItems(), 6);
1416 Object small_int(&scope, SmallInt::fromWord(0));
1417 EXPECT_TRUE(setIncludes(thread_, set_s, small_int));
1418 small_int = SmallInt::fromWord(1);
1419 EXPECT_TRUE(setIncludes(thread_, set_s, small_int));
1420 small_int = SmallInt::fromWord(2);
1421 EXPECT_TRUE(setIncludes(thread_, set_s, small_int));
1422 small_int = SmallInt::fromWord(3);
1423 EXPECT_TRUE(setIncludes(thread_, set_s, small_int));
1424 small_int = SmallInt::fromWord(4);
1425 EXPECT_TRUE(setIncludes(thread_, set_s, small_int));
1426 small_int = SmallInt::fromWord(5);
1427 EXPECT_TRUE(setIncludes(thread_, set_s, small_int));
1428}
1429
1430TEST_F(BuildString, BuildStringEmpty) {
1431 HandleScope scope(thread_);
1432
1433 const byte bytecode[] = {BUILD_STRING, 0, RETURN_VALUE, 0};
1434 Code code(&scope, newCodeWithBytes(bytecode));
1435
1436 EXPECT_TRUE(isStrEqualsCStr(runCode(code), ""));
1437}
1438
1439TEST_F(BuildString, BuildStringSingle) {
1440 HandleScope scope(thread_);
1441 Object str(&scope, SmallStr::fromCStr("foo"));
1442 Tuple consts(&scope, runtime_->newTupleWith1(str));
1443 const byte bytecode[] = {LOAD_CONST, 0, BUILD_STRING, 1, RETURN_VALUE, 0};
1444 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
1445
1446 EXPECT_TRUE(isStrEqualsCStr(runCode(code), "foo"));
1447}
1448
1449TEST_F(BuildString, BuildStringMultiSmall) {
1450 HandleScope scope(thread_);
1451 Object str(&scope, SmallStr::fromCStr("foo"));
1452 Object str1(&scope, SmallStr::fromCStr("bar"));
1453 Tuple consts(&scope, runtime_->newTupleWith2(str, str1));
1454 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1,
1455 BUILD_STRING, 2, RETURN_VALUE, 0};
1456 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
1457
1458 EXPECT_TRUE(isStrEqualsCStr(runCode(code), "foobar"));
1459}
1460
1461TEST_F(BuildString, BuildStringMultiLarge) {
1462 HandleScope scope(thread_);
1463 Object str(&scope, SmallStr::fromCStr("hello"));
1464 Object str1(&scope, SmallStr::fromCStr("world"));
1465 Object str2(&scope, SmallStr::fromCStr("python"));
1466 Tuple consts(&scope, runtime_->newTupleWith3(str, str1, str2));
1467 const byte bytecode[] = {LOAD_CONST, 0, LOAD_CONST, 1, LOAD_CONST, 2,
1468 BUILD_STRING, 3, RETURN_VALUE, 0};
1469 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
1470
1471 EXPECT_TRUE(isStrEqualsCStr(runCode(code), "helloworldpython"));
1472}
1473
1474TEST_F(UnpackSeq, UnpackRange) {
1475 const char* src = R"(
1476[a ,b, c] = range(2, 5)
1477)";
1478 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1479 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "a"), 2));
1480 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b"), 3));
1481 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "c"), 4));
1482}
1483
1484// LIST_APPEND(listAdd) in list_comp, followed by unpack
1485// TODO(rkng): list support in BINARY_ADD
1486TEST_F(UnpackList, UnpackListCompAppend) {
1487 const char* src = R"(
1488a = [1, 2, 3]
1489b = [x for x in a]
1490b1, b2, b3 = b
1491)";
1492 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1493 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b1"), 1));
1494 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b2"), 2));
1495 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b3"), 3));
1496}
1497
1498TEST_F(ThreadTest, SetAdd) {
1499 HandleScope scope(thread_);
1500 const char* src = R"(
1501a = [1, 2, 3]
1502b = {x for x in a}
1503)";
1504 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1505 Object b(&scope, mainModuleAt(runtime_, "b"));
1506 ASSERT_TRUE(b.isSet());
1507 Set set_b(&scope, *b);
1508 EXPECT_EQ(set_b.numItems(), 3);
1509}
1510
1511TEST_F(ThreadTest, MapAdd) {
1512 HandleScope scope(thread_);
1513 const char* src = R"(
1514a = ['a', 'b', 'c']
1515b = {x:x for x in a}
1516)";
1517 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1518 Object b(&scope, mainModuleAt(runtime_, "b"));
1519 EXPECT_EQ(b.isDict(), true);
1520 Dict dict_b(&scope, *b);
1521 EXPECT_EQ(dict_b.numItems(), 3);
1522}
1523
1524TEST_F(UnpackList, UnpackNestedLists) {
1525 const char* src = R"(
1526b = [[1,2], [3,4,5]]
1527b1, b2 = b
1528b11, b12 = b1
1529b21, b22, b23 = b2
1530)";
1531 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1532 HandleScope scope(thread_);
1533 List b(&scope, mainModuleAt(runtime_, "b"));
1534 EXPECT_EQ(b.numItems(), 2);
1535 List b1(&scope, mainModuleAt(runtime_, "b1"));
1536 EXPECT_EQ(b1.numItems(), 2);
1537 List b2(&scope, mainModuleAt(runtime_, "b2"));
1538 EXPECT_EQ(b2.numItems(), 3);
1539 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b11"), 1));
1540 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b12"), 2));
1541 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b21"), 3));
1542 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b22"), 4));
1543 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b23"), 5));
1544}
1545
1546TEST_F(UnpackSeq, UnpackRangeStep) {
1547 const char* src = R"(
1548[a ,b, c, d] = range(2, 10, 2)
1549)";
1550 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1551 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "a"), 2));
1552 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b"), 4));
1553 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "c"), 6));
1554 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "d"), 8));
1555}
1556
1557TEST_F(UnpackSeq, UnpackRangeNeg) {
1558 const char* src = R"(
1559[a ,b, c, d, e] = range(-10, 0, 2)
1560)";
1561 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1562 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "a"), -10));
1563 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b"), -8));
1564 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "c"), -6));
1565 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "d"), -4));
1566 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "e"), -2));
1567}
1568
1569TEST_F(ListIterTest, Build) {
1570 const char* src = R"(
1571a = [1, 2, 3]
1572result = []
1573for x in a:
1574 result.append(x)
1575)";
1576 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1577 HandleScope scope(thread_);
1578 Object result(&scope, mainModuleAt(runtime_, "result"));
1579 EXPECT_PYLIST_EQ(result, {1, 2, 3});
1580}
1581
1582TEST_F(ListAppendTest, BuildAndUnpack) {
1583 const char* src = R"(
1584a = [1, 2]
1585b = [x for x in [a] * 3]
1586b1, b2, b3 = b
1587b11, b12 = b1
1588)";
1589 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1590 HandleScope scope(thread_);
1591 List b(&scope, mainModuleAt(runtime_, "b"));
1592 EXPECT_EQ(b.numItems(), 3);
1593 List b1(&scope, mainModuleAt(runtime_, "b1"));
1594 EXPECT_EQ(b1.numItems(), 2);
1595 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b11"), 1));
1596 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "b12"), 2));
1597}
1598
1599TEST_F(ListInsertTest, InsertToList) {
1600 HandleScope scope(thread_);
1601 const char* src = R"(
1602l = []
1603for i in range(16):
1604 if i == 2 or i == 12:
1605 continue
1606 l.append(i)
1607
1608a, b = l[2], l[12]
1609
1610l.insert(2, 2)
1611l.insert(12, 12)
1612
1613s = 0
1614for el in l:
1615 s += el
1616)";
1617 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1618 Object a(&scope, mainModuleAt(runtime_, "a"));
1619 Object b(&scope, mainModuleAt(runtime_, "b"));
1620 Object l(&scope, mainModuleAt(runtime_, "l"));
1621 Object s(&scope, mainModuleAt(runtime_, "s"));
1622
1623 EXPECT_FALSE(isIntEqualsWord(*a, 2));
1624 EXPECT_FALSE(isIntEqualsWord(*b, 12));
1625
1626 List list_l(&scope, *l);
1627 ASSERT_EQ(list_l.numItems(), 16);
1628 EXPECT_TRUE(isIntEqualsWord(list_l.at(2), 2));
1629 EXPECT_TRUE(isIntEqualsWord(list_l.at(12), 12));
1630
1631 // sum(0..16) = 120
1632 EXPECT_TRUE(isIntEqualsWord(*s, 120));
1633}
1634
1635TEST_F(ListInsertTest, InsertToListBounds) {
1636 HandleScope scope(thread_);
1637 const char* src = R"(
1638l = [x for x in range(1, 5)]
1639l.insert(100, 5)
1640l.insert(400, 6)
1641l.insert(-100, 0)
1642)";
1643 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1644 Object l(&scope, mainModuleAt(runtime_, "l"));
1645 List list_l(&scope, *l);
1646 EXPECT_TRUE(isIntEqualsWord(list_l.at(0), 0));
1647 EXPECT_TRUE(isIntEqualsWord(list_l.at(1), 1));
1648 EXPECT_TRUE(isIntEqualsWord(list_l.at(2), 2));
1649 EXPECT_TRUE(isIntEqualsWord(list_l.at(3), 3));
1650 EXPECT_TRUE(isIntEqualsWord(list_l.at(4), 4));
1651 EXPECT_TRUE(isIntEqualsWord(list_l.at(5), 5));
1652 EXPECT_TRUE(isIntEqualsWord(list_l.at(6), 6));
1653}
1654
1655TEST_F(ListInsertTest, InsertToNegativeIndex) {
1656 HandleScope scope(thread_);
1657 const char* src = R"(
1658l = [0, 2, 4]
1659l.insert(-2, 1)
1660l.insert(-1, 3)
1661)";
1662 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1663 Object l(&scope, mainModuleAt(runtime_, "l"));
1664 List list_l(&scope, *l);
1665 ASSERT_EQ(list_l.numItems(), 5);
1666 EXPECT_TRUE(isIntEqualsWord(list_l.at(0), 0));
1667 EXPECT_TRUE(isIntEqualsWord(list_l.at(1), 1));
1668 EXPECT_TRUE(isIntEqualsWord(list_l.at(2), 2));
1669 EXPECT_TRUE(isIntEqualsWord(list_l.at(3), 3));
1670 EXPECT_TRUE(isIntEqualsWord(list_l.at(4), 4));
1671}
1672
1673TEST_F(ThreadTest, BaseTypeConflict) {
1674 const char* src = R"(
1675class Foo(list, dict): pass
1676)";
1677 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
1678 "multiple bases have instance lay-out conflict"));
1679}
1680
1681TEST_F(ThreadTest, BreakLoopWhileLoop) {
1682 const char* src = R"(
1683a = 0
1684result = []
1685while 1:
1686 a = a + 1
1687 result.append(a)
1688 if a == 3:
1689 break
1690)";
1691 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1692 HandleScope scope(thread_);
1693 Object result(&scope, mainModuleAt(runtime_, "result"));
1694 EXPECT_PYLIST_EQ(result, {1, 2, 3});
1695}
1696
1697TEST_F(ThreadTest, BreakLoopWhileLoop1) {
1698 const char* src = R"(
1699a = 0
1700result = []
1701while 1:
1702 a = a + 1
1703 result.append(a)
1704 if a == 3:
1705 break
1706)";
1707 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1708 HandleScope scope(thread_);
1709 Object result(&scope, mainModuleAt(runtime_, "result"));
1710 EXPECT_PYLIST_EQ(result, {1, 2, 3});
1711 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "a"), 3));
1712}
1713
1714TEST_F(ThreadTest, BreakLoopRangeLoop) {
1715 const char* src = R"(
1716result = []
1717for x in range(1,6):
1718 if x == 3:
1719 break;
1720 result.append(x)
1721)";
1722 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1723 HandleScope scope(thread_);
1724 Object result(&scope, mainModuleAt(runtime_, "result"));
1725 EXPECT_PYLIST_EQ(result, {1, 2});
1726}
1727
1728TEST_F(ThreadTest, ContinueLoopRangeLoop) {
1729 HandleScope scope(thread_);
1730 const char* src = R"(
1731l = []
1732
1733for x in range(4):
1734 if x == 3:
1735 try:
1736 continue
1737 except:
1738 # This is to prevent the peephole optimizer
1739 # from turning the CONTINUE_LOOP op
1740 # into a JUMP_ABSOLUTE op
1741 pass
1742 l.append(x)
1743)";
1744 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1745 Object l(&scope, mainModuleAt(runtime_, "l"));
1746 EXPECT_TRUE(l.isList());
1747 List list_l(&scope, *l);
1748 ASSERT_GE(list_l.numItems(), 3);
1749 EXPECT_EQ(list_l.at(0), SmallInt::fromWord(0));
1750 EXPECT_EQ(list_l.at(1), SmallInt::fromWord(1));
1751 EXPECT_EQ(list_l.at(2), SmallInt::fromWord(2));
1752}
1753
1754TEST_F(ThreadTest, Func2TestPyStone) { // mimic pystone.py Func2
1755 const char* src = R"(
1756def f1(x, y):
1757 return x + y
1758def f2():
1759 return f1(1, 2)
1760result = f2()
1761)";
1762 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1763 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 3));
1764}
1765
1766TEST_F(ThreadTest, BinSubscrString) { // pystone dependency
1767 const char* src = R"(
1768a = 'Hello'
1769r0 = a[0]
1770r1 = a[1]
1771r2 = a[2]
1772r3 = a[3]
1773r4 = a[4]
1774)";
1775 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1776 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "r0"), "H"));
1777 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "r1"), "e"));
1778 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "r2"), "l"));
1779 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "r3"), "l"));
1780 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "r4"), "o"));
1781}
1782
1783TEST_F(ThreadTest, SetupExceptNoOp) { // pystone dependency
1784 const char* src = R"(
1785def f(x):
1786 try:
1787 return x
1788 except ValueError:
1789 return "Invalid Argument"
1790result = f(100)
1791)";
1792 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1793 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 100));
1794}
1795
1796TEST_F(ThreadTest, BuildTypeWithMetaclass) {
1797 HandleScope scope(thread_);
1798 const char* src = R"(
1799class Foo(metaclass=type):
1800 pass
1801a = Foo()
1802)";
1803 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1804 Object foo(&scope, mainModuleAt(runtime_, "Foo"));
1805 EXPECT_TRUE(foo.isType());
1806 Object a(&scope, mainModuleAt(runtime_, "a"));
1807 EXPECT_TRUE(runtime_->typeOf(*a) == *foo);
1808}
1809
1810TEST_F(ThreadTest, BuildTypeWithMetaclass2) {
1811 HandleScope scope(thread_);
1812 const char* src = R"(
1813class Foo(type):
1814 def __new__(mcls, name, bases, dict):
1815 cls = super(Foo, mcls).__new__(mcls, name, bases, dict)
1816 cls.lalala = 123
1817 return cls
1818class Bar(metaclass=Foo):
1819 def __init__(self):
1820 self.hahaha = 456
1821b = Bar.lalala
1822a = Bar()
1823c = a.hahaha
1824)";
1825 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1826 Object bar(&scope, mainModuleAt(runtime_, "Bar"));
1827 EXPECT_TRUE(runtime_->isInstanceOfType(*bar));
1828 Object a(&scope, mainModuleAt(runtime_, "a"));
1829 EXPECT_TRUE(runtime_->typeOf(*a) == *bar);
1830 Object b(&scope, mainModuleAt(runtime_, "b"));
1831 EXPECT_TRUE(isIntEqualsWord(*b, 123));
1832 Object c(&scope, mainModuleAt(runtime_, "c"));
1833 EXPECT_TRUE(isIntEqualsWord(*c, 456));
1834}
1835
1836TEST_F(ThreadTest, NameLookupInTypeBodyFindsImplicitGlobal) {
1837 HandleScope scope(thread_);
1838 const char* src = R"(
1839a = 0
1840b = 0
1841class C:
1842 global a
1843 global b
1844 PI = 3
1845 a = PI
1846 PIPI = PI * 2
1847 b = PIPI
1848)";
1849 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1850 Object a(&scope, mainModuleAt(runtime_, "a"));
1851 EXPECT_TRUE(isIntEqualsWord(*a, 3));
1852 Object b(&scope, mainModuleAt(runtime_, "b"));
1853 EXPECT_TRUE(isIntEqualsWord(*b, 6));
1854}
1855
1856TEST_F(ThreadTest, NameLookupInTypeBodyFindsGlobal) {
1857 HandleScope scope(thread_);
1858 const char* src = R"(
1859var = 1
1860class C:
1861 global one
1862 global two
1863 one = var
1864 var = 2
1865 two = var
1866)";
1867 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1868 Object one(&scope, mainModuleAt(runtime_, "one"));
1869 EXPECT_TRUE(isIntEqualsWord(*one, 1));
1870 Object two(&scope, mainModuleAt(runtime_, "two"));
1871 EXPECT_TRUE(isIntEqualsWord(*two, 2));
1872}
1873
1874TEST_F(ThreadTest, ExecuteDeleteName) {
1875 HandleScope scope(thread_);
1876 const char* src = R"(
1877var = 1
1878del var
1879)";
1880 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1881 Object var(&scope, mainModuleAt(runtime_, "var"));
1882 EXPECT_TRUE(var.isError());
1883}
1884
1885TEST_F(ThreadTest, SetupFinally) {
1886 HandleScope scope(thread_);
1887 const char* src = R"(
1888x = 1
1889try:
1890 pass
1891finally:
1892 x = 2
1893)";
1894 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1895 Object x(&scope, mainModuleAt(runtime_, "x"));
1896 EXPECT_EQ(*x, SmallInt::fromWord(2));
1897}
1898
1899TEST_F(ThreadTest, SetupAnnotationsAndStoreAnnotations) {
1900 HandleScope scope(thread_);
1901 const char* src = R"(
1902global_with_annotation: int = 1
1903class ClassWithAnnotation:
1904 attribute_with_annotation: int = 2
1905class_anno_dict = ClassWithAnnotation.__annotations__
1906)";
1907 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1908 Dict module_anno_dict(&scope, mainModuleAt(runtime_, "__annotations__"));
1909 Str m_key(&scope, runtime_->newStrFromCStr("global_with_annotation"));
1910 Object m_value(&scope, dictAtByStr(thread_, module_anno_dict, m_key));
1911 EXPECT_EQ(*m_value, runtime_->typeAt(LayoutId::kInt));
1912
1913 Dict class_anno_dict(&scope, mainModuleAt(runtime_, "class_anno_dict"));
1914 Str c_key(&scope, runtime_->newStrFromCStr("attribute_with_annotation"));
1915 Object c_value(&scope, dictAtByStr(thread_, class_anno_dict, c_key));
1916 EXPECT_EQ(*c_value, runtime_->typeAt(LayoutId::kInt));
1917}
1918
1919TEST_F(ThreadTest, DeleteFastRaisesUnboundLocalError) {
1920 const char* src = R"(
1921def foo(a, b, c):
1922 del a
1923 return a
1924foo(1, 2, 3)
1925)";
1926 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src),
1927 LayoutId::kUnboundLocalError,
1928 "local variable 'a' referenced before assignment"));
1929}
1930
1931TEST_F(ThreadTest, DeleteFast) {
1932 HandleScope scope(thread_);
1933 const char* src = R"(
1934def foo(a, b, c):
1935 del a
1936 return b
1937x = foo(1, 2, 3)
1938)";
1939 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1940 Object x(&scope, mainModuleAt(runtime_, "x"));
1941 EXPECT_EQ(*x, SmallInt::fromWord(2));
1942}
1943
1944TEST_F(ThreadTest, ConstructInstanceWithKwargs) {
1945 HandleScope scope(thread_);
1946 const char* src = R"(
1947result_a = None
1948result_b = None
1949result_c = None
1950
1951class Foo:
1952 def __init__(self, a, b=None, c=None):
1953 global result_a, result_b, result_c
1954 result_a = a
1955 result_b = b
1956 result_c = c
1957
1958foo = Foo(1111, b=2222, c=3333)
1959)";
1960 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1961
1962 Object result_a(&scope, mainModuleAt(runtime_, "result_a"));
1963 EXPECT_TRUE(isIntEqualsWord(*result_a, 1111));
1964
1965 Object result_b(&scope, mainModuleAt(runtime_, "result_b"));
1966 EXPECT_TRUE(isIntEqualsWord(*result_b, 2222));
1967
1968 Object result_c(&scope, mainModuleAt(runtime_, "result_c"));
1969 EXPECT_TRUE(isIntEqualsWord(*result_c, 3333));
1970}
1971
1972TEST_F(ThreadTest, LoadTypeDeref) {
1973 HandleScope scope(thread_);
1974 const char* src = R"(
1975def foo():
1976 a = 1
1977 class Foo:
1978 b = a
1979 return Foo.b
1980x = foo()
1981)";
1982 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
1983 Object x(&scope, mainModuleAt(runtime_, "x"));
1984 EXPECT_EQ(*x, SmallInt::fromWord(1));
1985}
1986
1987TEST_F(ThreadTest, LoadTypeDerefFromLocal) {
1988 HandleScope scope(thread_);
1989 Object obj1(&scope, SmallInt::fromWord(1111));
1990 Tuple consts(&scope, runtime_->newTupleWith1(obj1));
1991 Object obj3(&scope, Runtime::internStrFromCStr(thread_, "lalala"));
1992 Tuple names(&scope, runtime_->newTupleWith1(obj3));
1993 const byte bytecode[] = {LOAD_CONST, 0, STORE_NAME, 0,
1994 LOAD_CLASSDEREF, 0, RETURN_VALUE, 0};
1995 Code code(&scope,
1996 newCodeWithBytesConstsNamesFlags(bytecode, consts, names, 0));
1997 Object obj2(&scope, Runtime::internStrFromCStr(thread_, "lalala"));
1998 Tuple freevars(&scope, runtime_->newTupleWith1(obj2));
1999 code.setFreevars(*freevars);
2000 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
2001 Module module(&scope, findMainModule(runtime_));
2002
2003 Function function(&scope,
2004 runtime_->newFunctionWithCode(thread_, name, code, module));
2005 Tuple closure(&scope, runtime_->newTupleWith1(obj3));
2006 function.setClosure(*closure);
2007
2008 Dict locals(&scope, runtime_->newDict());
2009 EXPECT_TRUE(isIntEqualsWord(
2010 thread_->callFunctionWithImplicitGlobals(function, locals), 1111));
2011}
2012
2013TEST_F(ThreadTest, PushCallFrameWithSameGlobalsPropagatesBuiltins) {
2014 HandleScope scope(thread_);
2015 Code code(&scope, newCodeWithBytes(View<byte>(nullptr, 0)));
2016
2017 Object qualname(&scope, runtime_->newStrFromCStr("<anonymous>"));
2018 Module module(&scope, findMainModule(runtime_));
2019 Function function(
2020 &scope, runtime_->newFunctionWithCode(thread_, qualname, code, module));
2021
2022 Frame* frame = thread_->currentFrame();
2023 thread_->stackPush(*function);
2024 Frame* new_frame = thread_->pushCallFrame(*function);
2025 EXPECT_NE(new_frame, frame);
2026}
2027
2028TEST_F(ThreadTest, ExecSetsMissingDunderBuiltins) {
2029 HandleScope scope(thread_);
2030 Object obj(&scope, NoneType::object());
2031 Tuple consts(&scope, runtime_->newTupleWith1(obj));
2032 const byte bytecode[] = {LOAD_CONST, 0, RETURN_VALUE, 0};
2033 Code code(&scope, newCodeWithBytesConsts(bytecode, consts));
2034 code.setFlags(0);
2035
2036 Object name(&scope, runtime_->newStrFromCStr("<test module>"));
2037 Module module(&scope, runtime_->newModule(name));
2038 Object none(&scope, NoneType::object());
2039
2040 ASSERT_TRUE(thread_->exec(code, module, none).isNoneType());
2041
2042 Module builtins_module(&scope, runtime_->findModuleById(ID(builtins)));
2043 Object proxy(&scope, builtins_module.moduleProxy());
2044 EXPECT_EQ(moduleAtById(thread_, module, ID(__builtins__)), proxy);
2045}
2046
2047TEST_F(ThreadTest, CallFunctionInDifferentModule) {
2048 HandleScope scope(thread_);
2049 ASSERT_FALSE(runFromCStr(runtime_, R"(
2050def a():
2051 def inner_a():
2052 return object
2053 return inner_a
2054result0 = a()()
2055)")
2056 .isError());
2057 // Object a(&scope, mainModuleAt(runtime_, "a"));
2058 Object result0(&scope, mainModuleAt(runtime_, "result0"));
2059 Object object(&scope, moduleAtByCStr(runtime_, "builtins", "object"));
2060 EXPECT_EQ(result0, object);
2061}
2062
2063TEST_F(ThreadTest, RaiseWithFmtFormatsString) {
2064 EXPECT_TRUE(raisedWithStr(
2065 thread_->raiseWithFmt(LayoutId::kTypeError, "hello %Y", ID(dict)),
2066 LayoutId::kTypeError, "hello dict"));
2067}
2068
2069TEST_F(ThreadTest, RaiseOSErrorFromErrnoWithInvalidErrnoReturnsOSError) {
2070 EXPECT_TRUE(raised(thread_->raiseOSErrorFromErrno(-5), LayoutId::kOSError));
2071}
2072
2073TEST_F(ThreadTest, RaiseOSErrorFromErrnoPicksOSErrorSubclass) {
2074 EXPECT_TRUE(raised(thread_->raiseOSErrorFromErrno(EACCES),
2075 LayoutId::kPermissionError));
2076}
2077
2078TEST_F(ThreadTest, StrOffsetWithNegativeReturnsNegativeOne) {
2079 HandleScope scope(thread_);
2080 Str str(&scope, SmallStr::fromCStr("foo"));
2081 EXPECT_EQ(thread_->strOffset(str, -10), -1);
2082}
2083
2084TEST_F(ThreadTest, StrOffsetWithLargeNumberReturnsLength) {
2085 HandleScope scope(thread_);
2086 Str str(&scope, SmallStr::fromCStr("foo"));
2087 EXPECT_EQ(thread_->strOffset(str, 5), 3);
2088}
2089
2090TEST_F(ThreadTest, StrOffsetWithIndexReturnsOffset) {
2091 HandleScope scope(thread_);
2092 Str str(&scope, SmallStr::fromCStr("\u00e9tude"));
2093 EXPECT_EQ(thread_->strOffset(str, 2), 3);
2094}
2095
2096TEST_F(ThreadTest, StrOffsetWithCacheHitReturnsCorrectOffsets) {
2097 HandleScope scope(thread_);
2098 Str str(&scope, runtime_->newStrFromCStr("\u00e9l\u00e9gie"));
2099 EXPECT_EQ(thread_->strOffset(str, 2), 3);
2100 EXPECT_EQ(thread_->strOffset(str, 4), 6);
2101 EXPECT_EQ(thread_->strOffset(str, 1), 2);
2102}
2103
2104TEST_F(ThreadTest, StrOffsetWithCacheMissReturnsCorrectOffsets) {
2105 HandleScope scope(thread_);
2106 Str str(&scope, runtime_->newStrFromCStr("\u00e9l\u00e9gie"));
2107 EXPECT_EQ(thread_->strOffset(str, 2), 3);
2108
2109 // out of bounds
2110 EXPECT_EQ(thread_->strOffset(str, 10), 8);
2111 EXPECT_EQ(thread_->strOffset(str, 1), 2);
2112
2113 // new string
2114 str = runtime_->newStrFromCStr("foo");
2115 EXPECT_EQ(thread_->strOffset(str, 2), 2);
2116}
2117
2118} // namespace testing
2119} // namespace py