this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "list-builtins.h"
3
4#include "gtest/gtest.h"
5
6#include "builtins-module.h"
7#include "builtins.h"
8#include "objects.h"
9#include "runtime.h"
10#include "test-utils.h"
11
12namespace py {
13namespace testing {
14
15using ListBuiltinsTest = RuntimeFixture;
16using ListIteratorBuiltinsTest = RuntimeFixture;
17
18TEST_F(ListBuiltinsTest, CopyWithListReturnsNewInstance) {
19 ASSERT_FALSE(runFromCStr(runtime_, R"(
20l = [1, 2, 3]
21result = list.copy(l)
22)")
23 .isError());
24 HandleScope scope(thread_);
25 Object list(&scope, mainModuleAt(runtime_, "l"));
26 EXPECT_TRUE(list.isList());
27 Object result_obj(&scope, mainModuleAt(runtime_, "result"));
28 EXPECT_TRUE(result_obj.isList());
29 List result(&scope, *result_obj);
30 EXPECT_NE(*list, *result);
31 EXPECT_EQ(result.numItems(), 3);
32}
33
34TEST_F(ListBuiltinsTest, DunderEqReturnsTrue) {
35 ASSERT_FALSE(runFromCStr(runtime_, R"(
36result = list.__eq__([1, 2, 3], [1, 2, 3])
37)")
38 .isError());
39 EXPECT_EQ(mainModuleAt(runtime_, "result"), RawBool::trueObj());
40}
41
42TEST_F(ListBuiltinsTest, DunderEqWithSameListReturnsTrue) {
43 ASSERT_FALSE(runFromCStr(runtime_, R"(
44class Foo:
45 def __eq__(self, other):
46 return False
47a = [1, 2, 3]
48result = list.__eq__(a, a)
49)")
50 .isError());
51 EXPECT_EQ(mainModuleAt(runtime_, "result"), RawBool::trueObj());
52}
53
54TEST_F(ListBuiltinsTest, DunderEqWithSameIdentityElementsReturnsTrue) {
55 ASSERT_FALSE(runFromCStr(runtime_, R"(
56nan = float("nan")
57result = list.__eq__([nan], [nan])
58)")
59 .isError());
60 EXPECT_EQ(mainModuleAt(runtime_, "result"), RawBool::trueObj());
61}
62
63TEST_F(ListBuiltinsTest, DunderEqWithEqualElementsReturnsTrue) {
64 ASSERT_FALSE(runFromCStr(runtime_, R"(
65class Foo:
66 def __init__(self, value):
67 self.value = value
68 def __eq__(self, other):
69 return type(self.value).__eq__(self.value, other.value)
70a = Foo(1)
71b = Foo(1)
72result = list.__eq__([a], [b])
73)")
74 .isError());
75 EXPECT_EQ(mainModuleAt(runtime_, "result"), RawBool::trueObj());
76}
77
78TEST_F(ListBuiltinsTest, DunderEqWithDifferentSizeReturnsFalse) {
79 ASSERT_FALSE(runFromCStr(runtime_, R"(
80result = list.__eq__([1, 2, 3], [1, 2])
81)")
82 .isError());
83 EXPECT_EQ(mainModuleAt(runtime_, "result"), RawBool::falseObj());
84}
85
86TEST_F(ListBuiltinsTest, DunderEqWithDifferentValuesReturnsFalse) {
87 ASSERT_FALSE(runFromCStr(runtime_, R"(
88result = list.__eq__([1, 2, 3], [1, 2, 4])
89)")
90 .isError());
91 EXPECT_EQ(mainModuleAt(runtime_, "result"), RawBool::falseObj());
92}
93
94TEST_F(ListBuiltinsTest, DunderEqWithNonListRhsReturnsNotImplemented) {
95 ASSERT_FALSE(runFromCStr(runtime_, R"(
96result = list.__eq__([1, 2, 3], (1, 2, 3));
97)")
98 .isError());
99 EXPECT_TRUE(mainModuleAt(runtime_, "result").isNotImplementedType());
100}
101
102TEST_F(ListBuiltinsTest, DunderInitFromList) {
103 ASSERT_FALSE(runFromCStr(runtime_, R"(
104a = list([1, 2])
105)")
106 .isError());
107 HandleScope scope(thread_);
108 List a(&scope, mainModuleAt(runtime_, "a"));
109 ASSERT_EQ(a.numItems(), 2);
110 EXPECT_TRUE(isIntEqualsWord(a.at(0), 1));
111 EXPECT_TRUE(isIntEqualsWord(a.at(1), 2));
112}
113
114TEST_F(ListBuiltinsTest, NewListIsNotASingleton) {
115 ASSERT_FALSE(runFromCStr(runtime_, R"(
116a = list() is not list()
117b = list([1, 2]) is not list([1, 2])
118)")
119 .isError());
120 HandleScope scope(thread_);
121 Bool a(&scope, mainModuleAt(runtime_, "a"));
122 Bool b(&scope, mainModuleAt(runtime_, "b"));
123 EXPECT_TRUE(a.value());
124 EXPECT_TRUE(b.value());
125}
126
127TEST_F(ListBuiltinsTest, AddToNonEmptyList) {
128 HandleScope scope(thread_);
129
130 ASSERT_FALSE(runFromCStr(runtime_, R"(
131a = [1, 2]
132b = [3, 4, 5]
133c = a + b
134)")
135 .isError());
136 Object c(&scope, mainModuleAt(runtime_, "c"));
137 ASSERT_TRUE(c.isList());
138 List list(&scope, List::cast(*c));
139 EXPECT_TRUE(isIntEqualsWord(list.at(0), 1));
140 EXPECT_TRUE(isIntEqualsWord(list.at(1), 2));
141 EXPECT_TRUE(isIntEqualsWord(list.at(2), 3));
142 EXPECT_TRUE(isIntEqualsWord(list.at(3), 4));
143 EXPECT_TRUE(isIntEqualsWord(list.at(4), 5));
144}
145
146TEST_F(ListBuiltinsTest, AddToEmptyList) {
147 HandleScope scope(thread_);
148
149 ASSERT_FALSE(runFromCStr(runtime_, R"(
150a = []
151b = [1, 2, 3]
152c = a + b
153)")
154 .isError());
155 Object c(&scope, mainModuleAt(runtime_, "c"));
156 ASSERT_TRUE(c.isList());
157 List list(&scope, List::cast(*c));
158 EXPECT_TRUE(isIntEqualsWord(list.at(0), 1));
159 EXPECT_TRUE(isIntEqualsWord(list.at(1), 2));
160 EXPECT_TRUE(isIntEqualsWord(list.at(2), 3));
161}
162
163TEST_F(ListBuiltinsTest, AddWithListSubclassReturnsList) {
164 HandleScope scope(thread_);
165 ASSERT_FALSE(runFromCStr(runtime_, R"(
166class C(list):
167 pass
168a = []
169b = C([1, 2, 3])
170c = a + b
171)")
172 .isError());
173 Object c(&scope, mainModuleAt(runtime_, "c"));
174 EXPECT_PYLIST_EQ(c, {1, 2, 3});
175}
176
177TEST_F(ListBuiltinsTest, AddListToTupleRaisesTypeError) {
178 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
179a = [1, 2, 3]
180b = (4, 5, 6)
181c = a + b
182)"),
183 LayoutId::kTypeError,
184 "can only concatenate list to list"));
185}
186
187TEST_F(ListBuiltinsTest, DunderContainsWithContainedElementReturnsTrue) {
188 HandleScope scope(thread_);
189 Int value0(&scope, runtime_->newInt(1));
190 Bool value1(&scope, RawBool::falseObj());
191 Str value2(&scope, runtime_->newStrFromCStr("hello"));
192 List list(&scope, runtime_->newList());
193 runtime_->listAdd(thread_, list, value0);
194 runtime_->listAdd(thread_, list, value1);
195 runtime_->listAdd(thread_, list, value2);
196 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value0),
197 RawBool::trueObj());
198 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value1),
199 RawBool::trueObj());
200 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value2),
201 RawBool::trueObj());
202}
203
204TEST_F(ListBuiltinsTest, DunderContainsWithUncontainedElementReturnsFalse) {
205 HandleScope scope(thread_);
206 Int value0(&scope, runtime_->newInt(7));
207 NoneType value1(&scope, RawNoneType::object());
208 List list(&scope, runtime_->newList());
209 runtime_->listAdd(thread_, list, value0);
210 runtime_->listAdd(thread_, list, value1);
211 Int value2(&scope, runtime_->newInt(42));
212 Bool value3(&scope, RawBool::trueObj());
213 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value2),
214 RawBool::falseObj());
215 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value3),
216 RawBool::falseObj());
217}
218
219TEST_F(ListBuiltinsTest, DunderContainsWithIdenticalObjectReturnsTrue) {
220 HandleScope scope(thread_);
221 ASSERT_FALSE(runFromCStr(runtime_, R"(
222class Foo:
223 def __eq__(self, other):
224 return False
225value = Foo()
226list = [value]
227)")
228 .isError());
229 Object value(&scope, mainModuleAt(runtime_, "value"));
230 List list(&scope, mainModuleAt(runtime_, "list"));
231 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value),
232 RawBool::trueObj());
233}
234
235TEST_F(ListBuiltinsTest,
236 DunderContainsWithNonIdenticalEqualKeyObjectReturnsTrue) {
237 HandleScope scope(thread_);
238 ASSERT_FALSE(runFromCStr(runtime_, R"(
239class Foo:
240 def __eq__(self, other):
241 return True
242value = Foo()
243list = [None]
244)")
245 .isError());
246 Object value(&scope, mainModuleAt(runtime_, "value"));
247 List list(&scope, mainModuleAt(runtime_, "list"));
248 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value),
249 RawBool::trueObj());
250}
251
252TEST_F(ListBuiltinsTest,
253 DunderContainsWithNonIdenticalEqualListObjectReturnsFalse) {
254 HandleScope scope(thread_);
255 ASSERT_FALSE(runFromCStr(runtime_, R"(
256class Foo:
257 def __eq__(self, other):
258 return True
259class Bar:
260 def __eq__(self, other):
261 return False
262value0 = Foo()
263value1 = Bar()
264list = [value0]
265)")
266 .isError());
267 Object value1(&scope, mainModuleAt(runtime_, "value1"));
268 List list(&scope, mainModuleAt(runtime_, "list"));
269 EXPECT_EQ(runBuiltin(METH(list, __contains__), list, value1),
270 RawBool::falseObj());
271}
272
273TEST_F(ListBuiltinsTest, DunderContainsWithRaisingEqPropagatesException) {
274 HandleScope scope(thread_);
275 ASSERT_FALSE(runFromCStr(runtime_, R"(
276class Foo:
277 def __eq__(self, other):
278 raise UserWarning("")
279value = Foo()
280list = [None]
281)")
282 .isError());
283 Object value(&scope, mainModuleAt(runtime_, "value"));
284 List list(&scope, mainModuleAt(runtime_, "list"));
285 Object result(&scope, runBuiltin(METH(list, __contains__), list, value));
286 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning));
287}
288
289TEST_F(ListBuiltinsTest,
290 DunderContainsWithRaisingDunderBoolPropagatesException) {
291 HandleScope scope(thread_);
292 ASSERT_FALSE(runFromCStr(runtime_, R"(
293class Foo:
294 def __bool__(self):
295 raise UserWarning("")
296class Bar:
297 def __eq__(self, other):
298 return Foo()
299value = Bar()
300list = [None]
301)")
302 .isError());
303 Object value(&scope, mainModuleAt(runtime_, "value"));
304 List list(&scope, mainModuleAt(runtime_, "list"));
305 EXPECT_TRUE(raised(runBuiltin(METH(list, __contains__), list, value),
306 LayoutId::kUserWarning));
307}
308
309TEST_F(ListBuiltinsTest, DunderContainsWithNonListSelfRaisesTypeError) {
310 HandleScope scope(thread_);
311 Int i(&scope, SmallInt::fromWord(3));
312 Object result(&scope, runBuiltin(METH(list, __contains__), i, i));
313 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
314}
315
316TEST_F(ListBuiltinsTest, ListInsertWithMissingArgumentsRaisesTypeError) {
317 EXPECT_TRUE(raisedWithStr(
318 runFromCStr(runtime_, "[1, 2].insert()"), LayoutId::kTypeError,
319 "'list.insert' takes min 3 positional arguments but 1 given"));
320}
321
322TEST_F(ListBuiltinsTest, ListInsertWithNonIntIndexRaisesTypeError) {
323 EXPECT_TRUE(raisedWithStr(
324 runFromCStr(runtime_, "[1, 2].insert({}, 3)"), LayoutId::kTypeError,
325 "'dict' object cannot be interpreted as an integer"));
326}
327
328TEST_F(ListBuiltinsTest, ListInsertWithLargeIntIndexRaisesTypeError) {
329 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "[1, 2].insert(2 ** 63, 1)"),
330 LayoutId::kOverflowError,
331 "Python int too large to convert to C ssize_t"));
332}
333
334TEST_F(ListBuiltinsTest, ListInsertWithBoolIndexInsertsAtInt) {
335 HandleScope scope(thread_);
336 List self(&scope, runtime_->newList());
337 Object value(&scope, SmallInt::fromWord(3));
338 runtime_->listAdd(thread_, self, value);
339 runtime_->listAdd(thread_, self, value);
340 Object fals(&scope, Bool::falseObj());
341 Object tru(&scope, Bool::trueObj());
342 Object result(&scope, runBuiltin(METH(list, insert), self, tru, tru));
343 EXPECT_EQ(result, NoneType::object());
344 result = runBuiltin(METH(list, insert), self, fals, fals);
345 EXPECT_EQ(result, NoneType::object());
346 ASSERT_EQ(self.numItems(), 4);
347 EXPECT_EQ(self.at(0), fals);
348 EXPECT_EQ(self.at(1), value);
349 EXPECT_EQ(self.at(2), tru);
350 EXPECT_EQ(self.at(3), value);
351}
352
353TEST_F(ListBuiltinsTest, ListInsertWithIntSubclassInsertsAtInt) {
354 ASSERT_FALSE(runFromCStr(runtime_, R"(
355class N(int):
356 pass
357a = [0, 0, 0, 0, 0]
358b = N(3)
359)")
360 .isError());
361 HandleScope scope(thread_);
362 List self(&scope, mainModuleAt(runtime_, "a"));
363 Object index(&scope, mainModuleAt(runtime_, "b"));
364 Object value(&scope, SmallInt::fromWord(1));
365 Object result(&scope, runBuiltin(METH(list, insert), self, index, value));
366 EXPECT_EQ(result, NoneType::object());
367 EXPECT_EQ(self.numItems(), 6);
368 EXPECT_EQ(self.at(3), value);
369}
370
371TEST_F(ListBuiltinsTest, ListRemove) {
372 ASSERT_FALSE(runFromCStr(runtime_, R"(
373a = [5, 4, 3, 2, 1]
374a.remove(2)
375a.remove(5)
376)")
377 .isError());
378 HandleScope scope(thread_);
379 Object a(&scope, mainModuleAt(runtime_, "a"));
380 EXPECT_PYLIST_EQ(a, {4, 3, 1});
381}
382
383TEST_F(ListBuiltinsTest, ListRemoveWithDuplicateItemsRemovesFirstMatchingItem) {
384 HandleScope scope(thread_);
385 Int value0(&scope, runtime_->newInt(0));
386 Int value1(&scope, runtime_->newInt(1));
387 Int value2(&scope, runtime_->newInt(2));
388 List list(&scope, runtime_->newList());
389 runtime_->listAdd(thread_, list, value0);
390 runtime_->listAdd(thread_, list, value1);
391 runtime_->listAdd(thread_, list, value2);
392 runtime_->listAdd(thread_, list, value1);
393 runtime_->listAdd(thread_, list, value0);
394
395 EXPECT_EQ(list.numItems(), 5);
396 runBuiltin(METH(list, remove), list, value1);
397 ASSERT_EQ(list.numItems(), 4);
398 EXPECT_EQ(list.at(0), value0);
399 EXPECT_EQ(list.at(1), value2);
400 EXPECT_EQ(list.at(2), value1);
401 EXPECT_EQ(list.at(3), value0);
402}
403
404TEST_F(ListBuiltinsTest, ListRemoveWithIdenticalObjectGetsRemoved) {
405 HandleScope scope(thread_);
406 ASSERT_FALSE(runFromCStr(runtime_, R"(
407class C:
408 def __eq__(self, other):
409 return False
410value = C()
411list = [value]
412)")
413 .isError());
414 Object value(&scope, mainModuleAt(runtime_, "value"));
415 List list(&scope, mainModuleAt(runtime_, "list"));
416 EXPECT_EQ(list.numItems(), 1);
417 runBuiltin(METH(list, remove), list, value);
418 EXPECT_EQ(list.numItems(), 0);
419}
420
421TEST_F(ListBuiltinsTest,
422 ListRemoveWithNonIdenticalEqualObjectInListGetsRemoved) {
423 HandleScope scope(thread_);
424 ASSERT_FALSE(runFromCStr(runtime_, R"(
425class C:
426 def __eq__(self, other):
427 return True
428list = [C()]
429)")
430 .isError());
431 Object value(&scope, NoneType::object());
432 List list(&scope, mainModuleAt(runtime_, "list"));
433 EXPECT_EQ(list.numItems(), 1);
434 runBuiltin(METH(list, remove), list, value);
435 EXPECT_EQ(list.numItems(), 0);
436}
437
438TEST_F(ListBuiltinsTest,
439 ListRemoveWithNonIdenticalEqualObjectAsKeyRaisesValueError) {
440 HandleScope scope(thread_);
441 ASSERT_FALSE(runFromCStr(runtime_, R"(
442class C:
443 def __eq__(self, other):
444 return True
445class D:
446 def __eq__(self, other):
447 return False
448value = C()
449list = [D()]
450)")
451 .isError());
452 Object value(&scope, mainModuleAt(runtime_, "value"));
453 List list(&scope, mainModuleAt(runtime_, "list"));
454 Object result(&scope, runBuiltin(METH(list, remove), list, value));
455 EXPECT_TRUE(raised(*result, LayoutId::kValueError));
456}
457
458TEST_F(ListBuiltinsTest, ListRemoveWithRaisingDunderEqualPropagatesException) {
459 HandleScope scope(thread_);
460 ASSERT_FALSE(runFromCStr(runtime_, R"(
461class Foo:
462 def __eq__(self, other):
463 raise UserWarning('')
464value = Foo()
465list = [None]
466)")
467 .isError());
468 Object value(&scope, mainModuleAt(runtime_, "value"));
469 List list(&scope, mainModuleAt(runtime_, "list"));
470 Object result(&scope, runBuiltin(METH(list, remove), list, value));
471 EXPECT_TRUE(raised(*result, LayoutId::kUserWarning));
472}
473
474TEST_F(ListBuiltinsTest, ListRemoveWithRaisingDunderBoolPropagatesException) {
475 HandleScope scope(thread_);
476 ASSERT_FALSE(runFromCStr(runtime_, R"(
477class C:
478 def __bool__(self):
479 raise UserWarning('foo')
480class D:
481 def __eq__(self, other):
482 return C()
483value = D()
484list = [None]
485)")
486 .isError());
487 Object value(&scope, mainModuleAt(runtime_, "value"));
488 List list(&scope, mainModuleAt(runtime_, "list"));
489 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(list, remove), list, value),
490 LayoutId::kUserWarning, "foo"));
491}
492
493TEST_F(ListBuiltinsTest, ReplicateList) {
494 ASSERT_FALSE(runFromCStr(runtime_, R"(
495result = [1, 2, 3] * 3
496)")
497 .isError());
498 HandleScope scope(thread_);
499 Object result(&scope, mainModuleAt(runtime_, "result"));
500 EXPECT_PYLIST_EQ(result, {1, 2, 3, 1, 2, 3, 1, 2, 3});
501}
502
503TEST_F(ListBuiltinsTest, ReplicateListWithNegativeRhsReturnsEmptyList) {
504 ASSERT_FALSE(runFromCStr(runtime_, R"(
505result = [1, 2, 3] * -3
506)")
507 .isError());
508 HandleScope scope(thread_);
509 Object result(&scope, mainModuleAt(runtime_, "result"));
510 EXPECT_PYLIST_EQ(result, {});
511}
512
513TEST_F(ListBuiltinsTest, SliceWithPositiveStepReturnsForwardsList) {
514 HandleScope scope(thread_);
515 List list1(&scope, listFromRange(1, 6));
516
517 // Test [2:]
518 List test(&scope, listSlice(thread_, list1, 2, 5, 1));
519 ASSERT_EQ(test.numItems(), 3);
520 EXPECT_TRUE(isIntEqualsWord(test.at(0), 3));
521 EXPECT_TRUE(isIntEqualsWord(test.at(1), 4));
522 EXPECT_TRUE(isIntEqualsWord(test.at(2), 5));
523}
524
525TEST_F(ListBuiltinsTest, SliceWithNegativeStepReturnsBackwardsList) {
526 HandleScope scope(thread_);
527 List list1(&scope, listFromRange(1, 6));
528
529 // Test [::-2]
530 List test(&scope, listSlice(thread_, list1, 4, -1, -2));
531 ASSERT_EQ(test.numItems(), 3);
532 EXPECT_TRUE(isIntEqualsWord(test.at(0), 5));
533 EXPECT_TRUE(isIntEqualsWord(test.at(1), 3));
534 EXPECT_TRUE(isIntEqualsWord(test.at(2), 1));
535}
536
537TEST_F(ListBuiltinsTest, IdenticalSliceIsCopy) {
538 HandleScope scope(thread_);
539 List list1(&scope, listFromRange(1, 6));
540
541 // Test: t[::] is t
542 List test(&scope, listSlice(thread_, list1, 0, 5, 1));
543 ASSERT_EQ(test.numItems(), 5);
544 EXPECT_TRUE(isIntEqualsWord(test.at(0), 1));
545 EXPECT_TRUE(isIntEqualsWord(test.at(4), 5));
546 ASSERT_NE(*test, *list1);
547}
548
549TEST_F(ListBuiltinsTest, DelitemWithInvalidNegativeIndexRaisesIndexError) {
550 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
551l = [1, 2, 3]
552del l[-4]
553)"),
554 LayoutId::kIndexError,
555 "list assignment index out of range"));
556}
557
558TEST_F(ListBuiltinsTest, DelitemWithInvalidIndexRaisesIndexError) {
559 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
560l = [1, 2, 3]
561del l[5]
562)"),
563 LayoutId::kIndexError,
564 "list assignment index out of range"));
565}
566
567TEST_F(ListBuiltinsTest, DelitemWithTooFewArgumentsRaisesTypeError) {
568 EXPECT_TRUE(raisedWithStr(
569 runFromCStr(runtime_, R"(
570[].__delitem__()
571)"),
572 LayoutId::kTypeError,
573 "'list.__delitem__' takes min 2 positional arguments but 1 given"));
574}
575
576TEST_F(ListBuiltinsTest, DelitemWithTooManyArgumentsRaisesTypeError) {
577 EXPECT_TRUE(raisedWithStr(
578 runFromCStr(runtime_, R"(
579[].__delitem__(1, 2)
580)"),
581 LayoutId::kTypeError,
582 "'list.__delitem__' takes max 2 positional arguments but 3 given"));
583}
584
585TEST_F(ListBuiltinsTest, DelitemWithNonIntegralIndexRaisesTypeError) {
586 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
587[].__delitem__("test")
588)"),
589 LayoutId::kTypeError,
590 "list indices must be integers or slices"));
591}
592
593TEST_F(ListBuiltinsTest, NonTypeInDunderNew) {
594 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
595list.__new__(1)
596)"),
597 LayoutId::kTypeError, "not a type object"));
598}
599
600TEST_F(ListBuiltinsTest, NonSubclassInDunderNew) {
601 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
602class Foo: pass
603list.__new__(Foo)
604)"),
605 LayoutId::kTypeError, "not a subtype of list"));
606}
607
608TEST_F(ListBuiltinsTest, SubclassList) {
609 HandleScope scope(thread_);
610 ASSERT_FALSE(runFromCStr(runtime_, R"(
611class Foo():
612 def __init__(self):
613 self.a = "a"
614class Bar(Foo, list): pass
615a = Bar()
616a.append(1)
617test1, test2 = a[0], a.a
618a.insert(0, 2)
619test3, test4 = a[0], a[1]
620a.pop()
621test5 = a[0]
622a.remove(2)
623test6 = len(a)
624)")
625 .isError());
626 Object test1(&scope, mainModuleAt(runtime_, "test1"));
627 Object test2(&scope, mainModuleAt(runtime_, "test2"));
628 Object test3(&scope, mainModuleAt(runtime_, "test3"));
629 Object test4(&scope, mainModuleAt(runtime_, "test4"));
630 Object test5(&scope, mainModuleAt(runtime_, "test5"));
631 Object test6(&scope, mainModuleAt(runtime_, "test6"));
632 EXPECT_EQ(*test1, SmallInt::fromWord(1));
633 EXPECT_EQ(*test2, SmallStr::fromCStr("a"));
634 EXPECT_EQ(*test3, SmallInt::fromWord(2));
635 EXPECT_EQ(*test4, SmallInt::fromWord(1));
636 EXPECT_EQ(*test5, SmallInt::fromWord(2));
637 EXPECT_EQ(*test6, SmallInt::fromWord(0));
638}
639
640TEST_F(ListBuiltinsTest, Delitem) {
641 HandleScope scope(thread_);
642 ASSERT_FALSE(runFromCStr(runtime_, R"(
643a = [42,'foo', 'bar']
644del a[2]
645del a[0]
646l = len(a)
647e = a[0]
648)")
649 .isError());
650 Object len(&scope, mainModuleAt(runtime_, "l"));
651 Object element(&scope, mainModuleAt(runtime_, "e"));
652 EXPECT_EQ(*len, SmallInt::fromWord(1));
653 EXPECT_EQ(*element, SmallStr::fromCStr("foo"));
654}
655
656TEST_F(ListBuiltinsTest, DunderIterReturnsListIter) {
657 HandleScope scope(thread_);
658 List empty_list(&scope, listFromRange(0, 0));
659 Object iter(&scope, runBuiltin(METH(list, __iter__), empty_list));
660 ASSERT_TRUE(iter.isListIterator());
661}
662
663TEST_F(ListIteratorBuiltinsTest, CallDunderNext) {
664 HandleScope scope(thread_);
665 List empty_list(&scope, listFromRange(0, 2));
666 Object iter(&scope, runBuiltin(METH(list, __iter__), empty_list));
667 ASSERT_TRUE(iter.isListIterator());
668
669 Object item1(&scope, runBuiltin(METH(list_iterator, __next__), iter));
670 EXPECT_TRUE(isIntEqualsWord(*item1, 0));
671
672 Object item2(&scope, runBuiltin(METH(list_iterator, __next__), iter));
673 EXPECT_TRUE(isIntEqualsWord(*item2, 1));
674}
675
676TEST_F(ListIteratorBuiltinsTest, DunderIterReturnsSelf) {
677 HandleScope scope(thread_);
678 List empty_list(&scope, listFromRange(0, 0));
679 Object iter(&scope, runBuiltin(METH(list, __iter__), empty_list));
680 ASSERT_TRUE(iter.isListIterator());
681
682 // Now call __iter__ on the iterator object
683 Object result(&scope, runBuiltin(METH(list_iterator, __iter__), iter));
684 ASSERT_EQ(*result, *iter);
685}
686
687TEST_F(ListIteratorBuiltinsTest, DunderLengthHintOnEmptyListIterator) {
688 HandleScope scope(thread_);
689 List empty_list(&scope, listFromRange(0, 0));
690 Object iter(&scope, runBuiltin(METH(list, __iter__), empty_list));
691 ASSERT_TRUE(iter.isListIterator());
692
693 Object length_hint(&scope,
694 runBuiltin(METH(list_iterator, __length_hint__), iter));
695 EXPECT_TRUE(isIntEqualsWord(*length_hint, 0));
696}
697
698TEST_F(ListIteratorBuiltinsTest, DunderLengthHintOnConsumedListIterator) {
699 HandleScope scope(thread_);
700 List list(&scope, listFromRange(0, 1));
701 Object iter(&scope, runBuiltin(METH(list, __iter__), list));
702 ASSERT_TRUE(iter.isListIterator());
703
704 Object length_hint1(&scope,
705 runBuiltin(METH(list_iterator, __length_hint__), iter));
706 EXPECT_TRUE(isIntEqualsWord(*length_hint1, 1));
707
708 // Consume the iterator
709 Object item1(&scope, runBuiltin(METH(list_iterator, __next__), iter));
710 EXPECT_TRUE(isIntEqualsWord(*item1, 0));
711
712 Object length_hint2(&scope,
713 runBuiltin(METH(list_iterator, __length_hint__), iter));
714 EXPECT_TRUE(isIntEqualsWord(*length_hint2, 0));
715}
716
717TEST_F(ListBuiltinsTest, InsertToList) {
718 HandleScope scope(thread_);
719 List list(&scope, runtime_->newList());
720
721 for (int i = 0; i < 9; i++) {
722 if (i == 1 || i == 6) {
723 continue;
724 }
725 Object value(&scope, SmallInt::fromWord(i));
726 runtime_->listAdd(thread_, list, value);
727 }
728 EXPECT_FALSE(isIntEqualsWord(list.at(1), 1));
729 EXPECT_FALSE(isIntEqualsWord(list.at(6), 6));
730
731 Object value2(&scope, SmallInt::fromWord(1));
732 listInsert(thread_, list, value2, 1);
733 Object value12(&scope, SmallInt::fromWord(6));
734 listInsert(thread_, list, value12, 6);
735
736 EXPECT_PYLIST_EQ(list, {0, 1, 2, 3, 4, 5, 6, 7, 8});
737}
738
739TEST_F(ListBuiltinsTest, InsertToListBounds) {
740 HandleScope scope(thread_);
741 List list(&scope, runtime_->newList());
742 for (int i = 0; i < 10; i++) {
743 Object value(&scope, SmallInt::fromWord(i));
744 runtime_->listAdd(thread_, list, value);
745 }
746 ASSERT_EQ(list.numItems(), 10);
747
748 Object value100(&scope, SmallInt::fromWord(100));
749 listInsert(thread_, list, value100, 100);
750 ASSERT_EQ(list.numItems(), 11);
751 EXPECT_TRUE(isIntEqualsWord(list.at(10), 100));
752
753 Object value0(&scope, SmallInt::fromWord(400));
754 listInsert(thread_, list, value0, 0);
755 ASSERT_EQ(list.numItems(), 12);
756 EXPECT_TRUE(isIntEqualsWord(list.at(0), 400));
757
758 Object value_n(&scope, SmallInt::fromWord(-10));
759 listInsert(thread_, list, value_n, -10);
760 ASSERT_EQ(list.numItems(), 13);
761 EXPECT_TRUE(isIntEqualsWord(list.at(2), -10));
762}
763
764TEST_F(ListBuiltinsTest, PopList) {
765 HandleScope scope(thread_);
766 List list(&scope, runtime_->newList());
767 for (int i = 0; i < 16; i++) {
768 Object value(&scope, SmallInt::fromWord(i));
769 runtime_->listAdd(thread_, list, value);
770 }
771 ASSERT_EQ(list.numItems(), 16);
772
773 // Pop from the end
774 RawObject res1 = listPop(thread_, list, 15);
775 ASSERT_EQ(list.numItems(), 15);
776 EXPECT_TRUE(isIntEqualsWord(list.at(14), 14));
777 EXPECT_TRUE(isIntEqualsWord(res1, 15));
778
779 // Pop elements from 5 - 10
780 for (int i = 0; i < 5; i++) {
781 RawObject res5 = listPop(thread_, list, 5);
782 EXPECT_TRUE(isIntEqualsWord(res5, i + 5));
783 }
784 ASSERT_EQ(list.numItems(), 10);
785 for (int i = 0; i < 5; i++) {
786 EXPECT_TRUE(isIntEqualsWord(list.at(i), i));
787 }
788 for (int i = 5; i < 10; i++) {
789 EXPECT_TRUE(isIntEqualsWord(list.at(i), i + 5));
790 }
791
792 // Pop element 0
793 RawObject res0 = listPop(thread_, list, 0);
794 ASSERT_EQ(list.numItems(), 9);
795 EXPECT_TRUE(isIntEqualsWord(list.at(0), 1));
796 EXPECT_TRUE(isIntEqualsWord(res0, 0));
797}
798
799TEST_F(ListBuiltinsTest, ExtendTuple) {
800 HandleScope scope(thread_);
801 List list(&scope, runtime_->newList());
802 Tuple object_array0(&scope, runtime_->emptyTuple());
803
804 for (int i = 0; i < 4; i++) {
805 Object value(&scope, SmallInt::fromWord(i));
806 runtime_->listAdd(thread_, list, value);
807 }
808 listExtend(Thread::current(), list, object_array0, 0);
809 EXPECT_EQ(list.numItems(), 4);
810
811 Object none(&scope, NoneType::object());
812 Tuple object_array1(&scope, runtime_->newTupleWith1(none));
813 listExtend(Thread::current(), list, object_array1, 1);
814 ASSERT_GE(list.numItems(), 5);
815 ASSERT_TRUE(list.at(4).isNoneType());
816
817 MutableTuple object_array16(&scope, runtime_->newMutableTuple(16));
818 for (word i = 0; i < 4; i++) {
819 object_array16.atPut(i, SmallInt::fromWord(i));
820 }
821 Tuple object_array_immutable(&scope, object_array16.becomeImmutable());
822
823 listExtend(Thread::current(), list, object_array_immutable, 4);
824 ASSERT_GE(list.numItems(), 9);
825 EXPECT_EQ(list.at(5), SmallInt::fromWord(0));
826 EXPECT_EQ(list.at(6), SmallInt::fromWord(1));
827 EXPECT_EQ(list.at(7), SmallInt::fromWord(2));
828 EXPECT_EQ(list.at(8), SmallInt::fromWord(3));
829}
830
831TEST_F(ListBuiltinsTest, SortEmptyListSucceeds) {
832 HandleScope scope(thread_);
833 List empty(&scope, runtime_->newList());
834 ASSERT_EQ(listSort(thread_, empty), NoneType::object());
835}
836
837TEST_F(ListBuiltinsTest, SortSingleElementListSucceeds) {
838 HandleScope scope(thread_);
839 List list(&scope, runtime_->newList());
840 Object elt(&scope, SmallInt::fromWord(5));
841 runtime_->listAdd(thread_, list, elt);
842 ASSERT_EQ(listSort(thread_, list), NoneType::object());
843 EXPECT_EQ(list.numItems(), 1);
844 EXPECT_EQ(list.at(0), *elt);
845}
846
847TEST_F(ListBuiltinsTest, SortMultiElementListSucceeds) {
848 HandleScope scope(thread_);
849 List list(&scope, runtime_->newList());
850 Object elt3(&scope, SmallInt::fromWord(3));
851 runtime_->listAdd(thread_, list, elt3);
852 Object elt2(&scope, SmallInt::fromWord(2));
853 runtime_->listAdd(thread_, list, elt2);
854 Object elt1(&scope, SmallInt::fromWord(1));
855 runtime_->listAdd(thread_, list, elt1);
856 ASSERT_EQ(listSort(thread_, list), NoneType::object());
857 EXPECT_EQ(list.numItems(), 3);
858 EXPECT_PYLIST_EQ(list, {1, 2, 3});
859}
860
861TEST_F(ListBuiltinsTest, SortMultiElementListSucceeds2) {
862 HandleScope scope(thread_);
863 List list(&scope, runtime_->newList());
864 Object elt3(&scope, SmallInt::fromWord(1));
865 runtime_->listAdd(thread_, list, elt3);
866 Object elt2(&scope, SmallInt::fromWord(3));
867 runtime_->listAdd(thread_, list, elt2);
868 Object elt1(&scope, SmallInt::fromWord(2));
869 runtime_->listAdd(thread_, list, elt1);
870 ASSERT_EQ(listSort(thread_, list), NoneType::object());
871 EXPECT_EQ(list.numItems(), 3);
872 EXPECT_PYLIST_EQ(list, {1, 2, 3});
873}
874
875TEST_F(ListBuiltinsTest, SortIsStable) {
876 HandleScope scope(thread_);
877 List list(&scope, runtime_->newList());
878 Object elt4(&scope, runtime_->newStrFromCStr("q"));
879 runtime_->listAdd(thread_, list, elt4);
880 Object elt3(&scope, runtime_->newStrFromCStr("world"));
881 runtime_->listAdd(thread_, list, elt3);
882 Object elt2(&scope, runtime_->newStrFromCStr("hello"));
883 runtime_->listAdd(thread_, list, elt2);
884 Object elt1(&scope, runtime_->newStrFromCStr("hello"));
885 runtime_->listAdd(thread_, list, elt1);
886 ASSERT_EQ(listSort(thread_, list), NoneType::object());
887 EXPECT_EQ(list.numItems(), 4);
888 EXPECT_EQ(list.at(0), *elt2);
889 EXPECT_EQ(list.at(1), *elt1);
890 EXPECT_EQ(list.at(2), *elt4);
891 EXPECT_EQ(list.at(3), *elt3);
892}
893
894TEST_F(ListBuiltinsTest, ListExtendSelfDuplicatesElements) {
895 ASSERT_FALSE(runFromCStr(runtime_, R"(
896a = [1, 2, 3]
897a.extend(a)
898)")
899 .isError());
900 HandleScope scope(thread_);
901 List a(&scope, mainModuleAt(runtime_, "a"));
902 ASSERT_EQ(a.numItems(), 6);
903 EXPECT_PYLIST_EQ(a, {1, 2, 3, 1, 2, 3});
904}
905
906TEST_F(ListBuiltinsTest, ListExtendListSubclassFallsBackToIter) {
907 ASSERT_FALSE(runFromCStr(runtime_, R"(
908class C(list):
909 def __iter__(self):
910 return [4, 5, 6].__iter__()
911a = [1, 2, 3]
912a.extend(C([1,2,3]))
913)")
914 .isError());
915 HandleScope scope(thread_);
916 List a(&scope, mainModuleAt(runtime_, "a"));
917 ASSERT_EQ(a.numItems(), 6);
918 EXPECT_PYLIST_EQ(a, {1, 2, 3, 4, 5, 6});
919}
920
921TEST_F(ListBuiltinsTest, ReverseEmptyListDoesNothing) {
922 ASSERT_FALSE(runFromCStr(runtime_, R"(
923result = []
924result.reverse()
925)")
926 .isError());
927 HandleScope scope(thread_);
928 Object result(&scope, mainModuleAt(runtime_, "result"));
929 ASSERT_TRUE(result.isList());
930 EXPECT_EQ(List::cast(*result).numItems(), 0);
931}
932
933TEST_F(ListBuiltinsTest, ReverseOneElementListDoesNothing) {
934 ASSERT_FALSE(runFromCStr(runtime_, R"(
935result = [2]
936result.reverse()
937)")
938 .isError());
939 HandleScope scope(thread_);
940 Object result(&scope, mainModuleAt(runtime_, "result"));
941 ASSERT_TRUE(result.isList());
942 EXPECT_EQ(List::cast(*result).numItems(), 1);
943 EXPECT_EQ(List::cast(*result).at(0), SmallInt::fromWord(2));
944}
945
946TEST_F(ListBuiltinsTest, ReverseOddManyElementListReversesList) {
947 ASSERT_FALSE(runFromCStr(runtime_, R"(
948result = [1, 2, 3]
949result.reverse()
950)")
951 .isError());
952 HandleScope scope(thread_);
953 Object result(&scope, mainModuleAt(runtime_, "result"));
954 EXPECT_PYLIST_EQ(result, {3, 2, 1});
955}
956
957TEST_F(ListBuiltinsTest, ReverseEvenManyElementListReversesList) {
958 ASSERT_FALSE(runFromCStr(runtime_, R"(
959result = [1, 2, 3, 4]
960result.reverse()
961)")
962 .isError());
963 HandleScope scope(thread_);
964 Object result(&scope, mainModuleAt(runtime_, "result"));
965 EXPECT_PYLIST_EQ(result, {4, 3, 2, 1});
966}
967
968TEST_F(ListBuiltinsTest, ReverseWithListSubclassDoesNotCallSubclassMethods) {
969 ASSERT_FALSE(runFromCStr(runtime_, R"(
970class C(list):
971 def __getitem__(self, key):
972 raise Exception("hi")
973 def __setitem__(self, key, val):
974 raise Exception("hi")
975result = C([1, 2, 3, 4])
976result.reverse()
977)")
978 .isError());
979 EXPECT_FALSE(Thread::current()->hasPendingException());
980}
981
982TEST_F(ListBuiltinsTest, SortWithMultiElementListSortsElements) {
983 ASSERT_FALSE(runFromCStr(runtime_, R"(
984ls = [3, 2, 1]
985ls.sort()
986)")
987 .isError());
988 HandleScope scope(thread_);
989 Object ls(&scope, mainModuleAt(runtime_, "ls"));
990 EXPECT_PYLIST_EQ(ls, {1, 2, 3});
991}
992
993TEST_F(ListBuiltinsTest, SortWithNonCallableKeyRaisesException) {
994 EXPECT_TRUE(raised(runFromCStr(runtime_, R"(
995ls = [3, 2, 1]
996ls.sort(key=5)
997)"),
998 LayoutId::kTypeError));
999 ;
1000}
1001
1002TEST_F(ListBuiltinsTest, SortWithKeySortsAccordingToKey) {
1003 ASSERT_FALSE(runFromCStr(runtime_, R"(
1004ls = [2, 3, 1]
1005ls.sort(key=lambda x: -x)
1006)")
1007 .isError());
1008 HandleScope scope(thread_);
1009 Object ls(&scope, mainModuleAt(runtime_, "ls"));
1010 EXPECT_PYLIST_EQ(ls, {3, 2, 1});
1011}
1012
1013TEST_F(ListBuiltinsTest, SortReverseReversesSortedList) {
1014 ASSERT_FALSE(runFromCStr(runtime_, R"(
1015ls = [2, 3, 1]
1016ls.sort(reverse=True)
1017)")
1018 .isError());
1019 HandleScope scope(thread_);
1020 Object ls(&scope, mainModuleAt(runtime_, "ls"));
1021 EXPECT_PYLIST_EQ(ls, {3, 2, 1});
1022}
1023
1024TEST_F(ListBuiltinsTest, ClearRemovesElements) {
1025 ASSERT_FALSE(runFromCStr(runtime_, R"(
1026ls = [2, 3, 1]
1027list.clear(ls)
1028)")
1029 .isError());
1030 HandleScope scope(thread_);
1031 Object ls(&scope, mainModuleAt(runtime_, "ls"));
1032 EXPECT_PYLIST_EQ(ls, {});
1033}
1034
1035TEST_F(ListBuiltinsTest, ClearRemovesAllElements) {
1036 ASSERT_FALSE(runFromCStr(runtime_, R"(
1037class C:
1038 pass
1039l = [C()]
1040)")
1041 .isError());
1042
1043 HandleScope scope(thread_);
1044 List list(&scope, mainModuleAt(runtime_, "l"));
1045 Object ref_obj(&scope, NoneType::object());
1046 {
1047 Object c(&scope, list.at(0));
1048 ref_obj = runtime_->newWeakRef(thread_, c);
1049 }
1050 WeakRef ref(&scope, *ref_obj);
1051 EXPECT_NE(ref.referent(), NoneType::object());
1052 runBuiltin(METH(list, clear), list);
1053 runtime_->collectGarbage();
1054 EXPECT_EQ(ref.referent(), NoneType::object());
1055}
1056
1057} // namespace testing
1058} // namespace py