this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "builtins-module.h"
3
4#include "gtest/gtest.h"
5
6#include "builtins.h"
7#include "dict-builtins.h"
8#include "module-builtins.h"
9#include "runtime.h"
10#include "str-builtins.h"
11#include "test-utils.h"
12#include "trampolines.h"
13
14namespace py {
15namespace testing {
16
17using BuiltinsModuleTest = RuntimeFixture;
18using BuiltinsModuleDeathTest = RuntimeFixture;
19
20TEST_F(BuiltinsModuleTest, BuiltinCallableOnTypeReturnsTrue) {
21 ASSERT_FALSE(runFromCStr(runtime_, R"(
22class Foo:
23 pass
24
25a = callable(Foo)
26 )")
27 .isError());
28 HandleScope scope(thread_);
29 Bool a(&scope, mainModuleAt(runtime_, "a"));
30 EXPECT_TRUE(a.value());
31}
32
33TEST_F(BuiltinsModuleTest, BuiltinCallableOnMethodReturnsTrue) {
34 ASSERT_FALSE(runFromCStr(runtime_, R"(
35class Foo:
36 def bar():
37 return None
38
39a = callable(Foo.bar)
40b = callable(Foo().bar)
41 )")
42 .isError());
43 HandleScope scope(thread_);
44 Bool a(&scope, mainModuleAt(runtime_, "a"));
45 Bool b(&scope, mainModuleAt(runtime_, "b"));
46 EXPECT_TRUE(a.value());
47 EXPECT_TRUE(b.value());
48}
49
50TEST_F(BuiltinsModuleTest, BuiltinCallableOnNonCallableReturnsFalse) {
51 ASSERT_FALSE(runFromCStr(runtime_, R"(
52a = callable(1)
53b = callable("hello")
54 )")
55 .isError());
56 HandleScope scope(thread_);
57 Bool a(&scope, mainModuleAt(runtime_, "a"));
58 Bool b(&scope, mainModuleAt(runtime_, "b"));
59 EXPECT_FALSE(a.value());
60 EXPECT_FALSE(b.value());
61}
62
63TEST_F(BuiltinsModuleTest, BuiltinCallableOnObjectWithCallOnTypeReturnsTrue) {
64 ASSERT_FALSE(runFromCStr(runtime_, R"(
65class Foo:
66 def __call__(self):
67 pass
68
69f = Foo()
70a = callable(f)
71 )")
72 .isError());
73 HandleScope scope(thread_);
74 Bool a(&scope, mainModuleAt(runtime_, "a"));
75 EXPECT_TRUE(a.value());
76}
77
78TEST_F(BuiltinsModuleTest,
79 BuiltinCallableOnObjectWithInstanceCallButNoTypeCallReturnsFalse) {
80 ASSERT_FALSE(runFromCStr(runtime_, R"(
81class Foo:
82 pass
83
84def fakecall():
85 pass
86
87f = Foo()
88f.__call__ = fakecall
89a = callable(f)
90 )")
91 .isError());
92 HandleScope scope(thread_);
93 Bool a(&scope, mainModuleAt(runtime_, "a"));
94 EXPECT_FALSE(a.value());
95}
96
97TEST_F(BuiltinsModuleTest, DirCallsDunderDirReturnsSortedList) {
98 HandleScope scope(thread_);
99 ASSERT_FALSE(runFromCStr(runtime_, R"(
100class C:
101 def __dir__(self):
102 return ["B", "A"]
103c = C()
104d = dir(c)
105)")
106 .isError());
107 Object d_obj(&scope, mainModuleAt(runtime_, "d"));
108 ASSERT_TRUE(d_obj.isList());
109 List d(&scope, *d_obj);
110 ASSERT_EQ(d.numItems(), 2);
111 EXPECT_TRUE(isStrEqualsCStr(d.at(0), "A"));
112 EXPECT_TRUE(isStrEqualsCStr(d.at(1), "B"));
113}
114
115TEST_F(BuiltinsModuleTest, EllipsisMatchesEllipsis) {
116 EXPECT_EQ(moduleAtByCStr(runtime_, "builtins", "Ellipsis"),
117 runtime_->ellipsis());
118}
119
120TEST_F(BuiltinsModuleTest, IdReturnsInt) {
121 HandleScope scope(thread_);
122 Object obj(&scope, runtime_->newInt(12345));
123 EXPECT_TRUE(runBuiltin(FUNC(builtins, id), obj).isInt());
124}
125
126TEST_F(BuiltinsModuleTest, IdDoesNotChangeAfterGC) {
127 HandleScope scope(thread_);
128 Object obj(&scope, runtime_->newStrFromCStr("hello world foobar"));
129 Object id_before(&scope, runBuiltin(FUNC(builtins, id), obj));
130 runtime_->collectGarbage();
131 Object id_after(&scope, runBuiltin(FUNC(builtins, id), obj));
132 EXPECT_EQ(*id_before, *id_after);
133}
134
135TEST_F(BuiltinsModuleTest, IdReturnsDifferentValueForDifferentObject) {
136 HandleScope scope(thread_);
137 Object obj1(&scope, runtime_->newStrFromCStr("hello world foobar"));
138 Object obj2(&scope, runtime_->newStrFromCStr("hello world foobarbaz"));
139 EXPECT_NE(runBuiltin(FUNC(builtins, id), obj1),
140 runBuiltin(FUNC(builtins, id), obj2));
141}
142
143TEST_F(BuiltinsModuleTest, BuiltinLenGetLenFromDict) {
144 ASSERT_FALSE(runFromCStr(runtime_, R"(
145len0 = len({})
146len1 = len({'one': 1})
147len5 = len({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5})
148)")
149 .isError());
150
151 HandleScope scope(thread_);
152 Object len0(&scope, mainModuleAt(runtime_, "len0"));
153 EXPECT_EQ(*len0, SmallInt::fromWord(0));
154 Object len1(&scope, mainModuleAt(runtime_, "len1"));
155 EXPECT_EQ(*len1, SmallInt::fromWord(1));
156 Object len5(&scope, mainModuleAt(runtime_, "len5"));
157 EXPECT_EQ(*len5, SmallInt::fromWord(5));
158}
159
160TEST_F(BuiltinsModuleTest, BuiltinLenGetLenFromList) {
161 ASSERT_FALSE(runFromCStr(runtime_, R"(
162len0 = len([])
163len1 = len([1])
164len5 = len([1,2,3,4,5])
165)")
166 .isError());
167
168 HandleScope scope(thread_);
169 Object len0(&scope, mainModuleAt(runtime_, "len0"));
170 EXPECT_EQ(*len0, SmallInt::fromWord(0));
171 Object len1(&scope, mainModuleAt(runtime_, "len1"));
172 EXPECT_EQ(*len1, SmallInt::fromWord(1));
173 Object len5(&scope, mainModuleAt(runtime_, "len5"));
174 EXPECT_EQ(*len5, SmallInt::fromWord(5));
175}
176
177TEST_F(BuiltinsModuleTest, BuiltinLenGetLenFromSet) {
178 ASSERT_FALSE(runFromCStr(runtime_, R"(
179len1 = len({1})
180len5 = len({1,2,3,4,5})
181)")
182 .isError());
183
184 HandleScope scope(thread_);
185 // TODO(cshapiro): test the empty set when we have builtins.set defined.
186 Object len1(&scope, mainModuleAt(runtime_, "len1"));
187 EXPECT_EQ(*len1, SmallInt::fromWord(1));
188 Object len5(&scope, mainModuleAt(runtime_, "len5"));
189 EXPECT_EQ(*len5, SmallInt::fromWord(5));
190}
191
192TEST_F(BuiltinsModuleTest, BuiltinOrd) {
193 HandleScope scope(thread_);
194 Str str(&scope, runtime_->newStrFromCStr("A"));
195 EXPECT_TRUE(isIntEqualsWord(runBuiltin(FUNC(builtins, ord), str), 65));
196 Int one(&scope, SmallInt::fromWord(1));
197 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), one),
198 LayoutId::kTypeError,
199 "Unsupported type in builtin 'ord'"));
200}
201
202TEST_F(BuiltinsModuleTest, BuiltinOrdWithBytearray) {
203 ASSERT_FALSE(runFromCStr(runtime_, R"(
204a_bytearray = bytearray(b'A')
205)")
206 .isError());
207 HandleScope scope(thread_);
208 Object a_bytearray(&scope, mainModuleAt(runtime_, "a_bytearray"));
209 EXPECT_TRUE(
210 isIntEqualsWord(runBuiltin(FUNC(builtins, ord), a_bytearray), 65));
211}
212
213TEST_F(BuiltinsModuleTest, BuiltinOrdWithEmptyBytearrayRaisesTypeError) {
214 ASSERT_FALSE(runFromCStr(runtime_, R"(
215a_bytearray = bytearray(b'')
216)")
217 .isError());
218 HandleScope scope(thread_);
219 Object empty(&scope, mainModuleAt(runtime_, "a_bytearray"));
220 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), empty),
221 LayoutId::kTypeError,
222 "Builtin 'ord' expects string of length 1"));
223}
224
225TEST_F(BuiltinsModuleTest, BuiltinOrdWithLongBytearrayRaisesTypeError) {
226 ASSERT_FALSE(runFromCStr(runtime_, R"(
227a_bytearray = bytearray(b'AB')
228)")
229 .isError());
230 HandleScope scope(thread_);
231 Object not_a_char(&scope, mainModuleAt(runtime_, "a_bytearray"));
232 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), not_a_char),
233 LayoutId::kTypeError,
234 "Builtin 'ord' expects string of length 1"));
235}
236
237TEST_F(BuiltinsModuleTest, BuiltinOrdWithBytes) {
238 unsigned char bytes[] = {'A'};
239 HandleScope scope(thread_);
240 Object a_bytes(&scope, runtime_->newBytesWithAll(bytes));
241 EXPECT_TRUE(isIntEqualsWord(runBuiltin(FUNC(builtins, ord), a_bytes), 65));
242}
243
244TEST_F(BuiltinsModuleTest, BuiltinOrdWithEmptyBytesRaisesTypeError) {
245 HandleScope scope(thread_);
246 Object empty(&scope, Bytes::empty());
247 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), empty),
248 LayoutId::kTypeError,
249 "Builtin 'ord' expects string of length 1"));
250}
251
252TEST_F(BuiltinsModuleTest, BuiltinOrdWithLongBytesRaisesTypeError) {
253 unsigned char bytes[] = {'A', 'B'};
254 HandleScope scope(thread_);
255 Object too_many_bytes(&scope, runtime_->newBytesWithAll(bytes));
256 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), too_many_bytes),
257 LayoutId::kTypeError,
258 "Builtin 'ord' expects string of length 1"));
259}
260
261TEST_F(BuiltinsModuleTest, BuiltinOrdWithStrSubclass) {
262 ASSERT_FALSE(runFromCStr(runtime_, R"(
263class MyStr(str): pass
264a_str = MyStr("A")
265)")
266 .isError());
267 HandleScope scope(thread_);
268 Object a_str(&scope, mainModuleAt(runtime_, "a_str"));
269 EXPECT_TRUE(isIntEqualsWord(runBuiltin(FUNC(builtins, ord), a_str), 65));
270}
271
272TEST_F(BuiltinsModuleTest, BuiltinOrdSupportNonASCII) {
273 HandleScope scope(thread_);
274 Str two_bytes(&scope, runtime_->newStrFromCStr("\xC3\xA9"));
275 Object two_ord(&scope, runBuiltin(FUNC(builtins, ord), two_bytes));
276 EXPECT_TRUE(isIntEqualsWord(*two_ord, 0xE9));
277
278 Str three_bytes(&scope, runtime_->newStrFromCStr("\xE2\xB3\x80"));
279 Object three_ord(&scope, runBuiltin(FUNC(builtins, ord), three_bytes));
280 EXPECT_TRUE(isIntEqualsWord(*three_ord, 0x2CC0));
281
282 Str four_bytes(&scope, runtime_->newStrFromCStr("\xF0\x9F\x86\x92"));
283 Object four_ord(&scope, runBuiltin(FUNC(builtins, ord), four_bytes));
284 EXPECT_TRUE(isIntEqualsWord(*four_ord, 0x1F192));
285}
286
287TEST_F(BuiltinsModuleTest, BuiltinOrdWithEmptyStrRaisesTypeError) {
288 HandleScope scope(thread_);
289 Object empty(&scope, Str::empty());
290 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), empty),
291 LayoutId::kTypeError,
292 "Builtin 'ord' expects string of length 1"));
293}
294
295TEST_F(BuiltinsModuleTest, BuiltinOrdWithEmptyStrSubclassRaisesTypeError) {
296 ASSERT_FALSE(runFromCStr(runtime_, R"(
297class MyStr(str): pass
298empty = MyStr("")
299)")
300 .isError());
301 HandleScope scope(thread_);
302 Object empty(&scope, mainModuleAt(runtime_, "empty"));
303 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), empty),
304 LayoutId::kTypeError,
305 "Builtin 'ord' expects string of length 1"));
306}
307
308TEST_F(BuiltinsModuleTest, BuiltinOrdStrWithManyCodePointsRaisesTypeError) {
309 HandleScope scope(thread_);
310 Object two_chars(&scope, runtime_->newStrFromCStr("ab"));
311 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), two_chars),
312 LayoutId::kTypeError,
313 "Builtin 'ord' expects string of length 1"));
314}
315
316TEST_F(BuiltinsModuleTest,
317 BuiltinOrdStrSubclassWithManyCodePointsRaiseTypeError) {
318 ASSERT_FALSE(runFromCStr(runtime_, R"(
319class MyStr(str): pass
320two_code_points = MyStr("ab")
321)")
322 .isError());
323 HandleScope scope(thread_);
324 Object two_code_points(&scope, mainModuleAt(runtime_, "two_code_points"));
325 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(builtins, ord), two_code_points),
326 LayoutId::kTypeError,
327 "Builtin 'ord' expects string of length 1"));
328}
329
330TEST_F(BuiltinsModuleTest, BuiltInReprOnUserTypeWithDunderRepr) {
331 ASSERT_FALSE(runFromCStr(runtime_, R"(
332class Foo:
333 def __repr__(self):
334 return "foo"
335
336a = repr(Foo())
337)")
338 .isError());
339 HandleScope scope(thread_);
340 Object a(&scope, mainModuleAt(runtime_, "a"));
341 EXPECT_TRUE(isStrEqualsCStr(*a, "foo"));
342}
343
344TEST_F(BuiltinsModuleTest, BuiltInReprOnClass) {
345 ASSERT_FALSE(runFromCStr(runtime_, "result = repr(int)").isError());
346 HandleScope scope(thread_);
347 Object result(&scope, mainModuleAt(runtime_, "result"));
348 EXPECT_TRUE(isStrEqualsCStr(*result, "<class 'int'>"));
349}
350
351TEST_F(BuiltinsModuleTest, BuiltInAsciiCallsDunderRepr) {
352 ASSERT_FALSE(runFromCStr(runtime_, R"(
353class Foo:
354 def __repr__(self):
355 return "foo"
356
357a = ascii(Foo())
358)")
359 .isError());
360 HandleScope scope(thread_);
361 Object a(&scope, mainModuleAt(runtime_, "a"));
362 EXPECT_TRUE(isStrEqualsCStr(*a, "foo"));
363}
364
365TEST_F(BuiltinsModuleTest, DunderBuildClassWithNonFunctionRaisesTypeError) {
366 HandleScope scope(thread_);
367 Object body(&scope, NoneType::object());
368 Object name(&scope, runtime_->newStrFromCStr("a"));
369 Object metaclass(&scope, Unbound::object());
370 Object bootstrap(&scope, Bool::falseObj());
371 Object bases(&scope, runtime_->emptyTuple());
372 Object kwargs(&scope, runtime_->newDict());
373 EXPECT_TRUE(raisedWithStr(
374 runBuiltin(FUNC(builtins, __build_class__), body, name, metaclass,
375 bootstrap, bases, kwargs),
376 LayoutId::kTypeError, "__build_class__: func must be a function"));
377}
378
379TEST_F(BuiltinsModuleTest, DunderBuildClassWithNonStringRaisesTypeError) {
380 HandleScope scope(thread_);
381 ASSERT_FALSE(runFromCStr(runtime_, "def f(): pass").isError());
382 Object body(&scope, mainModuleAt(runtime_, "f"));
383 Object name(&scope, NoneType::object());
384 Object metaclass(&scope, Unbound::object());
385 Object bootstrap(&scope, Bool::falseObj());
386 Object bases(&scope, runtime_->emptyTuple());
387 Object kwargs(&scope, runtime_->newDict());
388 EXPECT_TRUE(raisedWithStr(
389 runBuiltin(FUNC(builtins, __build_class__), body, name, metaclass,
390 bootstrap, bases, kwargs),
391 LayoutId::kTypeError, "__build_class__: name is not a string"));
392}
393
394TEST_F(BuiltinsModuleTest, DunderBuildClassCallsMetaclass) {
395 HandleScope scope(thread_);
396 ASSERT_FALSE(runFromCStr(runtime_, R"(
397class Meta(type):
398 def __new__(mcls, name, bases, namespace, *args, **kwargs):
399 return (mcls, name, bases, namespace, args, kwargs)
400class C(int, float, metaclass=Meta, hello="world"):
401 x = 42
402)")
403 .isError());
404 Object meta(&scope, mainModuleAt(runtime_, "Meta"));
405 Object c_obj(&scope, mainModuleAt(runtime_, "C"));
406 ASSERT_TRUE(c_obj.isTuple());
407 Tuple c(&scope, *c_obj);
408 ASSERT_EQ(c.length(), 6);
409 EXPECT_EQ(c.at(0), meta);
410 EXPECT_TRUE(isStrEqualsCStr(c.at(1), "C"));
411
412 ASSERT_TRUE(c.at(2).isTuple());
413 Tuple c_bases(&scope, c.at(2));
414 ASSERT_EQ(c_bases.length(), 2);
415 EXPECT_EQ(c_bases.at(0), runtime_->typeAt(LayoutId::kInt));
416 EXPECT_EQ(c_bases.at(1), runtime_->typeAt(LayoutId::kFloat));
417
418 ASSERT_TRUE(c.at(3).isDict());
419 Dict c_namespace(&scope, c.at(3));
420 Str x(&scope, runtime_->newStrFromCStr("x"));
421 EXPECT_EQ(dictIncludes(thread_, c_namespace, x, strHash(thread_, *x)),
422 Bool::trueObj());
423 ASSERT_TRUE(c.at(4).isTuple());
424 EXPECT_EQ(Tuple::cast(c.at(4)).length(), 0);
425 Str hello(&scope, runtime_->newStrFromCStr("hello"));
426 ASSERT_TRUE(c.at(5).isDict());
427 Dict c_kwargs(&scope, c.at(5));
428 EXPECT_EQ(c_kwargs.numItems(), 1);
429 EXPECT_TRUE(isStrEqualsCStr(dictAtByStr(thread_, c_kwargs, hello), "world"));
430}
431
432TEST_F(BuiltinsModuleTest, DunderBuildClassCalculatesMostSpecificMetaclass) {
433 HandleScope scope(thread_);
434 ASSERT_FALSE(runFromCStr(runtime_, R"(
435class Meta(type): pass
436class C1(int, metaclass=Meta): pass
437class C2(C1, metaclass=type): pass
438t1 = type(C1)
439t2 = type(C2)
440)")
441 .isError());
442 Object meta(&scope, mainModuleAt(runtime_, "Meta"));
443 Object t1(&scope, mainModuleAt(runtime_, "t1"));
444 Object t2(&scope, mainModuleAt(runtime_, "t2"));
445 ASSERT_TRUE(t1.isType());
446 ASSERT_TRUE(t2.isType());
447 EXPECT_EQ(t1, meta);
448 EXPECT_EQ(t2, meta);
449}
450
451TEST_F(BuiltinsModuleTest,
452 DunderBuildClassWithIncompatibleMetaclassesRaisesTypeError) {
453 EXPECT_TRUE(raisedWithStr(
454 runFromCStr(runtime_, R"(
455class M1(type): pass
456class M2(type): pass
457class C1(metaclass=M1): pass
458class C2(C1, metaclass=M2): pass
459)"),
460 LayoutId::kTypeError,
461 "metaclass conflict: the metaclass of a derived class must be a "
462 "(non-strict) subclass of the metaclasses of all its bases"));
463}
464
465TEST_F(BuiltinsModuleTest, DunderBuildClassWithMeetMetaclassUsesMeet) {
466 HandleScope scope(thread_);
467 ASSERT_FALSE(runFromCStr(runtime_, R"(
468class M1(type): pass
469class M2(type): pass
470class M3(M1, M2): pass
471class C1(metaclass=M1): pass
472class C2(metaclass=M2): pass
473class C3(C1, C2, metaclass=M3): pass
474t1 = type(C1)
475t2 = type(C2)
476t3 = type(C3)
477)")
478 .isError());
479 Object m1(&scope, mainModuleAt(runtime_, "M1"));
480 Object m2(&scope, mainModuleAt(runtime_, "M2"));
481 Object m3(&scope, mainModuleAt(runtime_, "M3"));
482 Object t1(&scope, mainModuleAt(runtime_, "t1"));
483 Object t2(&scope, mainModuleAt(runtime_, "t2"));
484 Object t3(&scope, mainModuleAt(runtime_, "t3"));
485 ASSERT_TRUE(t1.isType());
486 ASSERT_TRUE(t2.isType());
487 ASSERT_TRUE(t3.isType());
488 EXPECT_EQ(t1, m1);
489 EXPECT_EQ(t2, m2);
490 EXPECT_EQ(t3, m3);
491}
492
493TEST_F(BuiltinsModuleTest, DunderBuildClassPropagatesDunderPrepareError) {
494 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
495class Meta(type):
496 @classmethod
497 def __prepare__(cls, *args, **kwds):
498 raise IndentationError("foo")
499class C(metaclass=Meta):
500 pass
501)"),
502 LayoutId::kIndentationError, "foo"));
503}
504
505TEST_F(BuiltinsModuleTest, DunderBuildClassWithNonDictPrepareRaisesTypeError) {
506 EXPECT_TRUE(
507 raisedWithStr(runFromCStr(runtime_, R"(
508class Meta(type):
509 @classmethod
510 def __prepare__(cls, *args, **kwds):
511 return 42
512class C(metaclass=Meta):
513 pass
514)"),
515 LayoutId::kTypeError,
516 "Meta.__prepare__() must return a mapping, not int"));
517}
518
519TEST_F(BuiltinsModuleTest,
520 DunderBuildClassWithNonTypeMetaclassAndNonDictPrepareRaisesTypeError) {
521 EXPECT_TRUE(raisedWithStr(
522 runFromCStr(runtime_, R"(
523class Meta:
524 def __prepare__(self, *args, **kwds):
525 return 42
526class C(metaclass=Meta()):
527 pass
528)"),
529 LayoutId::kTypeError,
530 "<metaclass>.__prepare__() must return a mapping, not int"));
531}
532
533TEST_F(BuiltinsModuleTest, DunderBuildClassUsesDunderPrepareForClassDict) {
534 HandleScope scope(thread_);
535 ASSERT_FALSE(runFromCStr(runtime_, R"(
536class Meta(type):
537 @classmethod
538 def __prepare__(cls, *args, **kwds):
539 return {"foo": 42}
540class C(metaclass=Meta):
541 pass
542result = C.foo
543)")
544 .isError());
545 Object result(&scope, mainModuleAt(runtime_, "result"));
546 EXPECT_TRUE(isIntEqualsWord(*result, 42));
547}
548
549TEST_F(BuiltinsModuleTest, DunderBuildClassPassesNameBasesAndKwargsToPrepare) {
550 HandleScope scope(thread_);
551 ASSERT_FALSE(runFromCStr(runtime_, R"(
552class Meta(type):
553 def __init__(metacls, name, bases, namespace, **kwargs):
554 pass
555 def __new__(metacls, name, bases, namespace, **kwargs):
556 return super().__new__(metacls, name, bases, namespace)
557 @classmethod
558 def __prepare__(metacls, name, bases, **kwargs):
559 return {"foo": name, "bar": bases[0], "baz": kwargs["answer"]}
560class C(int, metaclass=Meta, answer=42):
561 pass
562name = C.foo
563base = C.bar
564answer = C.baz
565)")
566 .isError());
567 Object name(&scope, mainModuleAt(runtime_, "name"));
568 Object base(&scope, mainModuleAt(runtime_, "base"));
569 Object answer(&scope, mainModuleAt(runtime_, "answer"));
570 EXPECT_TRUE(isStrEqualsCStr(*name, "C"));
571 EXPECT_EQ(base, runtime_->typeAt(LayoutId::kInt));
572 EXPECT_TRUE(isIntEqualsWord(*answer, 42));
573}
574
575TEST_F(BuiltinsModuleTest, DunderBuildClassWithRaisingBodyPropagatesException) {
576 EXPECT_TRUE(raised(runFromCStr(runtime_, R"(
577class C:
578 raise UserWarning()
579)"),
580 LayoutId::kUserWarning));
581}
582
583TEST_F(BuiltinsModuleTest, DunderImportWithBuiltinReturnsModule) {
584 HandleScope scope(thread_);
585 Object name(&scope, runtime_->newStrFromCStr("_io"));
586 Object globals(&scope, NoneType::object());
587 Object locals(&scope, NoneType::object());
588 Object fromlist(&scope, runtime_->emptyTuple());
589 Object level(&scope, runtime_->newInt(0));
590 Object result_obj(&scope, runBuiltin(FUNC(builtins, __import__), name,
591 globals, locals, fromlist, level));
592 ASSERT_TRUE(result_obj.isModule());
593 Module result(&scope, *result_obj);
594 EXPECT_TRUE(isStrEqualsCStr(result.name(), "_io"));
595}
596
597TEST_F(BuiltinsModuleTest, DunderImportWithExtensionModuleReturnsModule) {
598 HandleScope scope(thread_);
599 Object name(&scope, runtime_->newStrFromCStr("errno"));
600 Object globals(&scope, NoneType::object());
601 Object locals(&scope, NoneType::object());
602 Object fromlist(&scope, runtime_->emptyTuple());
603 Object level(&scope, runtime_->newInt(0));
604 Object result_obj(&scope, runBuiltin(FUNC(builtins, __import__), name,
605 globals, locals, fromlist, level));
606 ASSERT_TRUE(result_obj.isModule());
607 Module result(&scope, *result_obj);
608 EXPECT_TRUE(isStrEqualsCStr(result.name(), "errno"));
609}
610
611TEST_F(BuiltinsModuleTest, DunderImportRaisesImportError) {
612 HandleScope scope(thread_);
613 // The minimal implementation should not open files.
614 Object name(&scope, runtime_->newStrFromCStr("antigravity"));
615 Object globals(&scope, NoneType::object());
616 Object locals(&scope, NoneType::object());
617 Object fromlist(&scope, runtime_->emptyTuple());
618 Object level(&scope, runtime_->newInt(0));
619 EXPECT_TRUE(
620 raisedWithStr(runBuiltin(FUNC(builtins, __import__), name, globals,
621 locals, fromlist, level),
622 LayoutId::kImportError,
623 "failed to import antigravity (bootstrap importer)"));
624}
625
626TEST_F(BuiltinsModuleTest, GetAttrFromClassReturnsValue) {
627 const char* src = R"(
628class Foo:
629 bar = 1
630obj = getattr(Foo, 'bar')
631)";
632 HandleScope scope(thread_);
633 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
634 Object obj(&scope, mainModuleAt(runtime_, "obj"));
635 EXPECT_EQ(*obj, SmallInt::fromWord(1));
636}
637
638TEST_F(BuiltinsModuleTest, GetAttrFromInstanceReturnsValue) {
639 const char* src = R"(
640class Foo:
641 bar = 1
642obj = getattr(Foo(), 'bar')
643)";
644 HandleScope scope(thread_);
645 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
646 Object obj(&scope, mainModuleAt(runtime_, "obj"));
647 EXPECT_EQ(*obj, SmallInt::fromWord(1));
648}
649
650TEST_F(BuiltinsModuleTest, GetAttrFromInstanceWithMissingAttrReturnsDefault) {
651 const char* src = R"(
652class Foo: pass
653obj = getattr(Foo(), 'bar', 2)
654)";
655 HandleScope scope(thread_);
656 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
657 Object obj(&scope, mainModuleAt(runtime_, "obj"));
658 EXPECT_EQ(*obj, SmallInt::fromWord(2));
659}
660
661TEST_F(BuiltinsModuleTest, GetAttrWithNonStringAttrRaisesTypeError) {
662 const char* src = R"(
663class Foo: pass
664getattr(Foo(), 1)
665)";
666 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
667 "attribute name must be string, not 'int'"));
668}
669
670TEST_F(BuiltinsModuleTest, GetAttrWithNonStringAttrAndDefaultRaisesTypeError) {
671 const char* src = R"(
672class Foo: pass
673getattr(Foo(), 1, 2)
674)";
675 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
676 "attribute name must be string, not 'int'"));
677}
678
679TEST_F(BuiltinsModuleTest,
680 GetAttrFromClassMissingAttrWithoutDefaultRaisesAttributeError) {
681 const char* src = R"(
682class Foo:
683 bar = 1
684getattr(Foo, 'foo')
685)";
686 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src),
687 LayoutId::kAttributeError,
688 "type object 'Foo' has no attribute 'foo'"));
689}
690
691TEST_F(BuiltinsModuleTest,
692 HashWithObjectWithNotCallableDunderHashRaisesTypeError) {
693 const char* src = R"(
694class C:
695 __hash__ = None
696
697hash(C())
698)";
699 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
700 "unhashable type: 'C'"));
701}
702
703TEST_F(BuiltinsModuleTest, HashWithObjectReturningNonIntRaisesTypeError) {
704 const char* src = R"(
705class C:
706 def __hash__(self): return "10"
707
708hash(C())
709)";
710 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
711 "__hash__ method should return an integer"));
712}
713
714TEST_F(BuiltinsModuleTest, HashWithObjectReturnsObjectDunderHashValue) {
715 ASSERT_FALSE(runFromCStr(runtime_, R"(
716class C:
717 def __hash__(self): return 10
718
719h = hash(C())
720)")
721 .isError());
722 EXPECT_EQ(mainModuleAt(runtime_, "h"), SmallInt::fromWord(10));
723}
724
725TEST_F(BuiltinsModuleTest,
726 HashWithObjectWithModifiedDunderHashReturnsClassDunderHashValue) {
727 ASSERT_FALSE(runFromCStr(runtime_, R"(
728class C:
729 def __hash__(self): return 10
730
731def fake_hash(): return 0
732c = C()
733c.__hash__ = fake_hash
734h = hash(c)
735)")
736 .isError());
737 EXPECT_EQ(mainModuleAt(runtime_, "h"), SmallInt::fromWord(10));
738}
739
740TEST_F(BuiltinsModuleTest, BuiltInSetAttr) {
741 const char* src = R"(
742class Foo:
743 bar = 1
744a = setattr(Foo, 'foo', 2)
745b = Foo.foo
746)";
747 HandleScope scope(thread_);
748 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
749 Object a(&scope, mainModuleAt(runtime_, "a"));
750 Object b(&scope, mainModuleAt(runtime_, "b"));
751 EXPECT_EQ(*a, NoneType::object());
752 EXPECT_EQ(*b, SmallInt::fromWord(2));
753}
754
755TEST_F(BuiltinsModuleTest, BuiltInSetAttrRaisesTypeError) {
756 const char* src = R"(
757class Foo:
758 bar = 1
759a = setattr(Foo, 2, 'foo')
760)";
761 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError,
762 "attribute name must be string, not 'int'"));
763}
764
765TEST_F(BuiltinsModuleTest, ModuleAttrReturnsBuiltinsName) {
766 // TODO(eelizondo): Parameterize test for all builtin types
767 const char* src = R"(
768a = hasattr(object, '__module__')
769b = getattr(object, '__module__')
770c = hasattr(list, '__module__')
771d = getattr(list, '__module__')
772)";
773 HandleScope scope(thread_);
774 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
775
776 Object a(&scope, mainModuleAt(runtime_, "a"));
777 EXPECT_EQ(*a, Bool::trueObj());
778 Object b(&scope, mainModuleAt(runtime_, "b"));
779 ASSERT_TRUE(b.isStr());
780 EXPECT_TRUE(Str::cast(*b).equalsCStr("builtins"));
781
782 Object c(&scope, mainModuleAt(runtime_, "c"));
783 EXPECT_EQ(*c, Bool::trueObj());
784 Object d(&scope, mainModuleAt(runtime_, "d"));
785 ASSERT_TRUE(d.isStr());
786 EXPECT_TRUE(Str::cast(*b).equalsCStr("builtins"));
787}
788
789TEST_F(BuiltinsModuleTest, QualnameAttrReturnsTypeName) {
790 // TODO(eelizondo): Parameterize test for all builtin types
791 const char* src = R"(
792a = hasattr(object, '__qualname__')
793b = getattr(object, '__qualname__')
794c = hasattr(list, '__qualname__')
795d = getattr(list, '__qualname__')
796)";
797 HandleScope scope(thread_);
798 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
799
800 Object a(&scope, mainModuleAt(runtime_, "a"));
801 EXPECT_EQ(*a, Bool::trueObj());
802 Object b(&scope, mainModuleAt(runtime_, "b"));
803 ASSERT_TRUE(b.isStr());
804 EXPECT_TRUE(Str::cast(*b).equalsCStr("object"));
805
806 Object c(&scope, mainModuleAt(runtime_, "c"));
807 EXPECT_EQ(*c, Bool::trueObj());
808 Object d(&scope, mainModuleAt(runtime_, "d"));
809 ASSERT_TRUE(d.isStr());
810 EXPECT_TRUE(Str::cast(*d).equalsCStr("list"));
811}
812
813TEST_F(BuiltinsModuleTest, BuiltinCompile) {
814 HandleScope scope(thread_);
815 ASSERT_FALSE(
816 runFromCStr(
817 runtime_,
818 R"(code = compile("a+b", "<string>", "eval", dont_inherit=True))")
819 .isError());
820 Str filename(&scope, runtime_->newStrFromCStr("<string>"));
821 Code code(&scope, mainModuleAt(runtime_, "code"));
822 ASSERT_TRUE(code.filename().isStr());
823 EXPECT_TRUE(Str::cast(code.filename()).equals(*filename));
824
825 ASSERT_TRUE(code.names().isTuple());
826 Tuple names(&scope, code.names());
827 ASSERT_EQ(names.length(), 2);
828 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("a")));
829 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("b")));
830}
831
832TEST_F(BuiltinsModuleTest, BuiltinCompileBytes) {
833 HandleScope scope(thread_);
834 ASSERT_FALSE(runFromCStr(runtime_, R"(
835data = b'a+b'
836code = compile(data, "<string>", "eval", dont_inherit=True)
837)")
838 .isError());
839 Code code(&scope, mainModuleAt(runtime_, "code"));
840 Object filename(&scope, code.filename());
841 EXPECT_TRUE(isStrEqualsCStr(*filename, "<string>"));
842
843 ASSERT_TRUE(code.names().isTuple());
844 Tuple names(&scope, code.names());
845 ASSERT_EQ(names.length(), 2);
846 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("a")));
847 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("b")));
848}
849
850TEST_F(BuiltinsModuleTest, BuiltinCompileWithBytesSubclass) {
851 HandleScope scope(thread_);
852 ASSERT_FALSE(runFromCStr(runtime_, R"(
853class Foo(bytes): pass
854data = Foo(b"a+b")
855code = compile(data, "<string>", "eval", dont_inherit=True)
856)")
857 .isError());
858 Code code(&scope, mainModuleAt(runtime_, "code"));
859 Object filename(&scope, code.filename());
860 EXPECT_TRUE(isStrEqualsCStr(*filename, "<string>"));
861
862 ASSERT_TRUE(code.names().isTuple());
863 Tuple names(&scope, code.names());
864 ASSERT_EQ(names.length(), 2);
865 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("a")));
866 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("b")));
867}
868
869TEST_F(BuiltinsModuleTest, BuiltinCompileWithStrSubclass) {
870 HandleScope scope(thread_);
871 ASSERT_FALSE(runFromCStr(runtime_, R"(
872class Foo(str): pass
873data = Foo("a+b")
874code = compile(data, "<string>", "eval", dont_inherit=True)
875)")
876 .isError());
877 Code code(&scope, mainModuleAt(runtime_, "code"));
878 Object filename(&scope, code.filename());
879 EXPECT_TRUE(isStrEqualsCStr(*filename, "<string>"));
880
881 ASSERT_TRUE(code.names().isTuple());
882 Tuple names(&scope, code.names());
883 ASSERT_EQ(names.length(), 2);
884 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("a")));
885 ASSERT_TRUE(names.contains(runtime_->newStrFromCStr("b")));
886}
887
888TEST_F(BuiltinsModuleDeathTest, BuiltinCompileRaisesTypeErrorGivenTooFewArgs) {
889 EXPECT_TRUE(
890 raisedWithStr(runFromCStr(runtime_, "compile(1)"), LayoutId::kTypeError,
891 "'compile' takes min 3 positional arguments but 1 given"));
892}
893
894TEST_F(BuiltinsModuleDeathTest, BuiltinCompileRaisesTypeErrorGivenTooManyArgs) {
895 EXPECT_TRUE(
896 raisedWithStr(runFromCStr(runtime_, "compile(1, 2, 3, 4, 5, 6, 7, 8, 9)"),
897 LayoutId::kTypeError,
898 "'compile' takes max 6 positional arguments but 9 given"));
899}
900
901TEST_F(BuiltinsModuleTest, BuiltinCompileRaisesTypeErrorGivenBadMode) {
902 EXPECT_TRUE(raisedWithStr(
903 runFromCStr(runtime_,
904 "compile('hello', 'hello', 'hello', dont_inherit=True)"),
905 LayoutId::kValueError,
906 "compile() mode must be 'exec', 'eval' or 'single'"));
907}
908
909TEST_F(BuiltinsModuleTest, AllOnListWithOnlyTrueReturnsTrue) {
910 ASSERT_FALSE(runFromCStr(runtime_, R"(
911result = all([True, True])
912 )")
913 .isError());
914 HandleScope scope(thread_);
915 Bool result(&scope, mainModuleAt(runtime_, "result"));
916 EXPECT_TRUE(result.value());
917}
918
919TEST_F(BuiltinsModuleTest, AllOnListWithFalseReturnsFalse) {
920 ASSERT_FALSE(runFromCStr(runtime_, R"(
921result = all([True, False, True])
922 )")
923 .isError());
924 HandleScope scope(thread_);
925 Bool result(&scope, mainModuleAt(runtime_, "result"));
926 EXPECT_FALSE(result.value());
927}
928
929TEST_F(BuiltinsModuleTest, AnyOnListWithOnlyFalseReturnsFalse) {
930 ASSERT_FALSE(runFromCStr(runtime_, R"(
931result = any([False, False])
932 )")
933 .isError());
934 HandleScope scope(thread_);
935 Bool result(&scope, mainModuleAt(runtime_, "result"));
936 EXPECT_FALSE(result.value());
937}
938
939TEST_F(BuiltinsModuleTest, AnyOnListWithTrueReturnsTrue) {
940 ASSERT_FALSE(runFromCStr(runtime_, R"(
941result = any([False, True, False])
942 )")
943 .isError());
944 HandleScope scope(thread_);
945 Bool result(&scope, mainModuleAt(runtime_, "result"));
946 EXPECT_TRUE(result.value());
947}
948
949TEST_F(BuiltinsModuleTest, FilterWithNonIterableArgumentRaisesTypeError) {
950 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "filter(None, 1)"),
951 LayoutId::kTypeError,
952 "'int' object is not iterable"));
953}
954
955TEST_F(BuiltinsModuleTest,
956 FilterWithNoneFuncAndIterableReturnsItemsOfTrueBoolValue) {
957 ASSERT_FALSE(runFromCStr(runtime_, R"(
958f = filter(None, [1,0,2,0])
959r0 = f.__next__()
960r1 = f.__next__()
961exhausted = False
962try:
963 f.__next__()
964except StopIteration:
965 exhausted = True
966)")
967 .isError());
968 HandleScope scope(thread_);
969 Object r0(&scope, mainModuleAt(runtime_, "r0"));
970 Object r1(&scope, mainModuleAt(runtime_, "r1"));
971 Object exhausted(&scope, mainModuleAt(runtime_, "exhausted"));
972 EXPECT_TRUE(isIntEqualsWord(*r0, 1));
973 EXPECT_TRUE(isIntEqualsWord(*r1, 2));
974 EXPECT_EQ(*exhausted, Bool::trueObj());
975}
976
977TEST_F(
978 BuiltinsModuleTest,
979 FilterWithFuncReturningBoolAndIterableReturnsItemsEvaluatedToTrueByFunc) {
980 ASSERT_FALSE(runFromCStr(runtime_, R"(
981def even(e): return e % 2 == 0
982
983f = filter(even, [1,2,3,4])
984r0 = f.__next__()
985r1 = f.__next__()
986exhausted = False
987try:
988 f.__next__()
989except StopIteration:
990 exhausted = True
991)")
992 .isError());
993 HandleScope scope(thread_);
994 Object r0(&scope, mainModuleAt(runtime_, "r0"));
995 Object r1(&scope, mainModuleAt(runtime_, "r1"));
996 Object exhausted(&scope, mainModuleAt(runtime_, "exhausted"));
997 EXPECT_TRUE(isIntEqualsWord(*r0, 2));
998 EXPECT_TRUE(isIntEqualsWord(*r1, 4));
999 EXPECT_EQ(*exhausted, Bool::trueObj());
1000}
1001
1002TEST_F(BuiltinsModuleTest, FormatWithNonStrFmtSpecRaisesTypeError) {
1003 EXPECT_TRUE(
1004 raised(runFromCStr(runtime_, "format('hi', 1)"), LayoutId::kTypeError));
1005}
1006
1007TEST_F(BuiltinsModuleTest, FormatCallsDunderFormat) {
1008 ASSERT_FALSE(runFromCStr(runtime_, R"(
1009class C:
1010 def __format__(self, fmt_spec):
1011 return "foobar"
1012result = format(C(), 'hi')
1013)")
1014 .isError());
1015 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "foobar"));
1016}
1017
1018TEST_F(BuiltinsModuleTest, FormatRaisesWhenDunderFormatReturnsNonStr) {
1019 ASSERT_FALSE(runFromCStr(runtime_, R"(
1020class C:
1021 def __format__(self, fmt_spec):
1022 return 1
1023)")
1024 .isError());
1025 EXPECT_TRUE(
1026 raised(runFromCStr(runtime_, "format(C(), 'hi')"), LayoutId::kTypeError));
1027}
1028
1029TEST_F(BuiltinsModuleTest, IterWithIterableCallsDunderIter) {
1030 ASSERT_FALSE(runFromCStr(runtime_, R"(
1031l = list(iter([1, 2, 3]))
1032)")
1033 .isError());
1034 HandleScope scope(thread_);
1035 Object l(&scope, mainModuleAt(runtime_, "l"));
1036 EXPECT_PYLIST_EQ(l, {1, 2, 3});
1037}
1038
1039TEST_F(BuiltinsModuleTest, IterWithNonIterableRaisesTypeError) {
1040 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1041iter(None)
1042)"),
1043 LayoutId::kTypeError,
1044 "'NoneType' object is not iterable"));
1045}
1046
1047TEST_F(BuiltinsModuleTest, IterWithRaisingDunderIterPropagatesException) {
1048 EXPECT_TRUE(raised(runFromCStr(runtime_, R"(
1049class C:
1050 def __iter__(self):
1051 raise UserWarning()
1052iter(C())
1053)"),
1054 LayoutId::kUserWarning));
1055}
1056
1057TEST_F(BuiltinsModuleTest, NextWithoutIteratorRaisesTypeError) {
1058 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1059class C:
1060 pass
1061next(C())
1062)"),
1063 LayoutId::kTypeError,
1064 "'C' object is not iterable"));
1065}
1066
1067TEST_F(BuiltinsModuleTest, NextWithIteratorFetchesNextItem) {
1068 ASSERT_FALSE(runFromCStr(runtime_, R"(
1069class C:
1070 def __iter__(self):
1071 self.a = 1
1072 return self
1073
1074 def __next__(self):
1075 x = self.a
1076 self.a += 1
1077 return x
1078
1079itr = iter(C())
1080c = next(itr)
1081d = next(itr)
1082)")
1083 .isError());
1084 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "c"), 1));
1085 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "d"), 2));
1086}
1087
1088TEST_F(BuiltinsModuleTest, NextWithIteratorAndDefaultFetchesNextItem) {
1089 ASSERT_FALSE(runFromCStr(runtime_, R"(
1090class C:
1091 def __iter__(self):
1092 self.a = 1
1093 return self
1094
1095 def __next__(self):
1096 x = self.a
1097 self.a += 1
1098 return x
1099
1100itr = iter(C())
1101c = next(itr, 0)
1102d = next(itr, 0)
1103)")
1104 .isError());
1105 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "c"), 1));
1106 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "d"), 2));
1107}
1108
1109TEST_F(BuiltinsModuleTest, NextWithIteratorRaisesStopIteration) {
1110 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1111class C:
1112 def __iter__(self):
1113 return self
1114
1115 def __next__(self):
1116 raise StopIteration('stopit')
1117
1118itr = iter(C())
1119next(itr)
1120)"),
1121 LayoutId::kStopIteration, "stopit"));
1122}
1123
1124TEST_F(BuiltinsModuleTest, NextWithIteratorAndDefaultReturnsDefault) {
1125 ASSERT_FALSE(runFromCStr(runtime_, R"(
1126class C:
1127 def __iter__(self):
1128 return self
1129
1130 def __next__(self):
1131 raise StopIteration('stopit')
1132itr = iter(C())
1133c = next(itr, None)
1134)")
1135 .isError());
1136 EXPECT_TRUE(mainModuleAt(runtime_, "c").isNoneType());
1137}
1138
1139TEST_F(BuiltinsModuleTest, SortedReturnsSortedList) {
1140 ASSERT_FALSE(runFromCStr(runtime_, R"(
1141unsorted = [5, 7, 8, 6]
1142result = sorted(unsorted)
1143)")
1144 .isError());
1145
1146 HandleScope scope(thread_);
1147 Object unsorted_obj(&scope, mainModuleAt(runtime_, "unsorted"));
1148 ASSERT_TRUE(unsorted_obj.isList());
1149 Object result_obj(&scope, mainModuleAt(runtime_, "result"));
1150 ASSERT_TRUE(result_obj.isList());
1151 EXPECT_NE(*unsorted_obj, *result_obj);
1152
1153 List unsorted(&scope, *unsorted_obj);
1154 ASSERT_EQ(unsorted.numItems(), 4);
1155 EXPECT_EQ(unsorted.at(0), SmallInt::fromWord(5));
1156 EXPECT_EQ(unsorted.at(1), SmallInt::fromWord(7));
1157 EXPECT_EQ(unsorted.at(2), SmallInt::fromWord(8));
1158 EXPECT_EQ(unsorted.at(3), SmallInt::fromWord(6));
1159
1160 List result(&scope, *result_obj);
1161 ASSERT_EQ(result.numItems(), 4);
1162 EXPECT_EQ(result.at(0), SmallInt::fromWord(5));
1163 EXPECT_EQ(result.at(1), SmallInt::fromWord(6));
1164 EXPECT_EQ(result.at(2), SmallInt::fromWord(7));
1165 EXPECT_EQ(result.at(3), SmallInt::fromWord(8));
1166}
1167
1168TEST_F(BuiltinsModuleTest, SortedWithReverseReturnsReverseSortedList) {
1169 ASSERT_FALSE(runFromCStr(runtime_, R"(
1170unsorted = [1, 2, 3, 4]
1171result = sorted(unsorted, reverse=True)
1172)")
1173 .isError());
1174
1175 HandleScope scope(thread_);
1176 Object unsorted_obj(&scope, mainModuleAt(runtime_, "unsorted"));
1177 ASSERT_TRUE(unsorted_obj.isList());
1178 Object result_obj(&scope, mainModuleAt(runtime_, "result"));
1179 ASSERT_TRUE(result_obj.isList());
1180 EXPECT_NE(*unsorted_obj, *result_obj);
1181
1182 List unsorted(&scope, *unsorted_obj);
1183 ASSERT_EQ(unsorted.numItems(), 4);
1184 EXPECT_EQ(unsorted.at(0), SmallInt::fromWord(1));
1185 EXPECT_EQ(unsorted.at(1), SmallInt::fromWord(2));
1186 EXPECT_EQ(unsorted.at(2), SmallInt::fromWord(3));
1187 EXPECT_EQ(unsorted.at(3), SmallInt::fromWord(4));
1188
1189 List result(&scope, *result_obj);
1190 ASSERT_EQ(result.numItems(), 4);
1191 EXPECT_EQ(result.at(0), SmallInt::fromWord(4));
1192 EXPECT_EQ(result.at(1), SmallInt::fromWord(3));
1193 EXPECT_EQ(result.at(2), SmallInt::fromWord(2));
1194 EXPECT_EQ(result.at(3), SmallInt::fromWord(1));
1195}
1196
1197TEST_F(BuiltinsModuleTest, MaxWithEmptyIterableRaisesValueError) {
1198 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "max([])"),
1199 LayoutId::kValueError,
1200 "max() arg is an empty sequence"));
1201}
1202
1203TEST_F(BuiltinsModuleTest, MaxWithMultipleArgsReturnsMaximum) {
1204 ASSERT_FALSE(runFromCStr(runtime_, "result = max(1, 3, 5, 2, -1)").isError());
1205 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 5));
1206}
1207
1208TEST_F(BuiltinsModuleTest, MaxWithNoArgsRaisesTypeError) {
1209 EXPECT_TRUE(
1210 raisedWithStr(runFromCStr(runtime_, "max()"), LayoutId::kTypeError,
1211 "'max' takes min 1 positional arguments but 0 given"));
1212}
1213
1214TEST_F(BuiltinsModuleTest, MaxWithIterableReturnsMaximum) {
1215 ASSERT_FALSE(
1216 runFromCStr(runtime_, "result = max((1, 3, 5, 2, -1))").isError());
1217 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 5));
1218}
1219
1220TEST_F(BuiltinsModuleTest, MaxWithEmptyIterableAndDefaultReturnsDefault) {
1221 ASSERT_FALSE(runFromCStr(runtime_, "result = max([], default=42)").isError());
1222 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 42));
1223}
1224
1225TEST_F(BuiltinsModuleTest, MaxWithKeyOrdersByKeyFunction) {
1226 ASSERT_FALSE(runFromCStr(runtime_, R"(
1227result = max((1, 2, 3), key=lambda x: -x)
1228)")
1229 .isError());
1230 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 1));
1231}
1232
1233TEST_F(BuiltinsModuleTest, MaxWithEmptyIterableAndKeyAndDefaultReturnsDefault) {
1234 ASSERT_FALSE(runFromCStr(runtime_, R"(
1235result = max((), key=lambda x: x, default='empty')
1236)")
1237 .isError());
1238 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "empty"));
1239}
1240
1241TEST_F(BuiltinsModuleTest, MaxWithMultipleArgsAndDefaultRaisesTypeError) {
1242 EXPECT_TRUE(raisedWithStr(
1243 runFromCStr(runtime_, "max(1, 2, default=0)"), LayoutId::kTypeError,
1244 "Cannot specify a default for max() with multiple positional arguments"));
1245}
1246
1247TEST_F(BuiltinsModuleTest, MaxWithKeyReturnsFirstOccuranceOfEqualValues) {
1248 ASSERT_FALSE(runFromCStr(runtime_, R"(
1249class A:
1250 pass
1251
1252first = A()
1253second = A()
1254result = max(first, second, key=lambda x: 1) is first
1255)")
1256 .isError());
1257 EXPECT_EQ(mainModuleAt(runtime_, "result"), Bool::trueObj());
1258}
1259
1260TEST_F(BuiltinsModuleTest, MaxWithoutKeyReturnsFirstOccuranceOfEqualValues) {
1261 ASSERT_FALSE(runFromCStr(runtime_, R"(
1262class A():
1263 def __gt__(self, _):
1264 return False
1265
1266first = A()
1267second = A()
1268result = max(first, second) is first
1269)")
1270 .isError());
1271 EXPECT_EQ(mainModuleAt(runtime_, "result"), Bool::trueObj());
1272}
1273
1274TEST_F(BuiltinsModuleTest, MinWithEmptyIterableRaisesValueError) {
1275 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "min([])"),
1276 LayoutId::kValueError,
1277 "min() arg is an empty sequence"));
1278}
1279
1280TEST_F(BuiltinsModuleTest, MinWithMultipleArgsReturnsMinimum) {
1281 ASSERT_FALSE(runFromCStr(runtime_, "result = min(4, 3, 1, 2, 5)").isError());
1282 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 1));
1283}
1284
1285TEST_F(BuiltinsModuleTest, MinWithNoArgsRaisesTypeError) {
1286 EXPECT_TRUE(
1287 raisedWithStr(runFromCStr(runtime_, "min()"), LayoutId::kTypeError,
1288 "'min' takes min 1 positional arguments but 0 given"));
1289}
1290
1291TEST_F(BuiltinsModuleTest, MinWithIterableReturnsMinimum) {
1292 ASSERT_FALSE(
1293 runFromCStr(runtime_, "result = min((4, 3, 1, 2, 5))").isError());
1294 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 1));
1295}
1296
1297TEST_F(BuiltinsModuleTest, MinWithEmptyIterableAndDefaultReturnsDefault) {
1298 ASSERT_FALSE(runFromCStr(runtime_, "result = min([], default=42)").isError());
1299 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 42));
1300}
1301
1302TEST_F(BuiltinsModuleTest, MinWithKeyOrdersByKeyFunction) {
1303 ASSERT_FALSE(runFromCStr(runtime_, R"(
1304result = min((1, 2, 3), key=lambda x: -x)
1305)")
1306 .isError());
1307 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 3));
1308}
1309
1310TEST_F(BuiltinsModuleTest, MinWithEmptyIterableAndKeyAndDefaultReturnsDefault) {
1311 ASSERT_FALSE(runFromCStr(runtime_, R"(
1312result = min((), key=lambda x: x, default='empty')
1313)")
1314 .isError());
1315 EXPECT_TRUE(isStrEqualsCStr(mainModuleAt(runtime_, "result"), "empty"));
1316}
1317
1318TEST_F(BuiltinsModuleTest, MinWithMultipleArgsAndDefaultRaisesTypeError) {
1319 EXPECT_TRUE(raisedWithStr(
1320 runFromCStr(runtime_, "min(1, 2, default=0)"), LayoutId::kTypeError,
1321 "Cannot specify a default for min() with multiple positional arguments"));
1322}
1323
1324TEST_F(BuiltinsModuleTest, MinReturnsFirstOccuranceOfEqualValues) {
1325 ASSERT_FALSE(runFromCStr(runtime_, R"(
1326class A:
1327 pass
1328
1329first = A()
1330second = A()
1331result = min(first, second, key=lambda x: 1) is first
1332)")
1333 .isError());
1334 EXPECT_EQ(mainModuleAt(runtime_, "result"), Bool::trueObj());
1335}
1336
1337TEST_F(BuiltinsModuleTest, MinWithoutKeyReturnsFirstOccuranceOfEqualValues) {
1338 ASSERT_FALSE(runFromCStr(runtime_, R"(
1339class A():
1340 def __lt__(self, _):
1341 return False
1342
1343first = A()
1344second = A()
1345result = min(first, second) is first
1346)")
1347 .isError());
1348 EXPECT_EQ(mainModuleAt(runtime_, "result"), Bool::trueObj());
1349}
1350
1351TEST_F(BuiltinsModuleTest, MapWithNonIterableArgumentRaisesTypeError) {
1352 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "map(1,1)"),
1353 LayoutId::kTypeError,
1354 "'int' object is not iterable"));
1355}
1356
1357TEST_F(BuiltinsModuleTest,
1358 MapWithIterableDunderNextReturnsFuncAppliedElementsSequentially) {
1359 ASSERT_FALSE(runFromCStr(runtime_, R"(
1360def inc(e):
1361 return e + 1
1362
1363m = map(inc, [1,2])
1364r0 = m.__next__()
1365r1 = m.__next__()
1366)")
1367 .isError());
1368 EXPECT_EQ(mainModuleAt(runtime_, "r0"), SmallInt::fromWord(2));
1369 EXPECT_EQ(mainModuleAt(runtime_, "r1"), SmallInt::fromWord(3));
1370}
1371
1372TEST_F(
1373 BuiltinsModuleTest,
1374 MapWithMultipleIterablesDunderNextReturnsFuncAppliedElementsSequentially) {
1375 ASSERT_FALSE(runFromCStr(runtime_, R"(
1376def inc(e0, e1):
1377 return e0 + e1
1378
1379m = map(inc, [1,2], [100,200])
1380r0 = m.__next__()
1381r1 = m.__next__()
1382)")
1383 .isError());
1384 EXPECT_EQ(mainModuleAt(runtime_, "r0"), SmallInt::fromWord(101));
1385 EXPECT_EQ(mainModuleAt(runtime_, "r1"), SmallInt::fromWord(202));
1386}
1387
1388TEST_F(BuiltinsModuleTest, MapDunderNextFinishesByRaisingStopIteration) {
1389 ASSERT_FALSE(runFromCStr(runtime_, R"(
1390def inc(e):
1391 return e + 1
1392
1393m = map(inc, [1,2])
1394m.__next__()
1395m.__next__()
1396exc_raised = False
1397try:
1398 m.__next__()
1399except StopIteration:
1400 exc_raised = True
1401)")
1402 .isError());
1403 EXPECT_EQ(mainModuleAt(runtime_, "exc_raised"), Bool::trueObj());
1404}
1405
1406TEST_F(
1407 BuiltinsModuleTest,
1408 MapWithMultipleIterablesDunderNextFinishesByRaisingStopIterationOnShorterOne) {
1409 ASSERT_FALSE(runFromCStr(runtime_, R"(
1410def inc(e0, e1):
1411 return e0, e1
1412
1413m = map(inc, [1,2], [100])
1414m.__next__()
1415exc_raised = False
1416try:
1417 m.__next__()
1418except StopIteration:
1419 exc_raised = True
1420)")
1421 .isError());
1422 EXPECT_EQ(mainModuleAt(runtime_, "exc_raised"), Bool::trueObj());
1423}
1424
1425TEST_F(BuiltinsModuleTest, EnumerateWithNonIterableRaisesTypeError) {
1426 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "enumerate(1.0)"),
1427 LayoutId::kTypeError,
1428 "'float' object is not iterable"));
1429}
1430
1431TEST_F(BuiltinsModuleTest, EnumerateReturnsEnumeratedTuples) {
1432 ASSERT_FALSE(runFromCStr(runtime_, R"(
1433e = enumerate([7, 3])
1434res1 = e.__next__()
1435res2 = e.__next__()
1436exhausted = False
1437try:
1438 e.__next__()
1439except StopIteration:
1440 exhausted = True
1441)")
1442 .isError());
1443 HandleScope scope(thread_);
1444 Object res1(&scope, mainModuleAt(runtime_, "res1"));
1445 ASSERT_TRUE(res1.isTuple());
1446 EXPECT_EQ(Tuple::cast(*res1).at(0), SmallInt::fromWord(0));
1447 EXPECT_EQ(Tuple::cast(*res1).at(1), SmallInt::fromWord(7));
1448 Object res2(&scope, mainModuleAt(runtime_, "res2"));
1449 ASSERT_TRUE(res2.isTuple());
1450 EXPECT_EQ(Tuple::cast(*res2).at(0), SmallInt::fromWord(1));
1451 EXPECT_EQ(Tuple::cast(*res2).at(1), SmallInt::fromWord(3));
1452 EXPECT_EQ(mainModuleAt(runtime_, "exhausted"), Bool::trueObj());
1453}
1454
1455TEST_F(BuiltinsModuleTest, AbsReturnsAbsoluteValue) {
1456 ASSERT_FALSE(runFromCStr(runtime_, R"(
1457res1 = abs(10)
1458res2 = abs(-10)
1459)")
1460 .isError());
1461
1462 HandleScope scope(thread_);
1463 Object res1(&scope, mainModuleAt(runtime_, "res1"));
1464 EXPECT_TRUE(isIntEqualsWord(*res1, 10));
1465 Object res2(&scope, mainModuleAt(runtime_, "res2"));
1466 EXPECT_TRUE(isIntEqualsWord(*res2, 10));
1467}
1468
1469TEST_F(BuiltinsModuleTest, AbsWithoutDunderAbsRaisesTypeError) {
1470 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1471class Foo(): pass
1472res1 = abs(Foo())
1473)"),
1474 LayoutId::kTypeError,
1475 "bad operand type for abs(): 'Foo'"));
1476}
1477
1478} // namespace testing
1479} // namespace py