this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <memory>
3
4#include "gtest/gtest.h"
5
6#include "dict-builtins.h"
7#include "frame.h"
8#include "function-builtins.h"
9#include "int-builtins.h"
10#include "modules.h"
11#include "runtime.h"
12#include "test-utils.h"
13
14namespace py {
15namespace testing {
16
17using CallTest = RuntimeFixture;
18using TrampolinesTest = RuntimeFixture;
19
20TEST_F(CallTest, CallBoundMethod) {
21 HandleScope scope(thread_);
22 ASSERT_FALSE(runFromCStr(runtime_, R"(
23def func(self):
24 return self
25
26def test(callable):
27 return callable()
28)")
29 .isError());
30
31 Object function(&scope, mainModuleAt(runtime_, "func"));
32 ASSERT_TRUE(function.isFunction());
33
34 Object self(&scope, SmallInt::fromWord(1111));
35 BoundMethod method(&scope, runtime_->newBoundMethod(function, self));
36
37 Object test(&scope, mainModuleAt(runtime_, "test"));
38 ASSERT_TRUE(test.isFunction());
39 Function func(&scope, *test);
40
41 Object result(&scope, Interpreter::call1(thread_, func, method));
42 EXPECT_TRUE(isIntEqualsWord(*result, 1111));
43}
44
45TEST_F(CallTest, CallBoundMethodWithArgs) {
46 HandleScope scope(thread_);
47 ASSERT_FALSE(runFromCStr(runtime_, R"(
48def func(self, a, b):
49 return [self, a, b]
50
51def test(callable):
52 return callable(2222, 3333)
53)")
54 .isError());
55
56 Object function(&scope, mainModuleAt(runtime_, "func"));
57 ASSERT_TRUE(function.isFunction());
58
59 Object self(&scope, SmallInt::fromWord(1111));
60 BoundMethod method(&scope, runtime_->newBoundMethod(function, self));
61
62 Object test(&scope, mainModuleAt(runtime_, "test"));
63 ASSERT_TRUE(test.isFunction());
64 Function func(&scope, *test);
65
66 Object result(&scope, Interpreter::call1(thread_, func, method));
67 EXPECT_PYLIST_EQ(result, {1111, 2222, 3333});
68}
69
70TEST_F(CallTest, CallBoundMethodKw) {
71 HandleScope scope(thread_);
72 ASSERT_FALSE(runFromCStr(runtime_, R"(
73result_self = None
74result_a = None
75result_b = None
76
77def func(self, a, b):
78 global result_self, result_a, result_b
79 result_self = self
80 result_a = a
81 result_b = b
82
83def test(callable):
84 return callable(a=2222, b=3333)
85)")
86 .isError());
87
88 Object function(&scope, mainModuleAt(runtime_, "func"));
89 ASSERT_TRUE(function.isFunction());
90
91 Object self(&scope, SmallInt::fromWord(1111));
92 BoundMethod method(&scope, runtime_->newBoundMethod(function, self));
93
94 Object test(&scope, mainModuleAt(runtime_, "test"));
95 ASSERT_TRUE(test.isFunction());
96 Function func(&scope, *test);
97 Tuple args(&scope, runtime_->newTupleWith1(method));
98 callFunction(func, args);
99
100 Object result_self(&scope, mainModuleAt(runtime_, "result_self"));
101 EXPECT_TRUE(isIntEqualsWord(*result_self, 1111));
102
103 Object result_a(&scope, mainModuleAt(runtime_, "result_a"));
104 EXPECT_TRUE(isIntEqualsWord(*result_a, 2222));
105
106 Object result_b(&scope, mainModuleAt(runtime_, "result_b"));
107 EXPECT_TRUE(isIntEqualsWord(*result_b, 3333));
108}
109
110TEST_F(CallTest, CallBoundMethodExArgs) {
111 HandleScope scope(thread_);
112 ASSERT_FALSE(runFromCStr(runtime_, R"(
113result_self = None
114result_a = None
115result_b = None
116
117def func(self, a, b):
118 global result_self, result_a, result_b
119 result_self = self
120 result_a = a
121 result_b = b
122
123def test(callable):
124 args = (2222, 3333)
125 return callable(*args)
126)")
127 .isError());
128
129 Object function(&scope, mainModuleAt(runtime_, "func"));
130 ASSERT_TRUE(function.isFunction());
131
132 Object self(&scope, SmallInt::fromWord(1111));
133 BoundMethod method(&scope, runtime_->newBoundMethod(function, self));
134
135 Object test(&scope, mainModuleAt(runtime_, "test"));
136 ASSERT_TRUE(test.isFunction());
137 Function func(&scope, *test);
138 Tuple args(&scope, runtime_->newTupleWith1(method));
139 callFunction(func, args);
140
141 Object result_self(&scope, mainModuleAt(runtime_, "result_self"));
142 EXPECT_TRUE(isIntEqualsWord(*result_self, 1111));
143
144 Object result_a(&scope, mainModuleAt(runtime_, "result_a"));
145 EXPECT_TRUE(isIntEqualsWord(*result_a, 2222));
146
147 Object result_b(&scope, mainModuleAt(runtime_, "result_b"));
148 EXPECT_TRUE(isIntEqualsWord(*result_b, 3333));
149}
150
151TEST_F(CallTest, CallBoundMethodExKwargs) {
152 HandleScope scope(thread_);
153 ASSERT_FALSE(runFromCStr(runtime_, R"(
154result_self = None
155result_a = None
156result_b = None
157
158def func(self, a, b):
159 global result_self, result_a, result_b
160 result_self = self
161 result_a = a
162 result_b = b
163
164def test(callable):
165 kwargs = {'a': 2222, 'b': 3333}
166 return callable(**kwargs)
167)")
168 .isError());
169
170 Object function(&scope, mainModuleAt(runtime_, "func"));
171 ASSERT_TRUE(function.isFunction());
172
173 Object self(&scope, SmallInt::fromWord(1111));
174 BoundMethod method(&scope, runtime_->newBoundMethod(function, self));
175
176 Object test(&scope, mainModuleAt(runtime_, "test"));
177 ASSERT_TRUE(test.isFunction());
178 Function func(&scope, *test);
179 Tuple args(&scope, runtime_->newTupleWith1(method));
180 callFunction(func, args);
181
182 Object result_self(&scope, mainModuleAt(runtime_, "result_self"));
183 EXPECT_TRUE(isIntEqualsWord(*result_self, 1111));
184
185 Object result_a(&scope, mainModuleAt(runtime_, "result_a"));
186 EXPECT_TRUE(isIntEqualsWord(*result_a, 2222));
187
188 Object result_b(&scope, mainModuleAt(runtime_, "result_b"));
189 EXPECT_TRUE(isIntEqualsWord(*result_b, 3333));
190}
191
192TEST_F(CallTest, CallBoundMethodExArgsAndKwargs) {
193 HandleScope scope(thread_);
194 ASSERT_FALSE(runFromCStr(runtime_, R"(
195result_self = None
196result_a = None
197result_b = None
198
199def func(self, a, b):
200 global result_self, result_a, result_b
201 result_self = self
202 result_a = a
203 result_b = b
204
205def test(callable):
206 args = (2222,)
207 kwargs = {'b': 3333}
208 return callable(*args, **kwargs)
209)")
210 .isError());
211
212 Object function(&scope, mainModuleAt(runtime_, "func"));
213 ASSERT_TRUE(function.isFunction());
214
215 Object self(&scope, SmallInt::fromWord(1111));
216 BoundMethod method(&scope, runtime_->newBoundMethod(function, self));
217
218 Object test(&scope, mainModuleAt(runtime_, "test"));
219 ASSERT_TRUE(test.isFunction());
220 Function func(&scope, *test);
221 Tuple args(&scope, runtime_->newTupleWith1(method));
222 callFunction(func, args);
223
224 Object result_self(&scope, mainModuleAt(runtime_, "result_self"));
225 EXPECT_TRUE(isIntEqualsWord(*result_self, 1111));
226
227 Object result_a(&scope, mainModuleAt(runtime_, "result_a"));
228 EXPECT_TRUE(isIntEqualsWord(*result_a, 2222));
229
230 Object result_b(&scope, mainModuleAt(runtime_, "result_b"));
231 EXPECT_TRUE(isIntEqualsWord(*result_b, 3333));
232}
233
234TEST_F(CallTest, CallDefaultArgs) {
235 ASSERT_FALSE(runFromCStr(runtime_, R"(
236def foo(a=1, b=2, c=3):
237 return [a, b, c]
238
239result0 = foo(33, 22, 11)
240result1 = foo()
241result2 = foo(1001)
242result3 = foo(1001, 1002)
243result4 = foo(1001, 1002, 1003)
244)")
245 .isError());
246 HandleScope scope(thread_);
247 Object result0(&scope, mainModuleAt(runtime_, "result0"));
248 EXPECT_PYLIST_EQ(result0, {33, 22, 11});
249 Object result1(&scope, mainModuleAt(runtime_, "result1"));
250 EXPECT_PYLIST_EQ(result1, {1, 2, 3});
251 Object result2(&scope, mainModuleAt(runtime_, "result2"));
252 EXPECT_PYLIST_EQ(result2, {1001, 2, 3});
253 Object result3(&scope, mainModuleAt(runtime_, "result3"));
254 EXPECT_PYLIST_EQ(result3, {1001, 1002, 3});
255 Object result4(&scope, mainModuleAt(runtime_, "result4"));
256 EXPECT_PYLIST_EQ(result4, {1001, 1002, 1003});
257}
258
259TEST_F(CallTest, CallMethodMixPosDefaultArgs) {
260 ASSERT_FALSE(runFromCStr(runtime_, R"(
261def foo(a, b=2):
262 return [a, b]
263result = foo(1)
264)")
265 .isError());
266 HandleScope scope(thread_);
267 Object result(&scope, mainModuleAt(runtime_, "result"));
268 EXPECT_PYLIST_EQ(result, {1, 2});
269}
270
271TEST_F(CallTest, CallBoundMethodMixed) {
272 ASSERT_FALSE(runFromCStr(runtime_, R"(
273class R:
274 def m(self, a, b=2):
275 return [a, b]
276r = R()
277result = r.m(9)
278)")
279 .isError());
280 HandleScope scope(thread_);
281 Object result(&scope, mainModuleAt(runtime_, "result"));
282 EXPECT_PYLIST_EQ(result, {9, 2});
283}
284
285TEST_F(CallTest, SingleKW) {
286 ASSERT_FALSE(runFromCStr(runtime_, R"(
287def foo(bar):
288 return bar
289result = foo(bar=2)
290)")
291 .isError());
292 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 2));
293}
294
295TEST_F(CallTest, MixedKW) {
296 ASSERT_FALSE(runFromCStr(runtime_, R"(
297def foo(a, b, c):
298 return [a, b, c]
299result = foo(1, b = 2, c = 3)
300)")
301 .isError());
302 HandleScope scope(thread_);
303 Object result(&scope, mainModuleAt(runtime_, "result"));
304 EXPECT_PYLIST_EQ(result, {1, 2, 3});
305}
306
307TEST_F(CallTest, FullKW) {
308 ASSERT_FALSE(runFromCStr(runtime_, R"(
309def foo(a, b, c):
310 return [a, b, c]
311result = foo(a = 1, b = 2, c = 3)
312)")
313 .isError());
314 HandleScope scope(thread_);
315 Object result(&scope, mainModuleAt(runtime_, "result"));
316 EXPECT_PYLIST_EQ(result, {1, 2, 3});
317}
318
319TEST_F(CallTest, KWOutOfOrder1) {
320 ASSERT_FALSE(runFromCStr(runtime_, R"(
321def foo(a, b, c):
322 return [a, b, c]
323result = foo(c = 3, a = 1, b = 2)
324)")
325 .isError());
326 HandleScope scope(thread_);
327 Object result(&scope, mainModuleAt(runtime_, "result"));
328 EXPECT_PYLIST_EQ(result, {1, 2, 3});
329}
330
331TEST_F(CallTest, KWOutOfOrder2) {
332 ASSERT_FALSE(runFromCStr(runtime_, R"(
333def foo(a, b, c):
334 return [a, b, c]
335result = foo(1, c = 3, b = 2)
336)")
337 .isError());
338 HandleScope scope(thread_);
339 Object result(&scope, mainModuleAt(runtime_, "result"));
340 EXPECT_PYLIST_EQ(result, {1, 2, 3});
341}
342
343TEST_F(CallTest, KeywordOnly1) {
344 ASSERT_FALSE(runFromCStr(runtime_, R"(
345def foo(a,b, *, c):
346 return [a,b,c]
347result = foo(1, 2, c = 3)
348)")
349 .isError());
350 HandleScope scope(thread_);
351 Object result(&scope, mainModuleAt(runtime_, "result"));
352 EXPECT_PYLIST_EQ(result, {1, 2, 3});
353}
354
355TEST_F(CallTest, KeywordOnly2) {
356 ASSERT_FALSE(runFromCStr(runtime_, R"(
357def foo(a,b, *, c):
358 return [a,b,c]
359result = foo(1, b = 2, c = 3)
360)")
361 .isError());
362 HandleScope scope(thread_);
363 Object result(&scope, mainModuleAt(runtime_, "result"));
364 EXPECT_PYLIST_EQ(result, {1, 2, 3});
365}
366
367TEST_F(CallTest, KeyWordDefaults) {
368 ASSERT_FALSE(runFromCStr(runtime_, R"(
369def foo(a, b = 22, c = 33):
370 return [a,b,c]
371result = foo(11, c = 3)
372)")
373 .isError());
374 HandleScope scope(thread_);
375 Object result(&scope, mainModuleAt(runtime_, "result"));
376 EXPECT_PYLIST_EQ(result, {11, 22, 3});
377}
378
379TEST_F(CallTest, VarArgsWithExcess) {
380 ASSERT_FALSE(runFromCStr(runtime_, R"(
381def foo(a, b, *c):
382 return [a,b,c]
383result = foo(1,2,3,4,5,6)
384)")
385 .isError());
386 HandleScope scope(thread_);
387 List result(&scope, mainModuleAt(runtime_, "result"));
388 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
389 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
390 Tuple tuple(&scope, result.at(2));
391 ASSERT_EQ(tuple.length(), 4);
392 EXPECT_TRUE(isIntEqualsWord(tuple.at(0), 3));
393 EXPECT_TRUE(isIntEqualsWord(tuple.at(1), 4));
394 EXPECT_TRUE(isIntEqualsWord(tuple.at(2), 5));
395 EXPECT_TRUE(isIntEqualsWord(tuple.at(3), 6));
396}
397
398TEST_F(CallTest, VarArgsEmpty) {
399 ASSERT_FALSE(runFromCStr(runtime_, R"(
400def foo(a, b, *c):
401 return [a,b,c]
402result = foo(1,2)
403)")
404 .isError());
405 HandleScope scope(thread_);
406 List result(&scope, mainModuleAt(runtime_, "result"));
407 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
408 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
409 Tuple tuple(&scope, result.at(2));
410 EXPECT_EQ(tuple.length(), 0);
411}
412
413TEST_F(CallTest, CallWithKeywordsCalleeWithVarkeyword) {
414 ASSERT_FALSE(runFromCStr(runtime_, R"(
415def foo(a,b,c,**d):
416 return [a,b,c,d]
417result = foo(1,2,c=3,g=4,h=5,j="bar")
418)")
419 .isError());
420 HandleScope scope(thread_);
421 List result(&scope, testing::mainModuleAt(runtime_, "result"));
422 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
423 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
424 EXPECT_TRUE(isIntEqualsWord(result.at(2), 3));
425
426 Dict dict(&scope, result.at(3));
427 Str name_g(&scope, runtime_->newStrFromCStr("g"));
428 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, name_g), 4));
429 Str name_h(&scope, runtime_->newStrFromCStr("h"));
430 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, name_h), 5));
431 Str name_j(&scope, runtime_->newStrFromCStr("j"));
432 EXPECT_TRUE(isStrEqualsCStr(dictAtByStr(thread_, dict, name_j), "bar"));
433}
434
435TEST_F(CallTest, CallWithNoArgsCalleeDefaultArgsVarargsVarkeyargs) {
436 ASSERT_FALSE(runFromCStr(runtime_, R"(
437def bar(a=1, b=2, *c, **d):
438 return [a,b,c,d]
439result = bar()
440)")
441 .isError());
442 HandleScope scope(thread_);
443 List result(&scope, testing::mainModuleAt(runtime_, "result"));
444 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
445 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
446 Tuple tuple(&scope, result.at(2));
447 EXPECT_EQ(tuple.length(), 0);
448 Dict dict(&scope, result.at(3));
449 EXPECT_EQ(dict.numItems(), 0);
450}
451
452TEST_F(CallTest, CallPositionalCalleeVargsEmptyVarkeyargs) {
453 ASSERT_FALSE(runFromCStr(runtime_, R"(
454def bar(a=1, b=2, *c, **d):
455 return [a,b,c,d]
456result = bar(1,2,3,4,5,6,7)
457)")
458 .isError());
459 HandleScope scope(thread_);
460 List result(&scope, testing::mainModuleAt(runtime_, "result"));
461 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
462 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
463 Tuple tuple(&scope, result.at(2));
464 ASSERT_EQ(tuple.length(), 5);
465 EXPECT_TRUE(isIntEqualsWord(tuple.at(0), 3));
466 EXPECT_TRUE(isIntEqualsWord(tuple.at(1), 4));
467 EXPECT_TRUE(isIntEqualsWord(tuple.at(2), 5));
468 EXPECT_TRUE(isIntEqualsWord(tuple.at(3), 6));
469 EXPECT_TRUE(isIntEqualsWord(tuple.at(4), 7));
470 Dict dict(&scope, result.at(3));
471 EXPECT_EQ(dict.numItems(), 0);
472}
473
474TEST_F(CallTest, CallWithKeywordsCalleeEmptyVarargsFullVarkeyargs) {
475 ASSERT_FALSE(runFromCStr(runtime_, R"(
476def bar(a=1, b=2, *c, **d):
477 return [a,b,c,d]
478result = bar(a1=11, a2=12, a3=13)
479)")
480 .isError());
481 HandleScope scope(thread_);
482 List result(&scope, testing::mainModuleAt(runtime_, "result"));
483 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
484 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
485
486 Object tuple_obj(&scope, result.at(2));
487 ASSERT_TRUE(tuple_obj.isTuple());
488 Tuple tuple(&scope, *tuple_obj);
489 EXPECT_EQ(tuple.length(), 0);
490
491 Dict dict(&scope, result.at(3));
492 Str name0(&scope, runtime_->newStrFromCStr("a3"));
493 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, name0), 13));
494 Str name1(&scope, runtime_->newStrFromCStr("a1"));
495 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, name1), 11));
496 Str name2(&scope, runtime_->newStrFromCStr("a2"));
497 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, name2), 12));
498}
499
500TEST_F(CallTest, CallWithKeywordsCalleeFullVarargsFullVarkeyargs) {
501 ASSERT_FALSE(runFromCStr(runtime_, R"(
502def bar(a=1, b=2, *c, **d):
503 return [a,b,c,d]
504result = bar(1,2,3,4,5,6,7,a9=9)
505)")
506 .isError());
507 HandleScope scope(thread_);
508 List result(&scope, testing::mainModuleAt(runtime_, "result"));
509 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
510 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
511
512 Tuple tuple(&scope, result.at(2));
513 EXPECT_TRUE(isIntEqualsWord(tuple.at(0), 3));
514 EXPECT_TRUE(isIntEqualsWord(tuple.at(1), 4));
515 EXPECT_TRUE(isIntEqualsWord(tuple.at(2), 5));
516 EXPECT_TRUE(isIntEqualsWord(tuple.at(3), 6));
517 EXPECT_TRUE(isIntEqualsWord(tuple.at(4), 7));
518
519 Dict dict(&scope, result.at(3));
520 Str name_g(&scope, runtime_->newStrFromCStr("a9"));
521 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, name_g), 9));
522}
523
524TEST_F(CallTest, CallWithOutOfOrderKeywords) {
525 ASSERT_FALSE(runFromCStr(runtime_, R"(
526def foobar(a,b,*,c):
527 return [a,b,c]
528result = foobar(c=3,a=1,b=2)
529)")
530 .isError());
531 HandleScope scope(thread_);
532 Object result(&scope, mainModuleAt(runtime_, "result"));
533 EXPECT_PYLIST_EQ(result, {1, 2, 3});
534}
535
536TEST_F(CallTest, CallWithKeywordsCalleeVarargsKeywordOnly) {
537 ASSERT_FALSE(runFromCStr(runtime_, R"(
538def foobar1(a,b,*c,d):
539 return [a,b,c,d]
540result = foobar1(1,2,3,4,5,d=9)
541)")
542 .isError());
543 HandleScope scope(thread_);
544 List result(&scope, mainModuleAt(runtime_, "result"));
545 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
546 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
547 Tuple tuple(&scope, result.at(2));
548 ASSERT_EQ(tuple.length(), 3);
549 EXPECT_TRUE(isIntEqualsWord(tuple.at(0), 3));
550 EXPECT_TRUE(isIntEqualsWord(tuple.at(1), 4));
551 EXPECT_TRUE(isIntEqualsWord(tuple.at(2), 5));
552 EXPECT_TRUE(isIntEqualsWord(result.at(3), 9));
553}
554
555TEST_F(CallTest, CallWithKeywordsCalleeVarargsVarkeyargsKeywordOnly) {
556 ASSERT_FALSE(runFromCStr(runtime_, R"(
557def foobar2(a,b,*c, e, **d):
558 return [a,b,c,d,e]
559result = foobar2(1,e=9,b=2,f1="a",f11=12)
560)")
561 .isError());
562 HandleScope scope(thread_);
563 List result(&scope, mainModuleAt(runtime_, "result"));
564 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
565 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
566 Tuple tuple(&scope, result.at(2));
567 ASSERT_EQ(tuple.length(), 0);
568 Dict dict(&scope, result.at(3));
569 Str f1(&scope, runtime_->newStrFromCStr("f1"));
570 EXPECT_TRUE(isStrEqualsCStr(dictAtByStr(thread_, dict, f1), "a"));
571 Str f11(&scope, runtime_->newStrFromCStr("f11"));
572 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, dict, f11), 12));
573 EXPECT_TRUE(isIntEqualsWord(result.at(4), 9));
574}
575
576TEST_F(CallTest, CallEx) {
577 ASSERT_FALSE(runFromCStr(runtime_, R"(
578def foo(a,b,c,d):
579 return [a,b,c,d]
580a = (1,2,3,4)
581result = foo(*a)
582)")
583 .isError());
584 HandleScope scope(thread_);
585 Object result(&scope, mainModuleAt(runtime_, "result"));
586 EXPECT_PYLIST_EQ(result, {1, 2, 3, 4});
587}
588
589TEST_F(CallTest, CallExBuildTupleUnpackWithCall) {
590 ASSERT_FALSE(runFromCStr(runtime_, R"(
591def foo(a,b,c,d):
592 return [a,b,c,d]
593a = (3,4)
594result = foo(1,2,*a)
595)")
596 .isError());
597 HandleScope scope(thread_);
598 Object result(&scope, mainModuleAt(runtime_, "result"));
599 EXPECT_PYLIST_EQ(result, {1, 2, 3, 4});
600}
601
602TEST_F(CallTest, CallExKw) {
603 ASSERT_FALSE(runFromCStr(runtime_, R"(
604def foo(a,b,c,d):
605 return [a,b,c,d]
606a = {'d': 4, 'b': 2, 'a': 1, 'c': 3}
607result = foo(**a)
608)")
609 .isError());
610 HandleScope scope(thread_);
611 Object result(&scope, mainModuleAt(runtime_, "result"));
612 EXPECT_PYLIST_EQ(result, {1, 2, 3, 4});
613}
614
615TEST_F(CallTest, KeywordOnly) {
616 const char* src = R"(
617def foo(a,b, *, c):
618 print(a,b,c)
619foo(1, 2, 3);
620)";
621 EXPECT_TRUE(raised(runFromCStr(runtime_, src), LayoutId::kTypeError));
622}
623
624TEST_F(CallTest, MissingKeyword) {
625 const char* src = R"(
626def foo(a,b, *, c):
627 print(a,b,c)
628foo(1, 2);
629)";
630 EXPECT_TRUE(raised(runFromCStr(runtime_, src), LayoutId::kTypeError));
631}
632
633TEST_F(CallTest, ArgNameMismatch) {
634 const char* src = R"(
635def foo(a,b, *, c):
636 print(a,b,c)
637foo(1, d = 2, c = 3);
638)";
639 EXPECT_TRUE(raised(runFromCStr(runtime_, src), LayoutId::kTypeError));
640}
641
642TEST_F(CallTest, TooManyKWArgs) {
643 const char* src = R"(
644def foo(a,b, *, c):
645 print(a,b,c)
646foo(1, 2, 4, c = 3);
647)";
648 EXPECT_TRUE(raised(runFromCStr(runtime_, src), LayoutId::kTypeError));
649}
650
651TEST_F(CallTest, TooManyArgs) {
652 const char* src = R"(
653def foo(a,b, c):
654 print(a,b,c)
655foo(1, 2, 3, 4);
656)";
657 EXPECT_TRUE(raised(runFromCStr(runtime_, src), LayoutId::kTypeError));
658}
659
660TEST_F(CallTest, TooFewArgs) {
661 const char* src = R"(
662def foo(a,b, c):
663 print(a,b,c)
664foo(3, 4);
665)";
666 EXPECT_TRUE(raised(runFromCStr(runtime_, src), LayoutId::kTypeError));
667}
668
669static ALIGN_16 RawObject builtinReturnSecondArg(Thread*, Arguments args) {
670 return args.get(1);
671}
672
673static void createAndPatchBuiltinReturnSecondArg(Runtime* runtime) {
674 // Ensure we have a __main__ module.
675 ASSERT_FALSE(runFromCStr(runtime, "").isError());
676 // def dummy(first, second):
677 const char* parameter_names[] = {"first", "second"};
678 addBuiltin("dummy", builtinReturnSecondArg, parameter_names, 0);
679}
680
681TEST_F(TrampolinesTest, BuiltinTrampolineKwPassesKwargs) {
682 HandleScope scope(thread_);
683 createAndPatchBuiltinReturnSecondArg(runtime_);
684 ASSERT_FALSE(runFromCStr(runtime_, "result = dummy(second=12345, first=None)")
685 .isError());
686 Object result(&scope, mainModuleAt(runtime_, "result"));
687 EXPECT_TRUE(isIntEqualsWord(*result, 12345));
688}
689
690TEST_F(TrampolinesTest, BuiltinTrampolineKwWithInvalidArgRaisesTypeError) {
691 createAndPatchBuiltinReturnSecondArg(runtime_);
692 EXPECT_TRUE(raisedWithStr(
693 runFromCStr(runtime_, "dummy(third=3, first=1)"), LayoutId::kTypeError,
694 "dummy() got an unexpected keyword argument 'third'"));
695}
696
697TEST_F(TrampolinesTest, InterpreterClosureUsesArgOverCellValue) {
698 HandleScope scope(thread_);
699
700 // Create code object
701 word nlocals = 1;
702 Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar"));
703 Tuple varnames(&scope, runtime_->newTupleWithN(nlocals, &bar));
704 Tuple cellvars(&scope, runtime_->newTupleWith1(bar));
705 const byte bytecode[] = {LOAD_CLOSURE, 0, LOAD_DEREF, 0, RETURN_VALUE, 0};
706 Bytes bc(&scope, runtime_->newBytesWithAll(bytecode));
707 Tuple empty_tuple(&scope, runtime_->emptyTuple());
708 Object empty_str(&scope, Str::empty());
709 Object empty_bytes(&scope, Bytes::empty());
710 word flags = Code::Flags::kOptimized | Code::Flags::kNewlocals;
711 Code code(&scope,
712 runtime_->newCode(/*argcount=*/1, /*posonlyargcount=*/0,
713 /*kwonlyargcount=*/0, nlocals, /*stacksize=*/0,
714 flags, /*code=*/bc, /*consts=*/empty_tuple,
715 /*names=*/empty_tuple, varnames,
716 /*freevars=*/empty_tuple, cellvars,
717 /*filename=*/empty_str, /*name=*/empty_str,
718 /*firstlineno=*/0, /*lnotab=*/empty_bytes));
719 ASSERT_TRUE(!code.cell2arg().isNoneType());
720
721 Object qualname(&scope, runtime_->newStrFromCStr("foo"));
722 Module module(&scope, findMainModule(runtime_));
723 Function foo(&scope,
724 runtime_->newFunctionWithCode(thread_, qualname, code, module));
725 Object obj(&scope, runtime_->newInt(99));
726 Tuple closure_tuple(&scope, runtime_->newTupleWith1(obj));
727 foo.setClosure(*closure_tuple);
728
729 Object argument(&scope, runtime_->newInt(3));
730 EXPECT_TRUE(isIntEqualsWord(Interpreter::call1(thread_, foo, argument), 3));
731}
732
733TEST_F(TrampolinesTest, InterpreterClosureUsesCellValue) {
734 HandleScope scope(thread_);
735 ASSERT_FALSE(runFromCStr(runtime_, R"(
736def foo(arg):
737 def bar():
738 return arg * 3
739 arg = 5
740 return bar()
741
742result = foo(-2)
743)")
744 .isError());
745 Function foo(&scope, mainModuleAt(runtime_, "foo"));
746 ASSERT_EQ(foo.entry(), &interpreterTrampoline);
747 // Ensure that cellvar was populated.
748 Code code(&scope, foo.code());
749 ASSERT_TRUE(!code.cell2arg().isNoneType());
750 Tuple cellvars(&scope, code.cellvars());
751 ASSERT_EQ(cellvars.length(), 1);
752 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 15));
753}
754
755static RawObject makeFunctionWithPosOnlyArg(Thread* thread) {
756 // Create:
757 // def foo(a, /, b):
758 // return (a, b)
759 HandleScope scope(thread);
760 Runtime* runtime = thread->runtime();
761 Object name(&scope, Runtime::internStrFromCStr(thread, "foo"));
762 const byte bytecode[] = {LOAD_FAST, 0, LOAD_FAST, 1,
763 BUILD_TUPLE, 2, RETURN_VALUE, 0};
764 Object a(&scope, Runtime::internStrFromCStr(thread, "a"));
765 Object b(&scope, Runtime::internStrFromCStr(thread, "b"));
766 Tuple varnames(&scope, runtime->newTupleWith2(a, b));
767 Bytes bc(&scope, runtime->newBytesWithAll(bytecode));
768 Object empty_tuple(&scope, runtime->emptyTuple());
769 Object empty_str(&scope, Str::empty());
770 Object empty_bytes(&scope, Bytes::empty());
771 Code code(&scope,
772 runtime->newCode(/*argcount=*/2, /*posonlyargcount=*/1,
773 /*kwonlyargcount=*/0, /*nlocals=*/2,
774 /*stacksize=*/2,
775 Code::Flags::kNewlocals | Code::Flags::kOptimized,
776 bc, /*consts=*/empty_tuple,
777 /*names=*/empty_tuple, varnames,
778 /*freevars=*/empty_tuple,
779 /*cellvars=*/empty_tuple,
780 /*filename=*/empty_str, name,
781 /*firstlineno=*/0, /*lnotab=*/empty_bytes));
782 Module module(&scope, findMainModule(runtime));
783 return runtime->newFunctionWithCode(thread, name, code, module);
784}
785
786TEST_F(TrampolinesTest, KeywordCallRejectsPositionalOnlyArgumentNames) {
787 HandleScope scope(thread_);
788 Function function(&scope, makeFunctionWithPosOnlyArg(thread_));
789
790 // `foo(a=2, b=4)`
791 thread_->stackPush(*function);
792 thread_->stackPush(runtime_->newInt(2));
793 thread_->stackPush(runtime_->newInt(4));
794 Object a(&scope, Runtime::internStrFromCStr(thread_, "a"));
795 Object b(&scope, Runtime::internStrFromCStr(thread_, "b"));
796 thread_->stackPush(runtime_->newTupleWith2(a, b));
797 Object result_obj(&scope, Interpreter::callKw(thread_, 2));
798 EXPECT_TRUE(raisedWithStr(
799 *result_obj, LayoutId::kTypeError,
800 "keyword argument specified for positional-only argument 'a'"));
801}
802
803TEST_F(TrampolinesTest, KeywordCallAcceptsNonPositionalOnlyArgumentNames) {
804 HandleScope scope(thread_);
805 Function function(&scope, makeFunctionWithPosOnlyArg(thread_));
806
807 // `foo(2, b=9)`
808 thread_->stackPush(*function);
809 thread_->stackPush(runtime_->newInt(2));
810 thread_->stackPush(runtime_->newInt(9));
811 Object b(&scope, Runtime::internStrFromCStr(thread_, "b"));
812 thread_->stackPush(runtime_->newTupleWith1(b));
813 Object result_obj(&scope, Interpreter::callKw(thread_, 2));
814 ASSERT_TRUE(result_obj.isTuple());
815 Tuple result(&scope, *result_obj);
816 ASSERT_EQ(result.length(), 2);
817 EXPECT_TRUE(isIntEqualsWord(result.at(0), 2));
818 EXPECT_TRUE(isIntEqualsWord(result.at(1), 9));
819}
820
821TEST_F(TrampolinesTest, KeywordCallWithPositionalOnlyArgumentsAndVarKeyArgs) {
822 HandleScope scope(thread_);
823
824 // Create:
825 // def foo(a, b=7, /, c=10, **kwargs):
826 // return (a, b, c, kwargs)
827 Object name(&scope, Runtime::internStrFromCStr(thread_, "foo"));
828 const byte bytecode[] = {LOAD_FAST, 0, LOAD_FAST, 1, LOAD_FAST, 2,
829 LOAD_FAST, 3, BUILD_TUPLE, 4, RETURN_VALUE, 0};
830 Object a(&scope, Runtime::internStrFromCStr(thread_, "a"));
831 Object b(&scope, Runtime::internStrFromCStr(thread_, "b"));
832 Object c(&scope, Runtime::internStrFromCStr(thread_, "c"));
833 Object kwargs(&scope, Runtime::internStrFromCStr(thread_, "kwargs"));
834 Tuple varnames(&scope, runtime_->newTupleWith4(a, b, c, kwargs));
835 Bytes bc(&scope, runtime_->newBytesWithAll(bytecode));
836 Object empty_tuple(&scope, runtime_->emptyTuple());
837 Object empty_str(&scope, Str::empty());
838 Object empty_bytes(&scope, Bytes::empty());
839 Code code(&scope, runtime_->newCode(
840 /*argcount=*/3, /*posonlyargcount=*/2,
841 /*kwonlyargcount=*/0, /*nlocals=*/4,
842 /*stacksize=*/4,
843 Code::Flags::kNewlocals | Code::Flags::kOptimized |
844 Code::Flags::kVarkeyargs,
845 bc,
846 /*consts=*/empty_tuple,
847 /*names=*/empty_tuple, varnames,
848 /*freevars=*/empty_tuple,
849 /*cellvars=*/empty_tuple,
850 /*filename=*/empty_str, name,
851 /*firstlineno=*/0, /*lnotab=*/empty_bytes));
852 Module module(&scope, findMainModule(runtime_));
853 Function foo(&scope,
854 runtime_->newFunctionWithCode(thread_, name, code, module));
855 Object seven(&scope, runtime_->newInt(7));
856 Object ten(&scope, runtime_->newInt(10));
857 foo.setDefaults(runtime_->newTupleWith2(seven, ten));
858 // Call foo(1, c=13, b=5).
859 thread_->stackPush(*foo);
860 thread_->stackPush(runtime_->newInt(1));
861 thread_->stackPush(runtime_->newInt(13));
862 thread_->stackPush(runtime_->newInt(5));
863 thread_->stackPush(runtime_->newTupleWith2(c, b));
864 Object result_obj(&scope, Interpreter::callKw(thread_, 3));
865
866 // Expect a `(1, 7, 13, {'b': 5})` result.
867 ASSERT_TRUE(result_obj.isTuple());
868 Tuple result(&scope, *result_obj);
869 ASSERT_EQ(result.length(), 4);
870 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
871 EXPECT_TRUE(isIntEqualsWord(result.at(1), 7));
872 EXPECT_TRUE(isIntEqualsWord(result.at(2), 13));
873 ASSERT_TRUE(result.at(3).isDict());
874 Dict result_dict(&scope, result.at(3));
875 EXPECT_EQ(result_dict.numItems(), 1);
876 Object b_name(&scope, Runtime::internStrFromCStr(thread_, "b"));
877 EXPECT_TRUE(isIntEqualsWord(dictAtByStr(thread_, result_dict, b_name), 5));
878}
879
880TEST_F(TrampolinesTest, ExplodeCallWithBadKeywordFails) {
881 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
882def take_kwargs(a): pass
883
884kwargs = {12: 34}
885take_kwargs(**kwargs)
886)"),
887 LayoutId::kTypeError, "keywords must be strings"));
888}
889
890TEST_F(TrampolinesTest, ExplodeCallWithZeroKeywords) {
891 ASSERT_FALSE(runFromCStr(runtime_, R"(
892def foo(a=10): return a
893result = foo(**{})
894)")
895 .isError());
896 HandleScope scope(thread_);
897 Object result(&scope, mainModuleAt(runtime_, "result"));
898 EXPECT_EQ(result, SmallInt::fromWord(10));
899}
900
901static ALIGN_16 RawObject numArgs(Thread* thread, Arguments) {
902 return SmallInt::fromWord(thread->currentFrame()->function().totalArgs());
903}
904
905static void createAndPatchBuiltinNumArgs(Runtime* runtime) {
906 // Ensure we have a __main__ module.
907 ASSERT_FALSE(runFromCStr(runtime, "").isError());
908 // def dummy(first, second):
909 const char* parameter_names[] = {"first", "second"};
910 addBuiltin("dummy", numArgs, parameter_names, 0);
911}
912
913TEST_F(TrampolinesTest, BuiltinTrampolineExReceivesExArgs) {
914 createAndPatchBuiltinNumArgs(runtime_);
915 HandleScope scope(thread_);
916 ASSERT_FALSE(runFromCStr(runtime_, "result = dummy(*(1,2))").isError());
917 Object result(&scope, mainModuleAt(runtime_, "result"));
918 EXPECT_TRUE(isIntEqualsWord(*result, 2));
919}
920
921TEST_F(TrampolinesTest, BuiltinTrampolineExReceivesMixOfPositionalAndExArgs1) {
922 createAndPatchBuiltinNumArgs(runtime_);
923 HandleScope scope(thread_);
924 ASSERT_FALSE(runFromCStr(runtime_, "result = dummy(1, *(2,))").isError());
925 Object result(&scope, mainModuleAt(runtime_, "result"));
926 EXPECT_TRUE(isIntEqualsWord(*result, 2));
927}
928
929static void createAndPatchBuiltinNumArgsVariadic(Runtime* runtime) {
930 // Ensure we have a __main__ module.
931 ASSERT_FALSE(runFromCStr(runtime, "").isError());
932 // def dummy(*args):
933 const char* parameter_names[] = {"args"};
934 addBuiltin("dummy", numArgs, parameter_names, Code::Flags::kVarargs);
935}
936
937TEST_F(TrampolinesTest,
938 BuiltinTrampolineExReceivesOnePositionalArgAndTwoVariableArgs) {
939 createAndPatchBuiltinNumArgsVariadic(runtime_);
940 HandleScope scope(thread_);
941 ASSERT_FALSE(runFromCStr(runtime_, "result = dummy(1, *(2, 3))").isError());
942 Object result(&scope, mainModuleAt(runtime_, "result"));
943 EXPECT_TRUE(isIntEqualsWord(*result, 1));
944}
945
946static void createAndPatchBuiltinNumArgsArgsKwargs(Runtime* runtime) {
947 // Ensure we have a __main__ module.
948 ASSERT_FALSE(runFromCStr(runtime, "").isError());
949 // def dummy(*args, **kwargs):
950 const char* parameter_names[] = {"args", "kwargs"};
951 addBuiltin("dummy", numArgs, parameter_names,
952 Code::Flags::kVarargs | Code::Flags::kVarkeyargs);
953}
954
955TEST_F(TrampolinesTest,
956 BuiltinTrampolineExReceivesTwoPositionalOneVariableAndTwoKwArgs) {
957 createAndPatchBuiltinNumArgsArgsKwargs(runtime_);
958 HandleScope scope(thread_);
959 ASSERT_FALSE(
960 runFromCStr(runtime_,
961 "result = dummy(1, 2, *(3,), **{'foo': 1, 'bar': 2})")
962 .isError());
963 Object result(&scope, mainModuleAt(runtime_, "result"));
964 EXPECT_TRUE(isIntEqualsWord(*result, 2));
965}
966
967TEST_F(TrampolinesTest, BuiltinTrampolineExReceivesVarArgs) {
968 createAndPatchBuiltinNumArgs(runtime_);
969 HandleScope scope(thread_);
970 ASSERT_FALSE(
971 runFromCStr(runtime_, "result = dummy(*(1,), second=5)").isError());
972 Object result(&scope, mainModuleAt(runtime_, "result"));
973 EXPECT_TRUE(isIntEqualsWord(*result, 2));
974}
975
976TEST_F(TrampolinesTest, BuiltinTrampolineExWithTooFewArgsRaisesTypeError) {
977 createAndPatchBuiltinNumArgs(runtime_);
978 EXPECT_TRUE(
979 raisedWithStr(runFromCStr(runtime_, "dummy(*(1,))"), LayoutId::kTypeError,
980 "'dummy' takes min 2 positional arguments but 1 given"));
981}
982
983TEST_F(TrampolinesTest, BuiltinTrampolineExWithTooManyArgsRaisesTypeError) {
984 createAndPatchBuiltinNumArgs(runtime_);
985 EXPECT_TRUE(raisedWithStr(
986 runFromCStr(runtime_, "dummy(*(1,2,3,4,5))"), LayoutId::kTypeError,
987 "'dummy' takes max 2 positional arguments but 5 given"));
988}
989
990TEST_F(TrampolinesTest, CallFunctionExWithNamedArgAndExplodeKwargs) {
991 ASSERT_FALSE(runFromCStr(runtime_, R"(
992def f(description, conflict_handler):
993 return [description, conflict_handler]
994
995result = f(description="foo", **{"conflict_handler": "conflict_handler value"})
996)")
997 .isError());
998 HandleScope scope(thread_);
999 Object result(&scope, mainModuleAt(runtime_, "result"));
1000 EXPECT_PYLIST_EQ(result, {"foo", "conflict_handler value"});
1001}
1002
1003TEST_F(TrampolinesTest, CallFunctionExWithExplodeKwargsStrSubclassAlwaysEq) {
1004 ASSERT_FALSE(runFromCStr(runtime_, R"(
1005class C(str):
1006 def __eq__(self, other):
1007 return True
1008 __hash__ = str.__hash__
1009
1010def f(param):
1011 return param
1012
1013actual = C("foo")
1014result = f(**{actual: 5})
1015)")
1016 .isError());
1017 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 5));
1018}
1019
1020TEST_F(TrampolinesTest,
1021 CallFunctionExWithExplodeKwargsStrSubclassReturnNonBool) {
1022 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1023class D:
1024 def __bool__(self):
1025 raise UserWarning('foo')
1026
1027class C(str):
1028 def __eq__(self, other):
1029 return D()
1030 __hash__ = str.__hash__
1031
1032def f(param):
1033 return param
1034
1035actual = C("foo")
1036result = f(**{actual: 5})
1037)"),
1038 LayoutId::kUserWarning, "foo"));
1039}
1040
1041TEST_F(TrampolinesTest,
1042 CallFunctionExWithExplodeKwargsStrSubclassRaiseException) {
1043 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1044class C(str):
1045 def __eq__(self, other):
1046 raise UserWarning('foo')
1047 __hash__ = str.__hash__
1048
1049def f(param):
1050 return param
1051
1052actual = C("foo")
1053result = f(**{actual: 5})
1054)"),
1055 LayoutId::kUserWarning, "foo"));
1056}
1057
1058TEST_F(TrampolinesTest, CallFunctionExWithExplodeKwargsStrSubclassNotEq) {
1059 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1060class C(str):
1061 __hash__ = str.__hash__
1062
1063def f(param):
1064 return param
1065
1066actual = C("foo")
1067result = f(**{actual: 5})
1068)"),
1069 LayoutId::kTypeError,
1070 "f() got an unexpected keyword argument 'foo'"));
1071}
1072
1073TEST_F(TrampolinesTest, CallFunctionExWithExplodeKwargsStrSubclassNeverEq) {
1074 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1075class C(str):
1076 def __eq__(self, other):
1077 return False
1078 __hash__ = str.__hash__
1079
1080def f(param):
1081 return param
1082
1083actual = C("param")
1084result = f(**{actual: 5})
1085)"),
1086 LayoutId::kTypeError,
1087 "f() got an unexpected keyword argument 'param'"));
1088}
1089
1090TEST_F(TrampolinesTest, CallFunctionWithParameterInVarnames) {
1091 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1092def add_argument(*args, **kwargs):
1093 action = action_class(**kwargs)
1094
1095def init():
1096 add_argument(action='help')
1097
1098init()
1099)"),
1100 LayoutId::kNameError,
1101 "name 'action_class' is not defined"));
1102}
1103
1104TEST_F(TrampolinesTest, CallFunctionWithParameterInVarargname) {
1105 ASSERT_FALSE(runFromCStr(runtime_, R"(
1106def test(*args, **kwargs):
1107 return kwargs['args']
1108
1109result = test(args=5)
1110)")
1111 .isError());
1112 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 5));
1113}
1114
1115TEST_F(TrampolinesTest, CallFunctionWithPositionalArgAndParameterInVarargname) {
1116 ASSERT_FALSE(runFromCStr(runtime_, R"(
1117def test(pos, *args, **kwargs):
1118 return kwargs['args']
1119
1120result = test(1, args=5)
1121)")
1122 .isError());
1123 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 5));
1124}
1125
1126} // namespace testing
1127} // namespace py