this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "int-builtins.h"
3
4#include <cmath>
5#include <limits>
6
7#include "gtest/gtest.h"
8
9#include "builtins.h"
10#include "handles.h"
11#include "objects.h"
12#include "runtime.h"
13#include "test-utils.h"
14#include "type-builtins.h"
15
16namespace py {
17namespace testing {
18
19using BoolBuiltinsTest = RuntimeFixture;
20using IntBuiltinsTest = RuntimeFixture;
21using LargeIntBuiltinsTest = RuntimeFixture;
22
23TEST_F(IntBuiltinsTest, BuiltinBases) {
24 HandleScope scope(thread_);
25
26 Type integer(&scope, runtime_->typeAt(LayoutId::kInt));
27 EXPECT_EQ(integer.builtinBase(), LayoutId::kInt);
28
29 Type small_int(&scope, runtime_->typeAt(LayoutId::kSmallInt));
30 EXPECT_EQ(small_int.builtinBase(), LayoutId::kInt);
31
32 Type large_int(&scope, runtime_->typeAt(LayoutId::kLargeInt));
33 EXPECT_EQ(large_int.builtinBase(), LayoutId::kInt);
34
35 Type boolean(&scope, runtime_->typeAt(LayoutId::kBool));
36 EXPECT_EQ(boolean.builtinBase(), LayoutId::kInt);
37}
38
39TEST_F(IntBuiltinsTest, CompareSmallIntEq) {
40 HandleScope scope(thread_);
41
42 ASSERT_FALSE(runFromCStr(runtime_, R"(
43a = 1
44b = 2
45a_eq_b = a == b
46a_eq_a = a == a
47b_eq_b = b == b
48)")
49 .isError());
50
51 Object a_eq_b(&scope, mainModuleAt(runtime_, "a_eq_b"));
52 EXPECT_EQ(*a_eq_b, Bool::falseObj());
53 Object a_eq_a(&scope, mainModuleAt(runtime_, "a_eq_a"));
54 EXPECT_EQ(*a_eq_a, Bool::trueObj());
55 Object b_eq_b(&scope, mainModuleAt(runtime_, "b_eq_b"));
56 EXPECT_EQ(*b_eq_b, Bool::trueObj());
57}
58
59TEST_F(IntBuiltinsTest, CompareSmallIntGe) {
60 HandleScope scope(thread_);
61
62 ASSERT_FALSE(runFromCStr(runtime_, R"(
63a = 1
64b = 2
65a_ge_a = a >= a
66a_ge_b = a >= b
67b_ge_a = b >= a
68b_ge_b = b >= b
69)")
70 .isError());
71
72 Object a_ge_a(&scope, mainModuleAt(runtime_, "a_ge_a"));
73 EXPECT_EQ(*a_ge_a, Bool::trueObj());
74 Object a_ge_b(&scope, mainModuleAt(runtime_, "a_ge_b"));
75 EXPECT_EQ(*a_ge_b, Bool::falseObj());
76 Object b_ge_a(&scope, mainModuleAt(runtime_, "b_ge_a"));
77 EXPECT_EQ(*b_ge_a, Bool::trueObj());
78 Object b_ge_b(&scope, mainModuleAt(runtime_, "b_ge_b"));
79 EXPECT_EQ(*b_ge_b, Bool::trueObj());
80}
81
82TEST_F(IntBuiltinsTest, CompareSmallIntGt) {
83 HandleScope scope(thread_);
84
85 ASSERT_FALSE(runFromCStr(runtime_, R"(
86a = 1
87b = 2
88a_gt_a = a > a
89a_gt_b = a > b
90b_gt_a = b > a
91b_gt_b = b > b
92)")
93 .isError());
94
95 Object a_gt_a(&scope, mainModuleAt(runtime_, "a_gt_a"));
96 EXPECT_EQ(*a_gt_a, Bool::falseObj());
97 Object a_gt_b(&scope, mainModuleAt(runtime_, "a_gt_b"));
98 EXPECT_EQ(*a_gt_b, Bool::falseObj());
99 Object b_gt_a(&scope, mainModuleAt(runtime_, "b_gt_a"));
100 EXPECT_EQ(*b_gt_a, Bool::trueObj());
101 Object b_gt_b(&scope, mainModuleAt(runtime_, "b_gt_b"));
102 EXPECT_EQ(*b_gt_b, Bool::falseObj());
103}
104
105TEST_F(IntBuiltinsTest, CompareSmallIntLe) {
106 HandleScope scope(thread_);
107
108 ASSERT_FALSE(runFromCStr(runtime_, R"(
109a = 1
110b = 2
111a_le_a = a <= a
112a_le_b = a <= b
113b_le_a = b <= a
114b_le_b = b <= b
115)")
116 .isError());
117
118 Object a_le_a(&scope, mainModuleAt(runtime_, "a_le_a"));
119 EXPECT_EQ(*a_le_a, Bool::trueObj());
120 Object a_le_b(&scope, mainModuleAt(runtime_, "a_le_b"));
121 EXPECT_EQ(*a_le_b, Bool::trueObj());
122 Object b_le_a(&scope, mainModuleAt(runtime_, "b_le_a"));
123 EXPECT_EQ(*b_le_a, Bool::falseObj());
124 Object b_le_b(&scope, mainModuleAt(runtime_, "b_le_b"));
125 EXPECT_EQ(*b_le_b, Bool::trueObj());
126}
127
128TEST_F(IntBuiltinsTest, CompareSmallIntLt) {
129 HandleScope scope(thread_);
130
131 ASSERT_FALSE(runFromCStr(runtime_, R"(
132a = 1
133b = 2
134a_lt_a = a < a
135a_lt_b = a < b
136b_lt_a = b < a
137b_lt_b = b < b
138)")
139 .isError());
140
141 Object a_lt_a(&scope, mainModuleAt(runtime_, "a_lt_a"));
142 EXPECT_EQ(*a_lt_a, Bool::falseObj());
143 Object a_lt_b(&scope, mainModuleAt(runtime_, "a_lt_b"));
144 EXPECT_EQ(*a_lt_b, Bool::trueObj());
145 Object b_lt_a(&scope, mainModuleAt(runtime_, "b_lt_a"));
146 EXPECT_EQ(*b_lt_a, Bool::falseObj());
147 Object b_lt_b(&scope, mainModuleAt(runtime_, "b_lt_b"));
148 EXPECT_EQ(*b_lt_b, Bool::falseObj());
149}
150
151TEST_F(IntBuiltinsTest, CompareSmallIntNe) {
152 HandleScope scope(thread_);
153
154 ASSERT_FALSE(runFromCStr(runtime_, R"(
155a = 1
156b = 2
157a_ne_b = a != b
158a_ne_a = a != a
159b_ne_b = b != b
160)")
161 .isError());
162
163 Object a_ne_b(&scope, mainModuleAt(runtime_, "a_ne_b"));
164 EXPECT_EQ(*a_ne_b, Bool::trueObj());
165 Object a_ne_a(&scope, mainModuleAt(runtime_, "a_ne_a"));
166 EXPECT_EQ(*a_ne_a, Bool::falseObj());
167 Object b_ne_b(&scope, mainModuleAt(runtime_, "b_ne_b"));
168 EXPECT_EQ(*b_ne_b, Bool::falseObj());
169}
170
171TEST_F(IntBuiltinsTest, CompareOpSmallInt) {
172 HandleScope scope(thread_);
173
174 ASSERT_FALSE(runFromCStr(runtime_, R"(
175a = 1
176b = 2
177c = 1
178a_lt_b = a < b
179a_le_b = a <= b
180a_eq_b = a == b
181a_ge_b = a >= b
182a_gt_b = a > b
183a_is_c = a is c
184a_is_not_c = a is not c
185)")
186 .isError());
187
188 Object a_lt_b(&scope, mainModuleAt(runtime_, "a_lt_b"));
189 EXPECT_EQ(*a_lt_b, Bool::trueObj());
190 Object a_le_b(&scope, mainModuleAt(runtime_, "a_le_b"));
191 EXPECT_EQ(*a_le_b, Bool::trueObj());
192 Object a_eq_b(&scope, mainModuleAt(runtime_, "a_eq_b"));
193 EXPECT_EQ(*a_eq_b, Bool::falseObj());
194 Object a_ge_b(&scope, mainModuleAt(runtime_, "a_ge_b"));
195 EXPECT_EQ(*a_ge_b, Bool::falseObj());
196 Object a_gt_b(&scope, mainModuleAt(runtime_, "a_gt_b"));
197 EXPECT_EQ(*a_gt_b, Bool::falseObj());
198 Object a_is_c(&scope, mainModuleAt(runtime_, "a_is_c"));
199 EXPECT_EQ(*a_is_c, Bool::trueObj());
200 Object a_is_not_c(&scope, mainModuleAt(runtime_, "a_is_not_c"));
201 EXPECT_EQ(*a_is_not_c, Bool::falseObj());
202}
203
204TEST_F(IntBuiltinsTest, UnaryPositiveSmallInt) {
205 HandleScope scope(thread_);
206
207 const char* src = R"(
208pos = 123
209plus_pos = +pos
210neg = -123
211plus_neg = +neg
212)";
213
214 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
215
216 Object plus_pos(&scope, mainModuleAt(runtime_, "plus_pos"));
217 EXPECT_TRUE(isIntEqualsWord(*plus_pos, 123));
218
219 Object plus_neg(&scope, mainModuleAt(runtime_, "plus_neg"));
220 EXPECT_TRUE(isIntEqualsWord(*plus_neg, -123));
221}
222
223TEST_F(IntBuiltinsTest, UnaryNegateSmallInt) {
224 HandleScope scope(thread_);
225
226 const char* src = R"(
227pos = 123
228minus_pos = -pos
229neg = -123
230minus_neg = -neg
231)";
232
233 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
234
235 Object minus_pos(&scope, mainModuleAt(runtime_, "minus_pos"));
236 EXPECT_TRUE(isIntEqualsWord(*minus_pos, -123));
237
238 Object minus_neg(&scope, mainModuleAt(runtime_, "minus_neg"));
239 EXPECT_TRUE(isIntEqualsWord(*minus_neg, 123));
240}
241
242TEST_F(IntBuiltinsTest, TruthyIntPos) {
243 HandleScope scope(thread_);
244 Int one(&scope, SmallInt::fromWord(1));
245 EXPECT_EQ(runBuiltin(METH(int, __bool__), one), Bool::trueObj());
246}
247
248TEST_F(IntBuiltinsTest, TruthyIntZero) {
249 HandleScope scope(thread_);
250 Int zero(&scope, SmallInt::fromWord(0));
251 EXPECT_EQ(runBuiltin(METH(int, __bool__), zero), Bool::falseObj());
252}
253
254TEST_F(IntBuiltinsTest, InplaceAdd) {
255 HandleScope scope(thread_);
256
257 ASSERT_FALSE(runFromCStr(runtime_, R"(
258a = 1
259a += 0
260b = a
261a += 2
262)")
263 .isError());
264 Object a(&scope, mainModuleAt(runtime_, "a"));
265 Object b(&scope, mainModuleAt(runtime_, "b"));
266 EXPECT_TRUE(isIntEqualsWord(*a, 3));
267 EXPECT_TRUE(isIntEqualsWord(*b, 1));
268}
269
270TEST_F(IntBuiltinsTest, InplaceMultiply) {
271 HandleScope scope(thread_);
272
273 ASSERT_FALSE(runFromCStr(runtime_, R"(
274a = 5
275a *= 1
276b = a
277a *= 2
278)")
279 .isError());
280 Object a(&scope, mainModuleAt(runtime_, "a"));
281 Object b(&scope, mainModuleAt(runtime_, "b"));
282 EXPECT_TRUE(isIntEqualsWord(*a, 10));
283 EXPECT_TRUE(isIntEqualsWord(*b, 5));
284}
285
286TEST_F(IntBuiltinsTest, InplaceFloordiv) {
287 HandleScope scope(thread_);
288
289 ASSERT_FALSE(runFromCStr(runtime_, R"(
290a = 5
291a //= 1
292b = a
293a //= 2
294)")
295 .isError());
296 Object a(&scope, mainModuleAt(runtime_, "a"));
297 Object b(&scope, mainModuleAt(runtime_, "b"));
298 EXPECT_TRUE(isIntEqualsWord(*a, 2));
299 EXPECT_TRUE(isIntEqualsWord(*b, 5));
300}
301
302TEST_F(IntBuiltinsTest, InplaceModulo) {
303 HandleScope scope(thread_);
304
305 ASSERT_FALSE(runFromCStr(runtime_, R"(
306a = 10
307a %= 7
308b = a
309a %= 2
310)")
311 .isError());
312 Object a(&scope, mainModuleAt(runtime_, "a"));
313 Object b(&scope, mainModuleAt(runtime_, "b"));
314 EXPECT_TRUE(isIntEqualsWord(*a, 1));
315 EXPECT_TRUE(isIntEqualsWord(*b, 3));
316}
317
318TEST_F(IntBuiltinsTest, InplaceSub) {
319 HandleScope scope(thread_);
320
321 ASSERT_FALSE(runFromCStr(runtime_, R"(
322a = 10
323a -= 0
324b = a
325a -= 7
326)")
327 .isError());
328 Object a(&scope, mainModuleAt(runtime_, "a"));
329 Object b(&scope, mainModuleAt(runtime_, "b"));
330 EXPECT_TRUE(isIntEqualsWord(*a, 3));
331 EXPECT_TRUE(isIntEqualsWord(*b, 10));
332}
333
334TEST_F(IntBuiltinsTest, InplaceXor) {
335 HandleScope scope(thread_);
336
337 ASSERT_FALSE(runFromCStr(runtime_, R"(
338a = 0xFE
339a ^= 0
340b = a
341a ^= 0x03
342)")
343 .isError());
344 Object a(&scope, mainModuleAt(runtime_, "a"));
345 Object b(&scope, mainModuleAt(runtime_, "b"));
346 EXPECT_TRUE(isIntEqualsWord(*a, 0xFD));
347 EXPECT_TRUE(isIntEqualsWord(*b, 0xFE));
348}
349
350TEST_F(IntBuiltinsTest, DunderAbsWithBoolFalseReturnsZero) {
351 HandleScope scope(thread_);
352 Int self(&scope, Bool::falseObj());
353 Object result(&scope, runBuiltin(METH(int, __abs__), self));
354 EXPECT_EQ(result, SmallInt::fromWord(0));
355}
356
357TEST_F(IntBuiltinsTest, DunderAbsWithBoolTrueReturnsOne) {
358 HandleScope scope(thread_);
359 Int self(&scope, Bool::trueObj());
360 Object result(&scope, runBuiltin(METH(int, __abs__), self));
361 EXPECT_EQ(result, SmallInt::fromWord(1));
362}
363
364TEST_F(IntBuiltinsTest, DunderAbsWithPositiveIntReturnsInt) {
365 HandleScope scope(thread_);
366 Int self(&scope, runtime_->newInt(1234));
367 Object result(&scope, runBuiltin(METH(int, __abs__), self));
368 EXPECT_TRUE(isIntEqualsWord(*result, 1234));
369}
370
371TEST_F(IntBuiltinsTest, DunderAbsWithNegativeIntReturnsInt) {
372 HandleScope scope(thread_);
373 const uword digits[] = {0x154a0071b091fb7e, 0x9661bb54b4e68c59};
374 Int self(&scope, runtime_->newLargeIntWithDigits(digits));
375 Object result(&scope, runBuiltin(METH(int, __abs__), self));
376 const uword expected_digits[] = {0xeab5ff8e4f6e0482, 0x699e44ab4b1973a6};
377 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
378}
379
380TEST_F(IntBuiltinsTest, DunderAbsWithIntSubclassReturnsInt) {
381 HandleScope scope(thread_);
382 ASSERT_FALSE(runFromCStr(runtime_, R"(
383class X(int): pass
384neg = X(-42)
385pos = X(42)
386zero = X()
387)")
388 .isError());
389 Object neg(&scope, mainModuleAt(runtime_, "neg"));
390 Object pos(&scope, mainModuleAt(runtime_, "pos"));
391 Object zero(&scope, mainModuleAt(runtime_, "zero"));
392 EXPECT_EQ(runBuiltin(METH(int, __abs__), neg), SmallInt::fromWord(42));
393 EXPECT_EQ(runBuiltin(METH(int, __abs__), pos), SmallInt::fromWord(42));
394 EXPECT_EQ(runBuiltin(METH(int, __abs__), zero), SmallInt::fromWord(0));
395}
396
397TEST_F(IntBuiltinsTest, DunderAddWithSmallIntsReturnsSmallInt) {
398 HandleScope scope(thread_);
399
400 Int left(&scope, SmallInt::fromWord(42));
401 Int right(&scope, SmallInt::fromWord(-7));
402 Object result(&scope, runBuiltin(METH(int, __add__), left, right));
403 EXPECT_TRUE(isIntEqualsWord(*result, 35));
404}
405
406TEST_F(IntBuiltinsTest, DunderAddWithSmallIntsOverflowReturnsLargeInt) {
407 HandleScope scope(thread_);
408
409 Int max_small_int(&scope, SmallInt::fromWord(RawSmallInt::kMaxValue));
410 Int one(&scope, SmallInt::fromWord(1));
411 Object result(&scope, runBuiltin(METH(int, __add__), max_small_int, one));
412 EXPECT_TRUE(isIntEqualsWord(*result, RawSmallInt::kMaxValue + 1));
413}
414
415TEST_F(IntBuiltinsTest, DunderAddWithLargeInts) {
416 HandleScope scope(thread_);
417
418 const uword digits_left[] = {0xfedcba0987654321, 0x1234567890abcdef};
419 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
420 const uword digits_right[] = {0x9876543210abcdef, 0xfedcba0123456789};
421 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
422 Object result(&scope, runBuiltin(METH(int, __add__), left, right));
423 const uword expected_digits[] = {0x97530e3b98111110, 0x11111079b3f13579};
424 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
425}
426
427TEST_F(IntBuiltinsTest, DunderAddWithPositiveLargeIntsCarrying) {
428 HandleScope scope(thread_);
429
430 const uword digits_left[] = {kMaxUword, kMaxUword, 0};
431 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
432 Int right(&scope, runtime_->newInt(1));
433 Object result(&scope, runBuiltin(METH(int, __add__), left, right));
434 const uword expected_digits[] = {0, 0, 1};
435 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
436}
437
438TEST_F(IntBuiltinsTest, DunderAddWithNegativeLargeIntsCarrying) {
439 HandleScope scope(thread_);
440
441 Int left(&scope, runtime_->newInt(-1));
442 // The smallest negative number representable with 2 digits.
443 const uword digits_right[] = {0, static_cast<uword>(kMinWord)};
444 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
445 Object result(&scope, runBuiltin(METH(int, __add__), left, right));
446 const uword expected_digits[] = {kMaxUword, kMaxWord, kMaxUword};
447 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
448}
449
450TEST_F(IntBuiltinsTest, DunderAndWithSmallIntsReturnsSmallInt) {
451 HandleScope scope(thread_);
452 Int left(&scope, SmallInt::fromWord(0x15)); // 0b010101
453 Int right(&scope, SmallInt::fromWord(0x38)); // 0b111000
454 Object result(&scope, runBuiltin(METH(int, __and__), left, right));
455 EXPECT_TRUE(isIntEqualsWord(*result, 0x10)); // 0b10000
456}
457
458TEST_F(IntBuiltinsTest, DunderAndWithLargeIntsReturnsLargeInt) {
459 HandleScope scope(thread_);
460 const uword digits_left[] = {0x0f, 0x30, 0x1};
461 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
462 const uword digits_right[] = {0x03, 0xf0, 0x2, 7};
463 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
464 Object result(&scope, runBuiltin(METH(int, __and__), left, right));
465 const uword expected_digits[] = {0x03, 0x30};
466 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
467}
468
469TEST_F(IntBuiltinsTest, DunderAndWithNonIntReturnsNotImplemented) {
470 HandleScope scope(thread_);
471 const uword digits[] = {1, 2};
472 Int left(&scope, runtime_->newLargeIntWithDigits(digits));
473 Object right(&scope, Str::empty());
474 Object result(&scope, runBuiltin(METH(int, __and__), left, right));
475 EXPECT_TRUE(result.isNotImplementedType());
476}
477
478TEST_F(IntBuiltinsTest, DunderAndWithInvalidArgumentLeftRaisesException) {
479 HandleScope scope(thread_);
480 Object left(&scope, Str::empty());
481 const uword digits[] = {1, 2};
482 LargeInt right(&scope, runtime_->newLargeIntWithDigits(digits));
483 Object result(&scope, runBuiltin(METH(int, __and__), left, right));
484 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
485}
486
487TEST_F(IntBuiltinsTest, DunderAndWithIntSubclassReturnsInt) {
488 HandleScope scope(thread_);
489 ASSERT_FALSE(runFromCStr(runtime_, R"(
490class X(int): pass
491left = X(0b0011)
492right = X(0b0101)
493)")
494 .isError());
495 Object left(&scope, mainModuleAt(runtime_, "left"));
496 Object right(&scope, mainModuleAt(runtime_, "right"));
497 Object result(&scope, runBuiltin(METH(int, __and__), left, right));
498 EXPECT_EQ(result, SmallInt::fromWord(1)); // 0b0001
499}
500
501TEST_F(IntBuiltinsTest, DunderCeilAliasesDunderInt) {
502 HandleScope scope(thread_);
503 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
504 Object ceil_name(&scope, Runtime::internStrFromCStr(thread_, "__ceil__"));
505 Object ceil_obj(&scope, typeAt(type, ceil_name));
506 ASSERT_TRUE(ceil_obj.isFunction());
507 Function ceil(&scope, *ceil_obj);
508 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
509 Object dint_obj(&scope, typeAt(type, dint_name));
510 ASSERT_TRUE(dint_obj.isFunction());
511 Function dint(&scope, *ceil_obj);
512 EXPECT_EQ(Code::cast(ceil.code()).code(), Code::cast(dint.code()).code());
513 EXPECT_EQ(ceil.entry(), dint.entry());
514 EXPECT_EQ(ceil.entryKw(), dint.entryKw());
515 EXPECT_EQ(ceil.entryEx(), dint.entryEx());
516}
517
518TEST_F(IntBuiltinsTest, DunderFloorAliasesDunderInt) {
519 Thread* thread = Thread::current();
520 HandleScope scope(thread);
521 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
522 Object floor_name(&scope, Runtime::internStrFromCStr(thread_, "__floor__"));
523 Object floor_obj(&scope, typeAt(type, floor_name));
524 ASSERT_TRUE(floor_obj.isFunction());
525 Function floor(&scope, *floor_obj);
526 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
527 Object dint_obj(&scope, typeAt(type, dint_name));
528 ASSERT_TRUE(dint_obj.isFunction());
529 Function dint(&scope, *floor_obj);
530 EXPECT_EQ(Code::cast(floor.code()).code(), Code::cast(dint.code()).code());
531 EXPECT_EQ(floor.entry(), dint.entry());
532 EXPECT_EQ(floor.entryKw(), dint.entryKw());
533 EXPECT_EQ(floor.entryEx(), dint.entryEx());
534}
535
536TEST_F(IntBuiltinsTest, DunderLshiftWithBoolsTrueFalseReturnsSmallInt) {
537 HandleScope scope(thread_);
538 Object left(&scope, Bool::trueObj());
539 Object right(&scope, Bool::falseObj());
540 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
541 EXPECT_TRUE(isIntEqualsWord(*result, 1));
542}
543
544TEST_F(IntBuiltinsTest, DunderLshiftWithBoolsFalseTrueReturnsSmallInt) {
545 HandleScope scope(thread_);
546 Object left(&scope, Bool::falseObj());
547 Object right(&scope, Bool::trueObj());
548 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
549 EXPECT_TRUE(isIntEqualsWord(*result, 0));
550}
551
552TEST_F(IntBuiltinsTest, DunderLshiftWithBoolSmallIntReturnsLargeInt) {
553 HandleScope scope(thread_);
554 Object left(&scope, Bool::trueObj());
555 Object right(&scope, runtime_->newInt(kBitsPerWord));
556 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
557 const uword expected_digits[] = {0, 1};
558 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
559}
560
561TEST_F(IntBuiltinsTest, DunderLshiftWithSmallIntsReturnsSmallInt) {
562 HandleScope scope(thread_);
563 Object left(&scope, runtime_->newInt(0xd)); // 0b1101
564 Object right(&scope, runtime_->newInt(3));
565 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
566 EXPECT_TRUE(isIntEqualsWord(*result, 0x68)); // 0b1101000
567}
568
569TEST_F(IntBuiltinsTest, DunderLshiftWithNegativeSmallIntReturnsSmallInt) {
570 HandleScope scope(thread_);
571 Object left(&scope, runtime_->newInt(-2));
572 Object right(&scope, runtime_->newInt(1));
573 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
574 EXPECT_TRUE(isIntEqualsWord(*result, -4));
575}
576
577TEST_F(IntBuiltinsTest, DunderLshiftWithZeroReturnsZero) {
578 HandleScope scope(thread_);
579 Object left(&scope, runtime_->newInt(0));
580 const uword digits[] = {1, 2, 3, 4};
581 Object right(&scope, runtime_->newLargeIntWithDigits(digits));
582 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
583 EXPECT_TRUE(isIntEqualsWord(*result, 0));
584}
585
586TEST_F(IntBuiltinsTest, DunderLshiftWithBigSmallIntReturnsSmallInt) {
587 HandleScope scope(thread_);
588 Object left(&scope, runtime_->newInt(RawSmallInt::kMaxValue >> 1));
589 Object right(&scope, runtime_->newInt(1));
590 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
591 EXPECT_TRUE(isIntEqualsWord(*result, RawSmallInt::kMaxValue - 1));
592}
593
594TEST_F(IntBuiltinsTest, DunderLshiftWithBigNegativeSmallIntReturnsSmallInt) {
595 HandleScope scope(thread_);
596 Object left(&scope, runtime_->newInt(RawSmallInt::kMinValue >> 1));
597 Object right(&scope, runtime_->newInt(1));
598 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
599 EXPECT_TRUE(isIntEqualsWord(*result, RawSmallInt::kMinValue));
600}
601
602TEST_F(IntBuiltinsTest, DunderLshiftWithSmallIntsReturnsLargeInt) {
603 HandleScope scope(thread_);
604 Object left(&scope, runtime_->newInt(4));
605 Object right(&scope, runtime_->newInt(kBitsPerWord - 4));
606 Object result_obj(&scope, runBuiltin(METH(int, __lshift__), left, right));
607 ASSERT_TRUE(result_obj.isLargeInt());
608 LargeInt result(&scope, *result_obj);
609 EXPECT_EQ(result.numDigits(), 1);
610 EXPECT_EQ(result.digitAt(0), uword{1} << (kBitsPerWord - 2));
611}
612
613TEST_F(IntBuiltinsTest, DunderLshiftWithSmallIntsNegativeReturnsLargeInt) {
614 HandleScope scope(thread_);
615 Object left(&scope, runtime_->newInt(-4));
616 Object right(&scope, runtime_->newInt(kBitsPerWord - 3));
617 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
618 const uword expected_digits[] = {static_cast<uword>(-4)
619 << (kBitsPerWord - 3)};
620 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
621}
622
623TEST_F(IntBuiltinsTest, DunderLshiftWithSmallIntOverflowReturnsLargeInt) {
624 HandleScope scope(thread_);
625 Object left(&scope, runtime_->newInt(4));
626 Object right(&scope, runtime_->newInt(kBitsPerWord - 3));
627 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
628 const uword expected_digits[] = {kHighbitUword, 0};
629 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
630}
631
632TEST_F(IntBuiltinsTest,
633 DunderLshiftWithNegativeSmallIntOverflowReturnsLargeInt) {
634 HandleScope scope(thread_);
635 Object left(&scope, runtime_->newInt(-4));
636 Object right(&scope, runtime_->newInt(kBitsPerWord - 2));
637 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
638 const uword expected_digits[] = {0, kMaxUword};
639 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
640}
641
642TEST_F(IntBuiltinsTest, DunderLshiftWithLargeIntReturnsLargeInt) {
643 HandleScope scope(thread_);
644 const uword digits[] = {1, 1};
645 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
646 Object right(&scope, runtime_->newInt(2 * kBitsPerWord + 2));
647 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
648 const uword expected_digits[] = {0, 0, 4, 4};
649 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
650}
651
652TEST_F(IntBuiltinsTest, DunderLshiftWithNegativeLargeIntReturnsLargeInt) {
653 HandleScope scope(thread_);
654 const uword digits[] = {kMaxUword - 1, kMaxUword - 1};
655 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
656 Object right(&scope, runtime_->newInt(2 * kBitsPerWord + 2));
657 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
658 const uword expected_digits[] = {0, 0, kMaxUword - 7, kMaxUword - 4};
659 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
660}
661
662TEST_F(IntBuiltinsTest, DunderLshiftWithLargeIntWholeWordReturnsLargeInt) {
663 HandleScope scope(thread_);
664 const uword digits[] = {0xfe84754526de453c, 0x47e8218b97f94763};
665 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
666 Object right(&scope, runtime_->newInt(kBitsPerWord * 2));
667 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
668 const uword expected_digits[] = {0, 0, 0xfe84754526de453c,
669 0x47e8218b97f94763};
670 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
671}
672
673TEST_F(IntBuiltinsTest, DunderLshiftWithNegativeShiftAmountRaiseValueError) {
674 HandleScope scope(thread_);
675 Object left(&scope, runtime_->newInt(0));
676 Object right(&scope, runtime_->newInt(-1));
677 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
678 EXPECT_TRUE(
679 raisedWithStr(*result, LayoutId::kValueError, "negative shift count"));
680}
681
682TEST_F(IntBuiltinsTest, DunderLshiftWithNonIntSelfRaisesTypeError) {
683 HandleScope scope(thread_);
684 Object left(&scope, Str::empty());
685 Object right(&scope, runtime_->newInt(0));
686 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
687 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
688}
689
690TEST_F(IntBuiltinsTest, DunderLshiftWithNonIntReturnsNotImplemented) {
691 HandleScope scope(thread_);
692 Object left(&scope, runtime_->newInt(0));
693 Object right(&scope, Str::empty());
694 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
695 EXPECT_TRUE(result.isNotImplementedType());
696}
697
698TEST_F(IntBuiltinsTest, DunderLshiftWithIntSubclassReturnsInt) {
699 HandleScope scope(thread_);
700 ASSERT_FALSE(runFromCStr(runtime_, R"(
701class X(int): pass
702left = X(0b1101)
703right = X(3)
704)")
705 .isError());
706 Object left(&scope, mainModuleAt(runtime_, "left"));
707 Object right(&scope, mainModuleAt(runtime_, "right"));
708 Object result(&scope, runBuiltin(METH(int, __lshift__), left, right));
709 EXPECT_EQ(result, SmallInt::fromWord(0x68)); // 0b1101000
710}
711
712TEST_F(IntBuiltinsTest, DunderModWithSmallIntReturnsInt) {
713 HandleScope scope(thread_);
714 Object left(&scope, runtime_->newInt(-9876));
715 Object right(&scope, runtime_->newInt(123));
716 Object result(&scope, runBuiltin(METH(int, __mod__), left, right));
717 EXPECT_TRUE(isIntEqualsWord(*result, 87));
718}
719
720TEST_F(IntBuiltinsTest, DunderModWithZeroRaisesZeroDivisionError) {
721 HandleScope scope(thread_);
722 Object left(&scope, runtime_->newInt(2));
723 Object right(&scope, runtime_->newInt(0));
724 Object result(&scope, runBuiltin(METH(int, __mod__), left, right));
725 EXPECT_TRUE(raisedWithStr(*result, LayoutId::kZeroDivisionError,
726 "integer division or modulo by zero"));
727}
728
729TEST_F(IntBuiltinsTest, DunderModWithNonIntSelfRaisesTypeError) {
730 HandleScope scope(thread_);
731 Object left(&scope, Str::empty());
732 Object right(&scope, runtime_->newInt(1));
733 Object result(&scope, runBuiltin(METH(int, __mod__), left, right));
734 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
735}
736
737TEST_F(IntBuiltinsTest, DunderModWithNontIntReturnsNotImplemented) {
738 HandleScope scope(thread_);
739 Object left(&scope, runtime_->newInt(1));
740 Object right(&scope, Str::empty());
741 Object result(&scope, runBuiltin(METH(int, __mod__), left, right));
742 EXPECT_TRUE(result.isNotImplementedType());
743}
744
745TEST_F(IntBuiltinsTest, DunderMulWithSmallIntsReturnsSmallInt) {
746 HandleScope scope(thread_);
747
748 Int left(&scope, runtime_->newInt(13));
749 Int right(&scope, runtime_->newInt(-3));
750 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
751 EXPECT_TRUE(isIntEqualsWord(*result, -39));
752}
753
754TEST_F(IntBuiltinsTest, DunderMulWithSmallIntsReturnsSingleDigitLargeInt) {
755 HandleScope scope(thread_);
756
757 Int left(&scope, RawSmallInt::fromWord(RawSmallInt::kMaxValue));
758 Int right(&scope, RawSmallInt::fromWord(2));
759 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
760 EXPECT_TRUE(isIntEqualsWord(*result, RawSmallInt::kMaxValue * 2));
761}
762
763TEST_F(IntBuiltinsTest, DunderMulWithSmallIntsReturnsLargeInt) {
764 HandleScope scope(thread_);
765
766 Int num(&scope, RawSmallInt::fromWord(RawSmallInt::kMaxValue));
767 Object result(&scope, runBuiltin(METH(int, __mul__), num, num));
768 const uword expected_digits[] = {0x8000000000000001, 0xfffffffffffffff};
769 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
770}
771
772TEST_F(IntBuiltinsTest, DunderMulWithSmallIntLargeIntReturnsLargeInt) {
773 HandleScope scope(thread_);
774
775 Int left(&scope, RawSmallInt::fromWord(-3));
776 const uword digits[] = {0xa1b2c3d4e5f67890, 0xaabbccddeeff};
777 Int right(&scope, runtime_->newLargeIntWithDigits(digits));
778 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
779 const uword expected_digits[] = {0x1ae7b4814e1c9650, 0xfffdffcc99663301};
780 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
781}
782
783TEST_F(IntBuiltinsTest, DunderMulWithZeroReturnsSmallInt) {
784 HandleScope scope(thread_);
785
786 const uword digits[] = {0, 1};
787 Int left(&scope, runtime_->newLargeIntWithDigits(digits));
788 Int right(&scope, RawSmallInt::fromWord(0));
789 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
790 EXPECT_TRUE(isIntEqualsWord(*result, 0));
791}
792
793TEST_F(IntBuiltinsTest, DunderMulWithPositiveLargeIntsReturnsLargeInt) {
794 HandleScope scope(thread_);
795
796 const uword digits_left[] = {0xfedcba0987654321, 0x1234567890abcdef};
797 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
798 const uword digits_right[] = {0x0123456789abcdef, 0xfedcba9876543210, 0};
799 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
800 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
801 const uword expected_digits[] = {0x2236d928fe5618cf, 0xaa6c87569f0ec6a4,
802 0x213cff7595234949, 0x121fa00acd77d743};
803 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
804}
805
806TEST_F(IntBuiltinsTest, DunderMulWithMaxPositiveLargeIntsReturnsLargeInt) {
807 HandleScope scope(thread_);
808
809 const uword digits[] = {kMaxUword, 0};
810 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
811 Object result(&scope, runBuiltin(METH(int, __mul__), num, num));
812 const uword expected_digits[] = {1, kMaxUword - 1, 0};
813 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
814}
815
816TEST_F(IntBuiltinsTest, DunderMulWithNegativeLargeIntsReturnsLargeInt) {
817 HandleScope scope(thread_);
818
819 // Smallest negative number representable with 2 digits.
820 const uword digits[] = {0, static_cast<uword>(kMinWord)};
821 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
822 Object result(&scope, runBuiltin(METH(int, __mul__), num, num));
823 const uword expected_digits[] = {0, 0, 0, static_cast<uword>(kMinWord) >> 1};
824 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
825}
826
827TEST_F(IntBuiltinsTest, DunderMulWithNegativePositiveLargeIntsReturnsLargeInt) {
828 HandleScope scope(thread_);
829
830 const uword digits_left[] = {0xada6d35d8ef7c790};
831 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
832 const uword digits_right[] = {0x3ff2ca02c44fbb1c, 0x5873a2744317c09a};
833 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
834 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
835 const uword expected_digits[] = {0x6d80780b775003c0, 0xb46184fc0839baa0,
836 0xe38c265747f0661f};
837 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
838}
839
840TEST_F(IntBuiltinsTest, DunderMulWithPositiveNegativeLargeIntsReturnsLargeInt) {
841 HandleScope scope(thread_);
842
843 const uword digits_left[] = {0x3ff2ca02c44fbb1c, 0x5873a2744317c09a};
844 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
845 const uword digits_right[] = {0xada6d35d8ef7c790};
846 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
847 Object result(&scope, runBuiltin(METH(int, __mul__), left, right));
848 const uword expected_digits[] = {0x6d80780b775003c0, 0xb46184fc0839baa0,
849 0xe38c265747f0661f};
850 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
851}
852
853TEST_F(IntBuiltinsTest, DunderMulWithNonIntSelfRaisesTypeError) {
854 HandleScope scope(thread_);
855
856 Str str(&scope, Str::empty());
857 Int right(&scope, runtime_->newInt(1));
858 Object result(&scope, runBuiltin(METH(int, __mul__), str, right));
859 ASSERT_TRUE(raised(*result, LayoutId::kTypeError));
860}
861
862TEST_F(IntBuiltinsTest, DunderMulWithNonIntRightReturnsNotImplemented) {
863 HandleScope scope(thread_);
864
865 Int left(&scope, runtime_->newInt(1));
866 Str str(&scope, Str::empty());
867 Object result(&scope, runBuiltin(METH(int, __mul__), left, str));
868 ASSERT_TRUE(result.isNotImplementedType());
869}
870
871TEST_F(IntBuiltinsTest, DunderOrWithSmallIntsReturnsSmallInt) {
872 HandleScope scope(thread_);
873 Int left(&scope, SmallInt::fromWord(0x15)); // 0b010101
874 Int right(&scope, SmallInt::fromWord(0x38)); // 0b111000
875 Object result(&scope, runBuiltin(METH(int, __or__), left, right));
876 EXPECT_TRUE(isIntEqualsWord(*result, 0x3D)); // 0b111101
877}
878
879TEST_F(IntBuiltinsTest, DunderOrWithLargeIntsReturnsLargeInt) {
880 HandleScope scope(thread_);
881 const uword digits_left[] = {0x0C, 0xB0, 0xCAFE};
882 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
883 const uword digits_right[] = {0x03, 0xD0};
884 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
885 Object result(&scope, runBuiltin(METH(int, __or__), left, right));
886 const uword expected_digits[] = {0x0F, 0xF0, 0xCAFE};
887 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
888}
889
890TEST_F(IntBuiltinsTest, DunderOrWithNonIntReturnsNotImplemented) {
891 HandleScope scope(thread_);
892 const uword digits[] = {1, 2};
893 Int left(&scope, runtime_->newLargeIntWithDigits(digits));
894 Object right(&scope, Str::empty());
895 Object result(&scope, runBuiltin(METH(int, __or__), left, right));
896 EXPECT_TRUE(result.isNotImplementedType());
897}
898
899TEST_F(IntBuiltinsTest, DunderOrWithInvalidArgumentLeftRaisesException) {
900 HandleScope scope(thread_);
901 Object left(&scope, Str::empty());
902 const uword digits[] = {1, 2};
903 LargeInt right(&scope, runtime_->newLargeIntWithDigits(digits));
904 Object result(&scope, runBuiltin(METH(int, __or__), left, right));
905 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
906}
907
908TEST_F(IntBuiltinsTest, DunderOrWithIntSubclassReturnsInt) {
909 HandleScope scope(thread_);
910 ASSERT_FALSE(runFromCStr(runtime_, R"(
911class X(int): pass
912left = X(0b0011)
913right = X(0b0101)
914)")
915 .isError());
916 Object left(&scope, mainModuleAt(runtime_, "left"));
917 Object right(&scope, mainModuleAt(runtime_, "right"));
918 Object result(&scope, runBuiltin(METH(int, __or__), left, right));
919 EXPECT_EQ(result, SmallInt::fromWord(7)); // 0b0111
920}
921
922TEST_F(IntBuiltinsTest, BinaryAddSmallInt) {
923 HandleScope scope(thread_);
924
925 ASSERT_FALSE(runFromCStr(runtime_, R"(
926a = 2
927b = 1
928c = a + b
929)")
930 .isError());
931
932 Object c(&scope, mainModuleAt(runtime_, "c"));
933 EXPECT_TRUE(isIntEqualsWord(*c, 3));
934}
935
936TEST_F(IntBuiltinsTest, BitLength) {
937 HandleScope scope(thread_);
938
939 // (0).bit_length() == 0
940 Object num(&scope, SmallInt::fromWord(0));
941 Object bit_length(&scope, runBuiltin(METH(int, bit_length), num));
942 EXPECT_TRUE(isIntEqualsWord(*bit_length, 0));
943
944 // (1).bit_length() == 1
945 num = SmallInt::fromWord(1);
946 Object bit_length1(&scope, runBuiltin(METH(int, bit_length), num));
947 EXPECT_TRUE(isIntEqualsWord(*bit_length1, 1));
948
949 // (-1).bit_length() == 1
950 num = SmallInt::fromWord(1);
951 Object bit_length2(&scope, runBuiltin(METH(int, bit_length), num));
952 EXPECT_TRUE(isIntEqualsWord(*bit_length2, 1));
953
954 // (SmallInt::kMaxValue).bit_length() == 62
955 num = SmallInt::fromWord(RawSmallInt::kMaxValue);
956 Object bit_length3(&scope, runBuiltin(METH(int, bit_length), num));
957 EXPECT_TRUE(isIntEqualsWord(*bit_length3, 62));
958
959 // (SmallInt::kMinValue).bit_length() == 63
960 num = SmallInt::fromWord(RawSmallInt::kMinValue);
961 Object bit_length4(&scope, runBuiltin(METH(int, bit_length), num));
962 EXPECT_TRUE(isIntEqualsWord(*bit_length4, 63));
963
964 // (kMaxInt64).bit_length() == 63
965 num = runtime_->newInt(kMaxInt64);
966 Object bit_length5(&scope, runBuiltin(METH(int, bit_length), num));
967 EXPECT_TRUE(isIntEqualsWord(*bit_length5, 63));
968
969 // (kMinInt64).bit_length() == 64
970 num = runtime_->newInt(kMinInt64);
971 Object bit_length6(&scope, runBuiltin(METH(int, bit_length), num));
972 EXPECT_TRUE(isIntEqualsWord(*bit_length6, 64));
973
974 uword digits[] = {0, kMaxInt32};
975 num = runtime_->newLargeIntWithDigits(digits);
976 Object bit_length7(&scope, runBuiltin(METH(int, bit_length), num));
977 // 31 bits for kMaxInt32 + 64 bits
978 EXPECT_TRUE(isIntEqualsWord(*bit_length7, 95));
979
980 // (kMinInt64 * 4).bit_length() == 66
981 uword digits2[] = {0, kMaxUword - 1}; // kMaxUword - 1 == -2
982 num = runtime_->newLargeIntWithDigits(digits2);
983 Object bit_length8(&scope, runBuiltin(METH(int, bit_length), num));
984 EXPECT_TRUE(isIntEqualsWord(*bit_length8, 66));
985
986 // (kMinInt64 * 4 + 3).bit_length() == 65
987 uword digits3[] = {3, kMaxUword - 1}; // kMaxUword - 1 == -2
988 num = runtime_->newLargeIntWithDigits(digits3);
989 Object bit_length9(&scope, runBuiltin(METH(int, bit_length), num));
990 EXPECT_TRUE(isIntEqualsWord(*bit_length9, 65));
991}
992
993TEST_F(IntBuiltinsTest, CompareLargeIntEq) {
994 HandleScope scope(thread_);
995
996 Object a(&scope, runtime_->newInt(RawSmallInt::kMaxValue + 1));
997 Object b(&scope, runtime_->newInt(RawSmallInt::kMinValue - 1));
998 Object zero(&scope, SmallInt::fromWord(0));
999 ASSERT_TRUE(a.isLargeInt());
1000 ASSERT_TRUE(b.isLargeInt());
1001
1002 Object cmp_1(&scope, runBuiltin(METH(int, __eq__), a, b));
1003 ASSERT_TRUE(cmp_1.isBool());
1004 EXPECT_EQ(*cmp_1, Bool::falseObj());
1005
1006 Object cmp_2(&scope, runBuiltin(METH(int, __eq__), a, zero));
1007 ASSERT_TRUE(cmp_2.isBool());
1008 EXPECT_EQ(*cmp_2, Bool::falseObj());
1009
1010 Object cmp_3(&scope, runBuiltin(METH(int, __eq__), a, a));
1011 ASSERT_TRUE(cmp_3.isBool());
1012 EXPECT_EQ(*cmp_3, Bool::trueObj());
1013
1014 Object cmp_4(&scope, runBuiltin(METH(int, __eq__), b, a));
1015 ASSERT_TRUE(cmp_4.isBool());
1016 EXPECT_EQ(*cmp_4, Bool::falseObj());
1017
1018 Object cmp_5(&scope, runBuiltin(METH(int, __eq__), b, zero));
1019 ASSERT_TRUE(cmp_5.isBool());
1020 EXPECT_EQ(*cmp_5, Bool::falseObj());
1021
1022 Object cmp_6(&scope, runBuiltin(METH(int, __eq__), b, b));
1023 ASSERT_TRUE(cmp_6.isBool());
1024 EXPECT_EQ(*cmp_6, Bool::trueObj());
1025}
1026
1027TEST_F(IntBuiltinsTest, CompareLargeIntNe) {
1028 HandleScope scope(thread_);
1029
1030 Object a(&scope, runtime_->newInt(RawSmallInt::kMaxValue + 1));
1031 Object b(&scope, runtime_->newInt(RawSmallInt::kMinValue - 1));
1032 Object zero(&scope, SmallInt::fromWord(0));
1033 ASSERT_TRUE(a.isLargeInt());
1034 ASSERT_TRUE(b.isLargeInt());
1035
1036 Object cmp_1(&scope, runBuiltin(METH(int, __ne__), a, b));
1037 ASSERT_TRUE(cmp_1.isBool());
1038 EXPECT_EQ(*cmp_1, Bool::trueObj());
1039
1040 Object cmp_2(&scope, runBuiltin(METH(int, __ne__), a, zero));
1041 ASSERT_TRUE(cmp_2.isBool());
1042 EXPECT_EQ(*cmp_2, Bool::trueObj());
1043
1044 Object cmp_3(&scope, runBuiltin(METH(int, __ne__), a, a));
1045 ASSERT_TRUE(cmp_3.isBool());
1046 EXPECT_EQ(*cmp_3, Bool::falseObj());
1047
1048 Object cmp_4(&scope, runBuiltin(METH(int, __ne__), b, a));
1049 ASSERT_TRUE(cmp_4.isBool());
1050 EXPECT_EQ(*cmp_4, Bool::trueObj());
1051
1052 Object cmp_5(&scope, runBuiltin(METH(int, __ne__), b, zero));
1053 ASSERT_TRUE(cmp_5.isBool());
1054 EXPECT_EQ(*cmp_5, Bool::trueObj());
1055
1056 Object cmp_6(&scope, runBuiltin(METH(int, __ne__), b, b));
1057 ASSERT_TRUE(cmp_6.isBool());
1058 EXPECT_EQ(*cmp_6, Bool::falseObj());
1059}
1060
1061TEST_F(IntBuiltinsTest, DunderFloatWithBoolReturnsFloat) {
1062 HandleScope scope(thread_);
1063
1064 Object a(&scope, Bool::trueObj());
1065 Object a_float(&scope, runBuiltin(METH(int, __float__), a));
1066 EXPECT_TRUE(isFloatEqualsDouble(*a_float, 1.0));
1067
1068 Object b(&scope, Bool::falseObj());
1069 Object b_float(&scope, runBuiltin(METH(int, __float__), b));
1070 EXPECT_TRUE(isFloatEqualsDouble(*b_float, 0.0));
1071}
1072
1073TEST_F(IntBuiltinsTest, DunderFloatWithSmallIntReturnsFloat) {
1074 HandleScope scope(thread_);
1075
1076 Int num(&scope, RawSmallInt::fromWord(-7));
1077 Object result(&scope, runBuiltin(METH(int, __float__), num));
1078 EXPECT_TRUE(isFloatEqualsDouble(*result, -7.0));
1079}
1080
1081TEST_F(IntBuiltinsTest, DunderFloatWithOneDigitLargeIntReturnsFloat) {
1082 HandleScope scope(thread_);
1083
1084 const uword digits[] = {static_cast<uword>(kMinWord)};
1085 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1086 Object result(&scope, runBuiltin(METH(int, __float__), num));
1087 EXPECT_TRUE(isFloatEqualsDouble(*result, double{kMinWord}));
1088}
1089
1090TEST_F(IntBuiltinsTest, DunderFloatWithLargeIntReturnsFloat) {
1091 HandleScope scope(thread_);
1092
1093 const uword digits[] = {0x85b3f6fb0496ac6f, 0x129ef6};
1094 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1095 Object result(&scope, runBuiltin(METH(int, __float__), num));
1096 EXPECT_TRUE(isFloatEqualsDouble(
1097 *result, std::strtod("0x1.29ef685b3f6fbp+84", nullptr)));
1098}
1099
1100TEST_F(IntBuiltinsTest, DunderFloatWithNegativeLargeIntReturnsFloat) {
1101 HandleScope scope(thread_);
1102
1103 const uword digits[] = {0x937822557f9bad3f, 0xb31911a86c86a071};
1104 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1105 Object result(&scope, runBuiltin(METH(int, __float__), num));
1106 EXPECT_TRUE(isFloatEqualsDouble(
1107 *result, std::strtod("-0x1.339bb95e4de58p+126", nullptr)));
1108}
1109
1110TEST_F(IntBuiltinsTest,
1111 DunderFloatWithNegativeLargeIntMagnitudeComputationCarriesReturnsFloat) {
1112 HandleScope scope(thread_);
1113
1114 const uword digits[] = {1, 0, 0, 0xfffedcc000000000};
1115 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1116 Object result(&scope, runBuiltin(METH(int, __float__), num));
1117 EXPECT_TRUE(
1118 isFloatEqualsDouble(*result, std::strtod("-0x1.234p240", nullptr)));
1119}
1120
1121TEST_F(IntBuiltinsTest, DunderFloatWithLargeIntRoundedDownReturnsFloat) {
1122 HandleScope scope(thread_);
1123
1124 // Produce a 1 so that all of the mantissa lies in the high digit but the bit
1125 // triggering the rounding is in the low digit.
1126 uword mantissa_high_bit = uword{1} << kDoubleMantissaBits;
1127 const uword digits[] = {0, mantissa_high_bit};
1128 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1129 Object result(&scope, runBuiltin(METH(int, __float__), num));
1130 EXPECT_TRUE(isFloatEqualsDouble(*result, std::strtod("0x1.p116", nullptr)));
1131}
1132
1133TEST_F(IntBuiltinsTest, DunderFloatWithLargeIntRoundedDownToEvenReturnsFloat) {
1134 HandleScope scope(thread_);
1135
1136 const uword digits[] = {uword{1} << (kBitsPerWord - kDoubleMantissaBits - 1),
1137 1};
1138 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1139 Object result(&scope, runBuiltin(METH(int, __float__), num));
1140 EXPECT_TRUE(isFloatEqualsDouble(*result, std::strtod("0x1.p64", nullptr)));
1141}
1142
1143TEST_F(IntBuiltinsTest, DunderFloatWithLargeIntRoundedUpToEvenReturnsFloat) {
1144 HandleScope scope(thread_);
1145
1146 uword mantissa_high_bit_plus_one = (uword{1} << kDoubleMantissaBits) + 1;
1147 const uword digits[] = {kHighbitUword, mantissa_high_bit_plus_one};
1148 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1149 Object result(&scope, runBuiltin(METH(int, __float__), num));
1150 EXPECT_TRUE(isFloatEqualsDouble(
1151 *result, std::strtod("0x1.0000000000002p116", nullptr)));
1152}
1153
1154TEST_F(IntBuiltinsTest,
1155 DunderFloatWithNegativeLargeIntRoundedDownToEvenReturnsFloat) {
1156 HandleScope scope(thread_);
1157
1158 uword mantissa_high_bit = uword{1} << kDoubleMantissaBits;
1159 const uword digits[] = {0, kHighbitUword, ~mantissa_high_bit};
1160 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1161 Object result(&scope, runBuiltin(METH(int, __float__), num));
1162 EXPECT_TRUE(isFloatEqualsDouble(*result, std::strtod("-0x1.p180", nullptr)));
1163}
1164
1165TEST_F(IntBuiltinsTest,
1166 DunderFloatWithNegativeLargeIntRoundedUpToEvenReturnsFloat) {
1167 HandleScope scope(thread_);
1168
1169 uword mantissa_high_bit_plus_one = (uword{1} << kDoubleMantissaBits) | 1;
1170 const uword digits[] = {0, kHighbitUword, ~mantissa_high_bit_plus_one};
1171 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1172 Object result(&scope, runBuiltin(METH(int, __float__), num));
1173 EXPECT_TRUE(isFloatEqualsDouble(
1174 *result, std::strtod("-0x1.0000000000002p180", nullptr)));
1175}
1176
1177TEST_F(IntBuiltinsTest,
1178 DunderFloatWithLargeIntRoundedUpIncreasingExponentReturnsFloat) {
1179 HandleScope scope(thread_);
1180
1181 uword mantissa_all_one = (uword{1} << (kDoubleMantissaBits + 1)) - 1;
1182 const uword digits[] = {kHighbitUword, mantissa_all_one};
1183 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
1184 Object result(&scope, runBuiltin(METH(int, __float__), num));
1185 EXPECT_TRUE(isFloatEqualsDouble(*result, std::strtod("0x1.p117", nullptr)));
1186}
1187
1188static RawObject largestIntBeforeFloatOverflow(Runtime* runtime) {
1189 int exponent_bits = kBitsPerDouble - kDoubleMantissaBits - 1;
1190 word max_unbiased_exponent = (1 << (exponent_bits - 1)) - 1;
1191 CHECK((max_unbiased_exponent + 1) % kBitsPerWord == 0,
1192 "assuming max exponent position matches highest bit in digit");
1193 // Note: Need an extra digit for the sign.
1194 word num_digits = (max_unbiased_exponent + 1) / kBitsPerWord + 1;
1195 std::unique_ptr<uword[]> digits(new uword[num_digits]);
1196 for (word i = 0; i < num_digits - 1; i++) {
1197 digits[i] = kMaxUword;
1198 }
1199 // Set the bit immediately below the mantissa to zero to avoid rounding up.
1200 digits[num_digits - 2] &= ~(1 << (kBitsPerWord - kDoubleMantissaBits - 2));
1201 digits[num_digits - 1] = 0;
1202 return runtime->newLargeIntWithDigits(View<uword>(digits.get(), num_digits));
1203}
1204
1205TEST_F(IntBuiltinsTest,
1206 DunderFloatLargestPossibleLargeIntBeforeOverflowReturnsFloat) {
1207 HandleScope scope(thread_);
1208
1209 Int num(&scope, largestIntBeforeFloatOverflow(runtime_));
1210 Object result(&scope, runBuiltin(METH(int, __float__), num));
1211 ASSERT_TRUE(result.isFloat());
1212 EXPECT_TRUE(isFloatEqualsDouble(*result, std::numeric_limits<double>::max()));
1213}
1214
1215TEST_F(IntBuiltinsTest, DunderFloatOverflowRaisesOverflowError) {
1216 HandleScope scope(thread_);
1217
1218 // Add 1 to the largest number that is still convertible to float.
1219 Int num0(&scope, largestIntBeforeFloatOverflow(runtime_));
1220 Int one(&scope, runtime_->newInt(1));
1221 Int num1(&scope, runBuiltin(METH(int, __add__), num0, one));
1222 Object result(&scope, runBuiltin(METH(int, __float__), num1));
1223 EXPECT_TRUE(raised(*result, LayoutId::kOverflowError));
1224}
1225
1226TEST_F(IntBuiltinsTest, DunderFloatWithNonIntReturnsError) {
1227 HandleScope scope(thread_);
1228 Object none(&scope, NoneType::object());
1229 Object result(&scope, runBuiltin(METH(int, __int__), none));
1230 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
1231}
1232
1233TEST_F(IntBuiltinsTest, DunderFloordivWithSmallIntReturnsInt) {
1234 HandleScope scope(thread_);
1235 Object left(&scope, runtime_->newInt(42));
1236 Object right(&scope, runtime_->newInt(9));
1237 Object result(&scope, runBuiltin(METH(int, __floordiv__), left, right));
1238 EXPECT_TRUE(isIntEqualsWord(*result, 4));
1239}
1240
1241TEST_F(IntBuiltinsTest, DunderFloordivWithZeroRaisesZeroDivisionError) {
1242 HandleScope scope(thread_);
1243 Object left(&scope, runtime_->newInt(2));
1244 Object right(&scope, runtime_->newInt(0));
1245 Object result(&scope, runBuiltin(METH(int, __floordiv__), left, right));
1246 EXPECT_TRUE(raisedWithStr(*result, LayoutId::kZeroDivisionError,
1247 "integer division or modulo by zero"));
1248}
1249
1250TEST_F(IntBuiltinsTest, DunderFloordivWithNonIntSelfRaisesTypeError) {
1251 HandleScope scope(thread_);
1252 Object left(&scope, Str::empty());
1253 Object right(&scope, runtime_->newInt(1));
1254 Object result(&scope, runBuiltin(METH(int, __floordiv__), left, right));
1255 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
1256}
1257
1258TEST_F(IntBuiltinsTest, DunderFloordivWithNontIntReturnsNotImplemented) {
1259 HandleScope scope(thread_);
1260 Object left(&scope, runtime_->newInt(1));
1261 Object right(&scope, Str::empty());
1262 Object result(&scope, runBuiltin(METH(int, __floordiv__), left, right));
1263 EXPECT_TRUE(result.isNotImplementedType());
1264}
1265
1266TEST_F(LargeIntBuiltinsTest, TruthyLargeInt) {
1267 ASSERT_FALSE(runFromCStr(runtime_, R"(
1268value = 46116860184273879030000000
1269)")
1270 .isError());
1271 HandleScope scope(thread_);
1272 Object value(&scope, mainModuleAt(runtime_, "value"));
1273 EXPECT_EQ(runBuiltin(METH(int, __bool__), value), Bool::trueObj());
1274}
1275
1276TEST_F(IntBuiltinsTest, CompareLargeIntGe) {
1277 HandleScope scope(thread_);
1278
1279 Object a(&scope, runtime_->newInt(RawSmallInt::kMaxValue + 1));
1280 Object b(&scope, runtime_->newInt(RawSmallInt::kMinValue - 1));
1281 Object zero(&scope, SmallInt::fromWord(0));
1282 ASSERT_TRUE(a.isLargeInt());
1283 ASSERT_TRUE(b.isLargeInt());
1284
1285 Object cmp_1(&scope, runBuiltin(METH(int, __ge__), a, b));
1286 ASSERT_TRUE(cmp_1.isBool());
1287 EXPECT_EQ(*cmp_1, Bool::trueObj());
1288
1289 Object cmp_2(&scope, runBuiltin(METH(int, __ge__), a, zero));
1290 ASSERT_TRUE(cmp_2.isBool());
1291 EXPECT_EQ(*cmp_2, Bool::trueObj());
1292
1293 Object cmp_3(&scope, runBuiltin(METH(int, __ge__), a, a));
1294 ASSERT_TRUE(cmp_3.isBool());
1295 EXPECT_EQ(*cmp_3, Bool::trueObj());
1296
1297 Object cmp_4(&scope, runBuiltin(METH(int, __ge__), b, a));
1298 ASSERT_TRUE(cmp_4.isBool());
1299 EXPECT_EQ(*cmp_4, Bool::falseObj());
1300
1301 Object cmp_5(&scope, runBuiltin(METH(int, __ge__), b, zero));
1302 ASSERT_TRUE(cmp_5.isBool());
1303 EXPECT_EQ(*cmp_5, Bool::falseObj());
1304
1305 Object cmp_6(&scope, runBuiltin(METH(int, __ge__), b, b));
1306 ASSERT_TRUE(cmp_6.isBool());
1307 EXPECT_EQ(*cmp_6, Bool::trueObj());
1308}
1309
1310TEST_F(IntBuiltinsTest, CompareLargeIntLe) {
1311 HandleScope scope(thread_);
1312
1313 Object a(&scope, runtime_->newInt(RawSmallInt::kMaxValue + 1));
1314 Object b(&scope, runtime_->newInt(RawSmallInt::kMinValue - 1));
1315 Object zero(&scope, SmallInt::fromWord(0));
1316 ASSERT_TRUE(a.isLargeInt());
1317 ASSERT_TRUE(b.isLargeInt());
1318
1319 Object cmp_1(&scope, runBuiltin(METH(int, __le__), a, b));
1320 ASSERT_TRUE(cmp_1.isBool());
1321 EXPECT_EQ(*cmp_1, Bool::falseObj());
1322
1323 Object cmp_2(&scope, runBuiltin(METH(int, __le__), a, zero));
1324 ASSERT_TRUE(cmp_2.isBool());
1325 EXPECT_EQ(*cmp_2, Bool::falseObj());
1326
1327 Object cmp_3(&scope, runBuiltin(METH(int, __le__), a, a));
1328 ASSERT_TRUE(cmp_3.isBool());
1329 EXPECT_EQ(*cmp_3, Bool::trueObj());
1330
1331 Object cmp_4(&scope, runBuiltin(METH(int, __le__), b, a));
1332 ASSERT_TRUE(cmp_4.isBool());
1333 EXPECT_EQ(*cmp_4, Bool::trueObj());
1334
1335 Object cmp_5(&scope, runBuiltin(METH(int, __le__), b, zero));
1336 ASSERT_TRUE(cmp_5.isBool());
1337 EXPECT_EQ(*cmp_5, Bool::trueObj());
1338
1339 Object cmp_6(&scope, runBuiltin(METH(int, __le__), b, b));
1340 ASSERT_TRUE(cmp_6.isBool());
1341 EXPECT_EQ(*cmp_6, Bool::trueObj());
1342}
1343
1344TEST_F(IntBuiltinsTest, CompareLargeIntGt) {
1345 HandleScope scope(thread_);
1346
1347 Object a(&scope, runtime_->newInt(RawSmallInt::kMaxValue + 1));
1348 Object b(&scope, runtime_->newInt(RawSmallInt::kMinValue - 1));
1349 Object zero(&scope, SmallInt::fromWord(0));
1350 ASSERT_TRUE(a.isLargeInt());
1351 ASSERT_TRUE(b.isLargeInt());
1352
1353 Object cmp_1(&scope, runBuiltin(METH(int, __gt__), a, b));
1354 ASSERT_TRUE(cmp_1.isBool());
1355 EXPECT_EQ(*cmp_1, Bool::trueObj());
1356
1357 Object cmp_2(&scope, runBuiltin(METH(int, __gt__), a, zero));
1358 ASSERT_TRUE(cmp_2.isBool());
1359 EXPECT_EQ(*cmp_2, Bool::trueObj());
1360
1361 Object cmp_3(&scope, runBuiltin(METH(int, __gt__), a, a));
1362 ASSERT_TRUE(cmp_3.isBool());
1363 EXPECT_EQ(*cmp_3, Bool::falseObj());
1364
1365 Object cmp_4(&scope, runBuiltin(METH(int, __gt__), b, a));
1366 ASSERT_TRUE(cmp_4.isBool());
1367 EXPECT_EQ(*cmp_4, Bool::falseObj());
1368
1369 Object cmp_5(&scope, runBuiltin(METH(int, __gt__), b, zero));
1370 ASSERT_TRUE(cmp_5.isBool());
1371 EXPECT_EQ(*cmp_5, Bool::falseObj());
1372
1373 Object cmp_6(&scope, runBuiltin(METH(int, __gt__), b, b));
1374 ASSERT_TRUE(cmp_6.isBool());
1375 EXPECT_EQ(*cmp_6, Bool::falseObj());
1376}
1377
1378TEST_F(IntBuiltinsTest, CompareLargeIntLt) {
1379 HandleScope scope(thread_);
1380
1381 Object a(&scope, runtime_->newInt(RawSmallInt::kMaxValue + 1));
1382 Object b(&scope, runtime_->newInt(RawSmallInt::kMinValue - 1));
1383 Object zero(&scope, SmallInt::fromWord(0));
1384 ASSERT_TRUE(a.isLargeInt());
1385 ASSERT_TRUE(b.isLargeInt());
1386
1387 Object cmp_1(&scope, runBuiltin(METH(int, __lt__), a, b));
1388 ASSERT_TRUE(cmp_1.isBool());
1389 EXPECT_EQ(*cmp_1, Bool::falseObj());
1390
1391 Object cmp_2(&scope, runBuiltin(METH(int, __lt__), a, zero));
1392 ASSERT_TRUE(cmp_2.isBool());
1393 EXPECT_EQ(*cmp_2, Bool::falseObj());
1394
1395 Object cmp_3(&scope, runBuiltin(METH(int, __lt__), a, a));
1396 ASSERT_TRUE(cmp_3.isBool());
1397 EXPECT_EQ(*cmp_3, Bool::falseObj());
1398
1399 Object cmp_4(&scope, runBuiltin(METH(int, __lt__), b, a));
1400 ASSERT_TRUE(cmp_4.isBool());
1401 EXPECT_EQ(*cmp_4, Bool::trueObj());
1402
1403 Object cmp_5(&scope, runBuiltin(METH(int, __lt__), b, zero));
1404 ASSERT_TRUE(cmp_5.isBool());
1405 EXPECT_EQ(*cmp_5, Bool::trueObj());
1406
1407 Object cmp_6(&scope, runBuiltin(METH(int, __lt__), b, b));
1408 ASSERT_TRUE(cmp_6.isBool());
1409 EXPECT_EQ(*cmp_6, Bool::falseObj());
1410}
1411
1412TEST_F(IntBuiltinsTest, DunderIndexAliasesDunderInt) {
1413 Thread* thread = Thread::current();
1414 HandleScope scope(thread);
1415 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
1416 Object index_name(&scope, Runtime::internStrFromCStr(thread_, "__index__"));
1417 Object index_obj(&scope, typeAt(type, index_name));
1418 ASSERT_TRUE(index_obj.isFunction());
1419 Function index(&scope, *index_obj);
1420 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
1421 Object dint_obj(&scope, typeAt(type, dint_name));
1422 ASSERT_TRUE(dint_obj.isFunction());
1423 Function dint(&scope, *index_obj);
1424 EXPECT_EQ(Code::cast(index.code()).code(), Code::cast(dint.code()).code());
1425 EXPECT_EQ(index.entry(), dint.entry());
1426 EXPECT_EQ(index.entryKw(), dint.entryKw());
1427 EXPECT_EQ(index.entryEx(), dint.entryEx());
1428}
1429
1430TEST_F(IntBuiltinsTest, DunderIntWithBoolFalseReturnsZero) {
1431 HandleScope scope(thread_);
1432
1433 Object self(&scope, Bool::falseObj());
1434 Object result(&scope, runBuiltin(METH(int, __int__), self));
1435 EXPECT_EQ(result, SmallInt::fromWord(0));
1436}
1437
1438TEST_F(IntBuiltinsTest, DunderIntWithBoolTrueReturnsOne) {
1439 HandleScope scope(thread_);
1440
1441 Object self(&scope, Bool::trueObj());
1442 Object result(&scope, runBuiltin(METH(int, __int__), self));
1443 EXPECT_EQ(result, SmallInt::fromWord(1));
1444}
1445
1446TEST_F(IntBuiltinsTest, DunderIntWithSmallIntReturnsSame) {
1447 HandleScope scope(thread_);
1448
1449 Object self(&scope, RawSmallInt::fromWord(7));
1450 Object result(&scope, runBuiltin(METH(int, __int__), self));
1451 EXPECT_EQ(self, result);
1452}
1453
1454TEST_F(IntBuiltinsTest, DunderIntReturnsSameValue) {
1455 HandleScope scope(thread_);
1456
1457 ASSERT_FALSE(runFromCStr(runtime_, R"(
1458a = (7).__int__()
1459b = int.__int__(7)
1460)")
1461 .isError());
1462 Object a(&scope, mainModuleAt(runtime_, "a"));
1463 Object b(&scope, mainModuleAt(runtime_, "b"));
1464 EXPECT_TRUE(isIntEqualsWord(*a, 7));
1465 EXPECT_TRUE(isIntEqualsWord(*b, 7));
1466
1467 Str str(&scope, runtime_->newStrFromCStr("python"));
1468 Object res(&scope, runBuiltin(METH(int, __int__), str));
1469 EXPECT_TRUE(res.isError());
1470}
1471
1472TEST_F(IntBuiltinsTest, DunderInvertWithBoolTrueReturnsSmallInt) {
1473 HandleScope scope(thread_);
1474 Object num(&scope, Bool::trueObj());
1475 Object result(&scope, runBuiltin(METH(int, __invert__), num));
1476 ASSERT_TRUE(result.isSmallInt());
1477 EXPECT_TRUE(isIntEqualsWord(*result, -2));
1478}
1479
1480TEST_F(IntBuiltinsTest, DunderInvertWithBoolFalseReturnsSmallInt) {
1481 HandleScope scope(thread_);
1482 Object num(&scope, Bool::falseObj());
1483 Object result(&scope, runBuiltin(METH(int, __invert__), num));
1484 ASSERT_TRUE(result.isSmallInt());
1485 EXPECT_TRUE(isIntEqualsWord(*result, -1));
1486}
1487
1488TEST_F(IntBuiltinsTest, DunderInvertWithSmallIntReturnsSmallInt) {
1489 HandleScope scope(thread_);
1490 Object num(&scope, SmallInt::fromWord(-224466));
1491 Object result(&scope, runBuiltin(METH(int, __invert__), num));
1492 ASSERT_TRUE(result.isSmallInt());
1493 EXPECT_TRUE(isIntEqualsWord(*result, 224465));
1494}
1495
1496TEST_F(IntBuiltinsTest, DunderInvertWithLargeIntReturnsLargeInt) {
1497 HandleScope scope(thread_);
1498 const uword num_digits[] = {0x6c5bfcb426758496, 0xda8bdbe69c009bc5, 0};
1499 Object num(&scope, runtime_->newLargeIntWithDigits(num_digits));
1500 Object result_obj(&scope, runBuiltin(METH(int, __invert__), num));
1501 ASSERT_TRUE(result_obj.isLargeInt());
1502 Int result(&scope, *result_obj);
1503 const uword expected_digits[] = {0x93a4034bd98a7b69, 0x2574241963ff643a,
1504 kMaxUword};
1505 Int expected(&scope, runtime_->newLargeIntWithDigits(expected_digits));
1506 EXPECT_EQ(expected.compare(*result), 0);
1507}
1508
1509TEST_F(IntBuiltinsTest, DunderBoolOnBool) {
1510 HandleScope scope(thread_);
1511
1512 Object true_obj(&scope, Bool::trueObj());
1513 EXPECT_EQ(runBuiltin(METH(int, __bool__), true_obj), Bool::trueObj());
1514
1515 Object false_obj(&scope, Bool::falseObj());
1516 EXPECT_EQ(runBuiltin(METH(int, __bool__), false_obj), Bool::falseObj());
1517}
1518
1519TEST_F(IntBuiltinsTest, DunderDivmodWithBoolsReturnsTuple) {
1520 HandleScope scope(thread_);
1521 Object left(&scope, Bool::trueObj());
1522 Object right(&scope, Bool::trueObj());
1523 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1524 ASSERT_TRUE(result_obj.isTuple());
1525 Tuple result(&scope, *result_obj);
1526 ASSERT_EQ(result.length(), 2);
1527 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1));
1528 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1529}
1530
1531TEST_F(IntBuiltinsTest, DunderDivmodWithSmallIntReturnsTuple) {
1532 HandleScope scope(thread_);
1533 Object left(&scope, RawSmallInt::fromWord(4321));
1534 Object right(&scope, RawSmallInt::fromWord(17));
1535 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1536 ASSERT_TRUE(result_obj.isTuple());
1537 Tuple result(&scope, *result_obj);
1538 ASSERT_EQ(result.length(), 2);
1539 EXPECT_TRUE(isIntEqualsWord(result.at(0), 254));
1540 EXPECT_TRUE(isIntEqualsWord(result.at(1), 3));
1541}
1542
1543TEST_F(IntBuiltinsTest,
1544 DunderDivmodWithSmallIntNegativeDividendNegativeDivisorReturnsTuple) {
1545 HandleScope scope(thread_);
1546 Object left(&scope, RawSmallInt::fromWord(-987654321));
1547 Object right(&scope, RawSmallInt::fromWord(-654));
1548 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1549 ASSERT_TRUE(result_obj.isTuple());
1550 Tuple result(&scope, *result_obj);
1551 ASSERT_EQ(result.length(), 2);
1552 EXPECT_TRUE(isIntEqualsWord(result.at(0), 1510174));
1553 EXPECT_TRUE(isIntEqualsWord(result.at(1), -525));
1554}
1555
1556TEST_F(IntBuiltinsTest, DunderDivmodWithSmallIntNegativeDividendReturnsTuple) {
1557 HandleScope scope(thread_);
1558 Object left(&scope, RawSmallInt::fromWord(-123456789));
1559 Object right(&scope, RawSmallInt::fromWord(456));
1560 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1561 ASSERT_TRUE(result_obj.isTuple());
1562 Tuple result(&scope, *result_obj);
1563 ASSERT_EQ(result.length(), 2);
1564 EXPECT_TRUE(isIntEqualsWord(result.at(0), -270739));
1565 EXPECT_TRUE(isIntEqualsWord(result.at(1), 195));
1566}
1567
1568TEST_F(IntBuiltinsTest,
1569 DunderDivmodWithSmallIntNegativeDividendNoRemainderReturnsTuple) {
1570 HandleScope scope(thread_);
1571 Object left(&scope, RawSmallInt::fromWord(-94222222181));
1572 Object right(&scope, RawSmallInt::fromWord(53));
1573 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1574 ASSERT_TRUE(result_obj.isTuple());
1575 Tuple result(&scope, *result_obj);
1576 ASSERT_EQ(result.length(), 2);
1577 EXPECT_TRUE(isIntEqualsWord(result.at(0), -1777777777));
1578 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1579}
1580
1581TEST_F(IntBuiltinsTest, DunderDivmodWithSmallIntNegativeDivisorReturnsTuple) {
1582 HandleScope scope(thread_);
1583 Object left(&scope, RawSmallInt::fromWord(111222333));
1584 Object right(&scope, RawSmallInt::fromWord(-444));
1585 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1586 ASSERT_TRUE(result_obj.isTuple());
1587 Tuple result(&scope, *result_obj);
1588 ASSERT_EQ(result.length(), 2);
1589 EXPECT_TRUE(isIntEqualsWord(result.at(0), -250501));
1590 EXPECT_TRUE(isIntEqualsWord(result.at(1), -111));
1591}
1592
1593TEST_F(IntBuiltinsTest,
1594 DunderDivmodWithSmallIntNegativeDivisorNoRemainderReturnsTuple) {
1595 HandleScope scope(thread_);
1596 Object left(&scope, RawSmallInt::fromWord(94222222181));
1597 Object right(&scope, RawSmallInt::fromWord(-53));
1598 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1599 ASSERT_TRUE(result_obj.isTuple());
1600 Tuple result(&scope, *result_obj);
1601 ASSERT_EQ(result.length(), 2);
1602 EXPECT_TRUE(isIntEqualsWord(result.at(0), -1777777777));
1603 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1604}
1605
1606TEST_F(IntBuiltinsTest,
1607 DunderDivmodWithSmallIntAndDivisorMinusOneReturnsTuple) {
1608 HandleScope scope(thread_);
1609 Object left(&scope, runtime_->newInt(kMinWord));
1610 Object right(&scope, runtime_->newInt(-1));
1611 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1612 ASSERT_TRUE(result_obj.isTuple());
1613 Tuple result(&scope, *result_obj);
1614 ASSERT_EQ(result.length(), 2);
1615 const uword expected_digits[] = {kHighbitUword, 0};
1616 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1617 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1618}
1619
1620TEST_F(IntBuiltinsTest,
1621 DunderDivmodWithLargeIntAndDivisorMinusOneReturnsTuple) {
1622 HandleScope scope(thread_);
1623 const uword digits[] = {0, kHighbitUword};
1624 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1625 Object right(&scope, runtime_->newInt(-1));
1626 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1627 ASSERT_TRUE(result_obj.isTuple());
1628 Tuple result(&scope, *result_obj);
1629 ASSERT_EQ(result.length(), 2);
1630 const uword expected_digits[] = {0, kHighbitUword, 0};
1631 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1632 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1633}
1634
1635TEST_F(IntBuiltinsTest, DunderDivmodWithSingleDigitDivisorReturnsTuple) {
1636 HandleScope scope(thread_);
1637 const uword digits[] = {0x4a23475557e990d0, 0x56c1275a8b41bed9};
1638 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1639 Object right(&scope, runtime_->newInt(77));
1640 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1641 ASSERT_TRUE(result_obj.isTuple());
1642 Tuple result(&scope, *result_obj);
1643 ASSERT_EQ(result.length(), 2);
1644 const uword expected_digits[] = {0x79cb7c896c08a31, 0x1206e39b2042db3};
1645 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1646 EXPECT_TRUE(isIntEqualsWord(result.at(1), 19));
1647}
1648
1649TEST_F(IntBuiltinsTest, DunderDivmodWithBoolDivisorReturnsTuple) {
1650 HandleScope scope(thread_);
1651 const uword digits[] = {0x4a23475557e990d0, 0x56c1275a8b41bed9};
1652 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1653 Object right(&scope, Bool::trueObj());
1654 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1655 ASSERT_TRUE(result_obj.isTuple());
1656 Tuple result(&scope, *result_obj);
1657 ASSERT_EQ(result.length(), 2);
1658 const uword expected_digits[] = {0x4a23475557e990d0, 0x56c1275a8b41bed9};
1659 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1660 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1661}
1662
1663TEST_F(IntBuiltinsTest,
1664 DunderDivmodWithSingleDigitNegativeDivisorReturnsTuple) {
1665 HandleScope scope(thread_);
1666 const uword digits[] = {0x6d73444a30629c55, 0x2c4ab2d4de16e2ef};
1667 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1668 Object right(&scope, runtime_->newInt(-87654));
1669 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1670 ASSERT_TRUE(result_obj.isTuple());
1671 Tuple result(&scope, *result_obj);
1672 ASSERT_EQ(result.length(), 2);
1673 const uword expected_digits[] = {0x334af489352d60f6, 0xffffdee26dff7ad9};
1674 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1675 EXPECT_TRUE(isIntEqualsWord(result.at(1), -7591));
1676}
1677
1678TEST_F(IntBuiltinsTest,
1679 DunderDivmodWithSingleDigitNegativeDivisorNoRemainderReturnsTuple) {
1680 HandleScope scope(thread_);
1681 const uword digits[] = {0x6d73444a30629c55, 0x2c4ab2d4de16e2ef};
1682 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1683 Object right(&scope, runtime_->newInt(-5));
1684 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1685 ASSERT_TRUE(result_obj.isTuple());
1686 Tuple result(&scope, *result_obj);
1687 ASSERT_EQ(result.length(), 2);
1688 const uword expected_digits[] = {0x83b5bf245cb913ef, 0xf72442a239fb6c36};
1689 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1690 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1691}
1692
1693TEST_F(IntBuiltinsTest,
1694 DunderDivmodWithSingleDigitDivisorNegativeDividendReturnsTuple) {
1695 HandleScope scope(thread_);
1696 const uword digits[] = {0x94472249c23c1189, 0xffe0519aab10d602};
1697 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1698 Object right(&scope, runtime_->newInt(12345));
1699 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1700 ASSERT_TRUE(result_obj.isTuple());
1701 Tuple result(&scope, *result_obj);
1702 ASSERT_EQ(result.length(), 2);
1703 const uword expected_digits[] = {0x5b96544c9be595f3, 0xffffff57d046e6d2};
1704 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1705 EXPECT_TRUE(isIntEqualsWord(result.at(1), 7790));
1706}
1707
1708TEST_F(
1709 IntBuiltinsTest,
1710 DunderDivmodWithSingleDigitDivisorNegativeDividendNoRemainderReturnsTuple) {
1711 HandleScope scope(thread_);
1712 const uword digits[] = {0x94472249c23c1189, 0xffe0519aab10d602};
1713 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1714 Object right(&scope, runtime_->newInt(5));
1715 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1716 ASSERT_TRUE(result_obj.isTuple());
1717 Tuple result(&scope, *result_obj);
1718 ASSERT_EQ(result.length(), 2);
1719 const uword expected_digits[] = {0x50db06db8d3f36b5, 0xfff9a9ebbbd02acd};
1720 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1721 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1722}
1723
1724TEST_F(IntBuiltinsTest,
1725 DunderDivmodWithSingleDigitNegativeDivisorNegativeDividendReturnsTuple) {
1726 HandleScope scope(thread_);
1727 const uword digits[] = {0x91a950df92c04492, 0xd60eebbadb89de2f};
1728 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1729 Object right(&scope, runtime_->newInt(-1117392329));
1730 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1731 ASSERT_TRUE(result_obj.isTuple());
1732 Tuple result(&scope, *result_obj);
1733 ASSERT_EQ(result.length(), 2);
1734 const uword expected_digits[] = {0x6aaebd022be4f5c, 0xa1368e9f};
1735 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1736 EXPECT_TRUE(isIntEqualsWord(result.at(1), -108249138));
1737}
1738
1739TEST_F(IntBuiltinsTest,
1740 DunderDivmodWithJustNotASingleDigitDivisorReturnsTuple) {
1741 HandleScope scope(thread_);
1742 const uword digits[] = {0xaaa, 3};
1743 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1744 Object right(&scope, runtime_->newInt(-0x100000000));
1745 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1746 ASSERT_TRUE(result_obj.isTuple());
1747 Tuple result(&scope, *result_obj);
1748 ASSERT_EQ(result.length(), 2);
1749 EXPECT_TRUE(isIntEqualsWord(result.at(0), -12884901889));
1750 EXPECT_TRUE(isIntEqualsWord(result.at(1), -4294964566));
1751}
1752
1753TEST_F(IntBuiltinsTest, DunderDivmodWithBiggerDivisorReturnsTuple) {
1754 HandleScope scope(thread_);
1755 const uword digits_left[] = {0x575420c5052ae9c6};
1756 Object left(&scope, runtime_->newLargeIntWithDigits(digits_left));
1757 const uword digits_right[] = {0x383b89d9e2bb74f5, 0x1234};
1758 Object right(&scope, runtime_->newLargeIntWithDigits(digits_right));
1759 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1760 ASSERT_TRUE(result_obj.isTuple());
1761 Tuple result(&scope, *result_obj);
1762 ASSERT_EQ(result.length(), 2);
1763 EXPECT_TRUE(isIntEqualsWord(result.at(0), 0));
1764 // The algorithm should take a shortcut and return the dividend unchanged.
1765 EXPECT_EQ(result.at(1), left);
1766}
1767
1768TEST_F(IntBuiltinsTest,
1769 DunderDivmodWithNegativeDividendBiggerDivisorReturnsTuple) {
1770 HandleScope scope(thread_);
1771 Object left(&scope, runtime_->newInt(-55));
1772 const uword digits[] = {0, 1};
1773 Object right(&scope, runtime_->newLargeIntWithDigits(digits));
1774 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1775 ASSERT_TRUE(result_obj.isTuple());
1776 Tuple result(&scope, *result_obj);
1777 ASSERT_EQ(result.length(), 2);
1778 EXPECT_TRUE(isIntEqualsWord(result.at(0), -1));
1779 const uword expected_digits[] = {~uword{54}, 0};
1780 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits));
1781}
1782
1783TEST_F(IntBuiltinsTest,
1784 DunderDivmodWithDividendBiggerNegativeDivisorReturnsTuple) {
1785 HandleScope scope(thread_);
1786 Object left(&scope, runtime_->newInt(55));
1787 const uword digits[] = {0, kHighbitUword};
1788 Object right(&scope, runtime_->newLargeIntWithDigits(digits));
1789 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1790 ASSERT_TRUE(result_obj.isTuple());
1791 Tuple result(&scope, *result_obj);
1792 ASSERT_EQ(result.length(), 2);
1793 EXPECT_TRUE(isIntEqualsWord(result.at(0), -1));
1794 const uword expected_digits[] = {55, kHighbitUword};
1795 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits));
1796}
1797
1798TEST_F(IntBuiltinsTest,
1799 DunderDivmodWithNegativeDividendBiggerNegativeDivisorReturnsTuple) {
1800 HandleScope scope(thread_);
1801 Object left(&scope, runtime_->newInt(-55));
1802 const uword digits[] = {0, kMaxUword};
1803 Object right(&scope, runtime_->newLargeIntWithDigits(digits));
1804 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1805 ASSERT_TRUE(result_obj.isTuple());
1806 Tuple result(&scope, *result_obj);
1807 ASSERT_EQ(result.length(), 2);
1808 EXPECT_TRUE(isIntEqualsWord(result.at(0), 0));
1809 EXPECT_TRUE(isIntEqualsWord(result.at(1), -55));
1810}
1811
1812TEST_F(IntBuiltinsTest, DunderDivmodWithLargeIntReturnsTuple) {
1813 HandleScope scope(thread_);
1814 const uword digits_left[] = {0x383b89d9e2bb74f5, 0x410f8dceb8660505,
1815 0x383b1ab8d7938f4b, 0x87108b9b45b43d};
1816 Object left(&scope, runtime_->newLargeIntWithDigits(digits_left));
1817 const uword digits_right[] = {0x975420c5052ae9c6, 0x3bcd71afac71b2e4};
1818 Object right(&scope, runtime_->newLargeIntWithDigits(digits_right));
1819 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1820 ASSERT_TRUE(result_obj.isTuple());
1821 Tuple result(&scope, *result_obj);
1822 ASSERT_EQ(result.length(), 2);
1823 const uword expected_digits1[] = {0x4015dc39ddfb7863, 0x2422dc41b36a89e};
1824 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits1));
1825 const uword expected_digits2[] = {0x58023143a26c3d63, 0x290c5dcb84cbb46f};
1826 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits2));
1827}
1828
1829TEST_F(IntBuiltinsTest, DunderDivmodWithLargeIntPowerOfTwoReturnsTuple) {
1830 HandleScope scope(thread_);
1831 const uword digits_left[] = {0xee31ba892c71000e, 0x7175d128f7c2574a};
1832 Object left(&scope, runtime_->newLargeIntWithDigits(digits_left));
1833 const uword digits_right[] = {0, 1};
1834 Object right(&scope, runtime_->newLargeIntWithDigits(digits_right));
1835 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1836 ASSERT_TRUE(result_obj.isTuple());
1837 Tuple result(&scope, *result_obj);
1838 ASSERT_EQ(result.length(), 2);
1839 EXPECT_TRUE(isIntEqualsWord(result.at(0), 0x7175d128f7c2574a));
1840 const uword expected_digits[] = {0xee31ba892c71000e, 0};
1841 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits));
1842}
1843
1844TEST_F(IntBuiltinsTest,
1845 DunderDivmodWithZeroDividendBiggerNegativeDivisorReturnsTuple) {
1846 HandleScope scope(thread_);
1847 Object left(&scope, runtime_->newInt(0));
1848 const uword digits[] = {0, 1};
1849 Object right(&scope, runtime_->newLargeIntWithDigits(digits));
1850 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1851 ASSERT_TRUE(result_obj.isTuple());
1852 Tuple result(&scope, *result_obj);
1853 ASSERT_EQ(result.length(), 2);
1854 EXPECT_TRUE(isIntEqualsWord(result.at(0), 0));
1855 EXPECT_TRUE(isIntEqualsWord(result.at(1), 0));
1856}
1857
1858TEST_F(IntBuiltinsTest, DunderDivmodWithLargeIntNegativeDividendReturnsTuple) {
1859 HandleScope scope(thread_);
1860 const uword digits_left[] = {0x72a8be6d697d55c0, 0x9d95978dc878d9ae,
1861 0xae86bef7900edb79};
1862 Object left(&scope, runtime_->newLargeIntWithDigits(digits_left));
1863 const uword digits_right[] = {0x9893b50147995ab1, 0x73537a3bc36c3a0e};
1864 Object right(&scope, runtime_->newLargeIntWithDigits(digits_right));
1865 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1866 ASSERT_TRUE(result_obj.isTuple());
1867 Tuple result(&scope, *result_obj);
1868 ASSERT_EQ(result.length(), 2);
1869 const uword expected_digits1[] = {0x4b2538374030ad53, 0xffffffffffffffff};
1870 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits1));
1871 const uword expected_digits2[] = {0x2f13a2c4f4b515d, 0x38ab976c676089ea};
1872 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits2));
1873}
1874
1875TEST_F(IntBuiltinsTest, DunderDivmodWithLargeIntNegativeDivisorReturnsTuple) {
1876 HandleScope scope(thread_);
1877 const uword digits_left[] = {0x11000235a5b61b48, 0x54cb34ee1cde8d78,
1878 0x2ac801d0ae5dcf65};
1879 Object left(&scope, runtime_->newLargeIntWithDigits(digits_left));
1880 const uword digits_right[] = {0xfb2879c8be1e7dda, 0xf8101cf6608d0f6a};
1881 Object right(&scope, runtime_->newLargeIntWithDigits(digits_right));
1882 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1883 ASSERT_TRUE(result_obj.isTuple());
1884 Tuple result(&scope, *result_obj);
1885 ASSERT_EQ(result.length(), 2);
1886 const uword expected_digits1[] = {0x9c248b8175e4f19f, 0xfffffffffffffffa};
1887 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits1));
1888 const uword expected_digits2[] = {0xdc2e58062423b6e2, 0xfa5dd4db30c9589e};
1889 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits2));
1890}
1891
1892TEST_F(IntBuiltinsTest,
1893 DunderDivmodWithLargeIntNegativeDividendNegativeDivisorReturnsTuple) {
1894 HandleScope scope(thread_);
1895 const uword digits_left[] = {0xc4b749b3bc2eb7e0, 0x74e4cc72dc8a2e9b,
1896 0x46bb00bd468a1799, 0xc29ae4e0ae05134};
1897 Object left(&scope, runtime_->newLargeIntWithDigits(digits_left));
1898 const uword digits_right[] = {0x839c30dba1685693, 0xad0140cf78eaee70,
1899 0xd77ec3cef0613585};
1900 Object right(&scope, runtime_->newLargeIntWithDigits(digits_right));
1901 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1902 ASSERT_TRUE(result_obj.isTuple());
1903 Tuple result(&scope, *result_obj);
1904 ASSERT_EQ(result.length(), 2);
1905 const uword expected_digits1[] = {0xb320ce53675ba5b0};
1906 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits1));
1907 const uword expected_digits2[] = {0xfbf66d17996573d0, 0xfb57b237e188be27,
1908 0xe9d7473ac0f6b873};
1909 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits2));
1910}
1911
1912TEST_F(IntBuiltinsTest,
1913 DunderDivmodWithLargeIntTriggeringNegateBugReturnsTuple) {
1914 HandleScope scope(thread_);
1915 const uword digits[] = {1, 0, 1};
1916 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
1917 Object right(&scope, runtime_->newInt(-5));
1918 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1919 ASSERT_TRUE(result_obj.isTuple());
1920 Tuple result(&scope, *result_obj);
1921 ASSERT_EQ(result.length(), 2);
1922 const uword expected_digits[] = {0xcccccccccccccccc, 0xcccccccccccccccc};
1923 EXPECT_TRUE(isIntEqualsDigits(result.at(0), expected_digits));
1924 EXPECT_TRUE(isIntEqualsWord(result.at(1), -3));
1925}
1926
1927TEST_F(IntBuiltinsTest, DunderDivmodReturnsMinWordPlusOneModulo) {
1928 HandleScope scope(thread_);
1929 const uword left_digits[] = {1, 1};
1930 Object left(&scope, runtime_->newLargeIntWithDigits(left_digits));
1931 const uword right_digits[] = {static_cast<uword>(kMinWord)};
1932 Object right(&scope, runtime_->newLargeIntWithDigits(right_digits));
1933 Object result_obj(&scope, runBuiltin(METH(int, __divmod__), left, right));
1934 ASSERT_TRUE(result_obj.isTuple());
1935 Tuple result(&scope, *result_obj);
1936 ASSERT_EQ(result.length(), 2);
1937 EXPECT_TRUE(isIntEqualsWord(result.at(0), -3));
1938 const uword expected_digits[] = {static_cast<uword>(kMinWord) + 1};
1939 EXPECT_TRUE(isIntEqualsDigits(result.at(1), expected_digits));
1940}
1941
1942TEST_F(IntBuiltinsTest, DunderDivmodWithZeroRaisesZeroDivisionError) {
1943 HandleScope scope(thread_);
1944 Object left(&scope, runtime_->newInt(2));
1945 Object right(&scope, runtime_->newInt(0));
1946 Object result(&scope, runBuiltin(METH(int, __divmod__), left, right));
1947 EXPECT_TRUE(raisedWithStr(*result, LayoutId::kZeroDivisionError,
1948 "integer division or modulo by zero"));
1949}
1950
1951TEST_F(IntBuiltinsTest, DunderDivmodWithNonIntSelfRaisesTypeError) {
1952 HandleScope scope(thread_);
1953 Object left(&scope, Str::empty());
1954 Object right(&scope, runtime_->newInt(1));
1955 Object result(&scope, runBuiltin(METH(int, __divmod__), left, right));
1956 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
1957}
1958
1959TEST_F(IntBuiltinsTest, DunderDivmodWithNontIntReturnsNotImplemented) {
1960 HandleScope scope(thread_);
1961 Object left(&scope, runtime_->newInt(1));
1962 Object right(&scope, Str::empty());
1963 Object result(&scope, runBuiltin(METH(int, __divmod__), left, right));
1964 EXPECT_TRUE(result.isNotImplementedType());
1965}
1966
1967TEST_F(IntBuiltinsTest, DunderEqOnBool) {
1968 HandleScope scope(thread_);
1969
1970 Object true_obj(&scope, Bool::trueObj());
1971 EXPECT_EQ(runBuiltin(METH(int, __eq__), true_obj, true_obj), Bool::trueObj());
1972
1973 Object false_obj(&scope, Bool::falseObj());
1974 EXPECT_EQ(runBuiltin(METH(int, __eq__), true_obj, false_obj),
1975 Bool::falseObj());
1976
1977 Object zero(&scope, SmallInt::fromWord(0));
1978 EXPECT_EQ(runBuiltin(METH(int, __eq__), true_obj, zero), Bool::falseObj());
1979
1980 Object one(&scope, SmallInt::fromWord(1));
1981 EXPECT_EQ(runBuiltin(METH(int, __eq__), true_obj, one), Bool::trueObj());
1982}
1983
1984TEST_F(IntBuiltinsTest, DunderNeOnBool) {
1985 HandleScope scope(thread_);
1986
1987 Object true_obj(&scope, Bool::trueObj());
1988 EXPECT_EQ(runBuiltin(METH(int, __ne__), true_obj, true_obj),
1989 Bool::falseObj());
1990
1991 Object false_obj(&scope, Bool::falseObj());
1992 EXPECT_EQ(runBuiltin(METH(int, __ne__), true_obj, false_obj),
1993 Bool::trueObj());
1994
1995 Object zero(&scope, SmallInt::fromWord(0));
1996 EXPECT_EQ(runBuiltin(METH(int, __ne__), true_obj, zero), Bool::trueObj());
1997
1998 Object one(&scope, SmallInt::fromWord(1));
1999 EXPECT_EQ(runBuiltin(METH(int, __ne__), true_obj, one), Bool::falseObj());
2000}
2001
2002TEST_F(IntBuiltinsTest, DunderNegWithSmallIntReturnsSmallInt) {
2003 HandleScope scope(thread_);
2004 Object num(&scope, runtime_->newInt(42));
2005 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2006 EXPECT_TRUE(isIntEqualsWord(*result, -42));
2007}
2008
2009TEST_F(IntBuiltinsTest, DunderNegWithSmallIntReturnsLargeInt) {
2010 HandleScope scope(thread_);
2011 Object num(&scope, runtime_->newInt(RawSmallInt::kMinValue));
2012 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2013 EXPECT_TRUE(isIntEqualsWord(*result, -RawSmallInt::kMinValue));
2014}
2015
2016TEST_F(IntBuiltinsTest, DunderNegWithBoolFalseReturnsSmallInt) {
2017 HandleScope scope(thread_);
2018 Object value(&scope, Bool::falseObj());
2019 Object result(&scope, runBuiltin(METH(int, __neg__), value));
2020 EXPECT_TRUE(isIntEqualsWord(*result, 0));
2021}
2022
2023TEST_F(IntBuiltinsTest, DunderNegWithBoolTrueReturnsSmallInt) {
2024 HandleScope scope(thread_);
2025 Object value(&scope, Bool::trueObj());
2026 Object result(&scope, runBuiltin(METH(int, __neg__), value));
2027 EXPECT_TRUE(isIntEqualsWord(*result, -1));
2028}
2029
2030TEST_F(IntBuiltinsTest, DunderNegWithLargeIntReturnsSmallInt) {
2031 HandleScope scope(thread_);
2032 Object num(&scope, runtime_->newInt(-RawSmallInt::kMinValue));
2033 EXPECT_TRUE(num.isLargeInt());
2034 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2035 EXPECT_TRUE(isIntEqualsWord(*result, RawSmallInt::kMinValue));
2036}
2037
2038TEST_F(IntBuiltinsTest, DunderNegWithLargeIntReturnsLargeInt) {
2039 HandleScope scope(thread_);
2040 const uword digits[] = {0xad7721b1763aff22, 0x2afce48517f151b2};
2041 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2042 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2043 const uword expected_digits[] = {0x5288de4e89c500de, 0xd5031b7ae80eae4d};
2044 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2045}
2046
2047TEST_F(IntBuiltinsTest, DunderNegWithLargeIntCarriesReturnsLargeInt) {
2048 HandleScope scope(thread_);
2049 const uword digits[] = {0, 0xfffffff000000000};
2050 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2051 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2052 const uword expected_digits[] = {0, 0x1000000000};
2053 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2054}
2055
2056TEST_F(IntBuiltinsTest, DunderNegWithLargeIntOverflowsReturnsLargeInt) {
2057 HandleScope scope(thread_);
2058 const uword digits[] = {0, kHighbitUword};
2059 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2060 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2061 const uword expected_digits[] = {0, kHighbitUword, 0};
2062 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2063}
2064
2065TEST_F(IntBuiltinsTest, DunderNegWithLargeIntShrinksReturnsLargeInt) {
2066 HandleScope scope(thread_);
2067 const uword digits[] = {kHighbitUword, 0};
2068 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2069 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2070 const uword expected_digits[] = {kHighbitUword};
2071 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2072}
2073
2074TEST_F(IntBuiltinsTest, DunderNegWithLargeIntNoShrinksReturnsLargeInt) {
2075 HandleScope scope(thread_);
2076 const uword digits[] = {1, kHighbitUword, 0};
2077 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2078 Object result(&scope, runBuiltin(METH(int, __neg__), num));
2079 const uword expected_digits[] = {kMaxUword, kHighbitUword - 1, kMaxUword};
2080 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2081}
2082
2083TEST_F(IntBuiltinsTest, DunderPosAliasesDunderInt) {
2084 Thread* thread = Thread::current();
2085 HandleScope scope(thread);
2086 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
2087 Object pos_name(&scope, Runtime::internStrFromCStr(thread_, "__pos__"));
2088 Object pos_obj(&scope, typeAt(type, pos_name));
2089 ASSERT_TRUE(pos_obj.isFunction());
2090 Function pos(&scope, *pos_obj);
2091 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
2092 Object dint_obj(&scope, typeAt(type, dint_name));
2093 ASSERT_TRUE(dint_obj.isFunction());
2094 Function dint(&scope, *pos_obj);
2095 EXPECT_EQ(Code::cast(pos.code()).code(), Code::cast(dint.code()).code());
2096 EXPECT_EQ(pos.entry(), dint.entry());
2097 EXPECT_EQ(pos.entryKw(), dint.entryKw());
2098 EXPECT_EQ(pos.entryEx(), dint.entryEx());
2099}
2100
2101TEST_F(IntBuiltinsTest, DunderLtOnBool) {
2102 HandleScope scope(thread_);
2103
2104 Object true_obj(&scope, Bool::trueObj());
2105 Object false_obj(&scope, Bool::falseObj());
2106 EXPECT_EQ(runBuiltin(METH(int, __lt__), true_obj, false_obj),
2107 Bool::falseObj());
2108 EXPECT_EQ(runBuiltin(METH(int, __lt__), false_obj, true_obj),
2109 Bool::trueObj());
2110
2111 Object one(&scope, SmallInt::fromWord(1));
2112 EXPECT_EQ(runBuiltin(METH(int, __lt__), false_obj, one), Bool::trueObj());
2113
2114 Object minus_one(&scope, SmallInt::fromWord(-1));
2115 EXPECT_EQ(runBuiltin(METH(int, __lt__), false_obj, minus_one),
2116 Bool::falseObj());
2117}
2118
2119TEST_F(IntBuiltinsTest, DunderGeOnBool) {
2120 HandleScope scope(thread_);
2121
2122 Object true_obj(&scope, Bool::trueObj());
2123 Object false_obj(&scope, Bool::falseObj());
2124 EXPECT_EQ(runBuiltin(METH(int, __ge__), true_obj, false_obj),
2125 Bool::trueObj());
2126 EXPECT_EQ(runBuiltin(METH(int, __ge__), false_obj, true_obj),
2127 Bool::falseObj());
2128
2129 Object one(&scope, SmallInt::fromWord(1));
2130 EXPECT_EQ(runBuiltin(METH(int, __ge__), false_obj, one), Bool::falseObj());
2131
2132 Object minus_one(&scope, SmallInt::fromWord(-1));
2133 EXPECT_EQ(runBuiltin(METH(int, __ge__), false_obj, minus_one),
2134 Bool::trueObj());
2135}
2136
2137TEST_F(IntBuiltinsTest, DunderGtOnBool) {
2138 HandleScope scope(thread_);
2139
2140 Object true_obj(&scope, Bool::trueObj());
2141 Object false_obj(&scope, Bool::falseObj());
2142 EXPECT_EQ(runBuiltin(METH(int, __gt__), true_obj, false_obj),
2143 Bool::trueObj());
2144 EXPECT_EQ(runBuiltin(METH(int, __gt__), false_obj, true_obj),
2145 Bool::falseObj());
2146
2147 Object one(&scope, SmallInt::fromWord(1));
2148 EXPECT_EQ(runBuiltin(METH(int, __gt__), false_obj, one), Bool::falseObj());
2149
2150 Object minus_one(&scope, SmallInt::fromWord(-1));
2151 EXPECT_EQ(runBuiltin(METH(int, __gt__), false_obj, minus_one),
2152 Bool::trueObj());
2153}
2154
2155TEST_F(IntBuiltinsTest, DunderLeOnBool) {
2156 HandleScope scope(thread_);
2157
2158 Object true_obj(&scope, Bool::trueObj());
2159 Object false_obj(&scope, Bool::falseObj());
2160 EXPECT_EQ(runBuiltin(METH(int, __le__), true_obj, false_obj),
2161 Bool::falseObj());
2162 EXPECT_EQ(runBuiltin(METH(int, __le__), false_obj, true_obj),
2163 Bool::trueObj());
2164
2165 Object one(&scope, SmallInt::fromWord(1));
2166 EXPECT_EQ(runBuiltin(METH(int, __le__), false_obj, one), Bool::trueObj());
2167
2168 Object minus_one(&scope, SmallInt::fromWord(-1));
2169 EXPECT_EQ(runBuiltin(METH(int, __le__), false_obj, minus_one),
2170 Bool::falseObj());
2171}
2172
2173TEST_F(IntBuiltinsTest, DunderRoundAliasesDunderInt) {
2174 Thread* thread = Thread::current();
2175 HandleScope scope(thread);
2176 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
2177 Object round_name(&scope, Runtime::internStrFromCStr(thread_, "__round__"));
2178 Object round_obj(&scope, typeAt(type, round_name));
2179 ASSERT_TRUE(round_obj.isFunction());
2180 Function round(&scope, *round_obj);
2181 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
2182 Object dint_obj(&scope, typeAt(type, dint_name));
2183 ASSERT_TRUE(dint_obj.isFunction());
2184 Function dint(&scope, *round_obj);
2185 EXPECT_EQ(Code::cast(round.code()).code(), Code::cast(dint.code()).code());
2186 EXPECT_EQ(round.entry(), dint.entry());
2187 EXPECT_EQ(round.entryKw(), dint.entryKw());
2188 EXPECT_EQ(round.entryEx(), dint.entryEx());
2189}
2190
2191TEST_F(IntBuiltinsTest, DunderTruncAliasesDunderInt) {
2192 HandleScope scope(thread_);
2193 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
2194 Object trunc_name(&scope, Runtime::internStrFromCStr(thread_, "__trunc__"));
2195 Object trunc_obj(&scope, typeAt(type, trunc_name));
2196 ASSERT_TRUE(trunc_obj.isFunction());
2197 Function trunc(&scope, *trunc_obj);
2198 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
2199 Object dint_obj(&scope, typeAt(type, dint_name));
2200 ASSERT_TRUE(dint_obj.isFunction());
2201 Function dint(&scope, *trunc_obj);
2202 EXPECT_EQ(Code::cast(trunc.code()).code(), Code::cast(dint.code()).code());
2203 EXPECT_EQ(trunc.entry(), dint.entry());
2204 EXPECT_EQ(trunc.entryKw(), dint.entryKw());
2205 EXPECT_EQ(trunc.entryEx(), dint.entryEx());
2206}
2207
2208TEST_F(IntBuiltinsTest, FromBytesWithLittleEndianReturnsLargeInt) {
2209 HandleScope scope(thread_);
2210 ASSERT_FALSE(
2211 runFromCStr(runtime_, "result = int.__radd__(True, 41)").isError());
2212 Object result(&scope, mainModuleAt(runtime_, "result"));
2213 EXPECT_TRUE(isIntEqualsWord(*result, 42));
2214}
2215
2216TEST_F(IntBuiltinsTest, DunderRandWithSmallIntsReturnsSmallInt) {
2217 HandleScope scope(thread_);
2218 ASSERT_FALSE(
2219 runFromCStr(runtime_, "result = int.__rand__(0x123456789, 0x987654321)")
2220 .isError());
2221 Object result(&scope, mainModuleAt(runtime_, "result"));
2222 EXPECT_TRUE(isIntEqualsWord(*result, 0x103454301));
2223}
2224
2225TEST_F(IntBuiltinsTest, DunderReprWithZeroReturnsStr) {
2226 HandleScope scope(thread_);
2227 Object num(&scope, runtime_->newInt(0));
2228 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2229 EXPECT_TRUE(isStrEqualsCStr(*result, "0"));
2230}
2231
2232TEST_F(IntBuiltinsTest, DunderReprWithSmallIntReturnsStr) {
2233 HandleScope scope(thread_);
2234 Object num(&scope, runtime_->newInt(0xdeadbeef));
2235 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2236 EXPECT_TRUE(isStrEqualsCStr(*result, "3735928559"));
2237}
2238
2239TEST_F(IntBuiltinsTest, DunderReprWithSmallIntMaxReturnsStr) {
2240 HandleScope scope(thread_);
2241 Object num(&scope, runtime_->newInt(RawSmallInt::kMaxValue));
2242 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2243 EXPECT_TRUE(isStrEqualsCStr(*result, "4611686018427387903"));
2244}
2245
2246TEST_F(IntBuiltinsTest, DunderReprWithSmallIntMinReturnsStr) {
2247 HandleScope scope(thread_);
2248 Object num(&scope, runtime_->newInt(RawSmallInt::kMinValue));
2249 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2250 EXPECT_TRUE(isStrEqualsCStr(*result, "-4611686018427387904"));
2251}
2252
2253TEST_F(IntBuiltinsTest, DunderReprWithBoolFalseReturnsStr) {
2254 HandleScope scope(thread_);
2255 Object num(&scope, Bool::falseObj());
2256 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2257 EXPECT_TRUE(isStrEqualsCStr(*result, "0"));
2258}
2259
2260TEST_F(IntBuiltinsTest, DunderReprWithBoolTrueReturnsStr) {
2261 HandleScope scope(thread_);
2262 Object num(&scope, Bool::trueObj());
2263 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2264 EXPECT_TRUE(isStrEqualsCStr(*result, "1"));
2265}
2266
2267TEST_F(IntBuiltinsTest, DunderReprWithLargeIntOneDigitReturnsStr) {
2268 HandleScope scope(thread_);
2269 const uword digits[] = {0x7ab65f95e6775822};
2270 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2271 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2272 EXPECT_TRUE(isStrEqualsCStr(*result, "8842360015809894434"));
2273}
2274
2275TEST_F(IntBuiltinsTest, DunderReprWithLargeIntOneDigitMinReturnsStr) {
2276 HandleScope scope(thread_);
2277 const uword digits[] = {0x8000000000000000};
2278 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2279 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2280 EXPECT_TRUE(isStrEqualsCStr(*result, "-9223372036854775808"));
2281}
2282
2283TEST_F(IntBuiltinsTest, DunderReprWithLargeIntOneDigitMaxReturnsStr) {
2284 HandleScope scope(thread_);
2285 const uword digits[] = {0x7fffffffffffffff};
2286 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2287 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2288 EXPECT_TRUE(isStrEqualsCStr(*result, "9223372036854775807"));
2289}
2290
2291TEST_F(IntBuiltinsTest, DunderReprWithLargeIntReturnsStr) {
2292 HandleScope scope(thread_);
2293
2294 const uword digits[] = {0x68ccbb7f61087fb7, 0x4081e2972fe52778};
2295 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2296 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2297 EXPECT_TRUE(
2298 isStrEqualsCStr(*result, "85744993827831399429103580491677204407"));
2299}
2300
2301TEST_F(IntBuiltinsTest, DunderReprWithNegativeLargeIntReturnsStr) {
2302 HandleScope scope(thread_);
2303
2304 const uword digits[] = {0x49618108301eff93, 0xc70a0c6e0731da35,
2305 0x438a2278e8762294, 0xccf89b106c9b714d,
2306 0xfa694d4cbdf0b0ba};
2307 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2308 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2309 EXPECT_TRUE(
2310 isStrEqualsCStr(*result,
2311 "-4663013431296140509759060231428418933437027788588076073"
2312 "3669209802197774863968523736917349564525"));
2313}
2314
2315TEST_F(IntBuiltinsTest, DunderReprWithLargeIntManyZerosReturnsStr) {
2316 HandleScope scope(thread_);
2317
2318 const uword digits[] = {0x6ea69b2000000000, 0xf374ff2873cd99de, 0x375c24};
2319 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2320 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2321 EXPECT_TRUE(isStrEqualsCStr(
2322 *result, "1234567890000000000000000000000000000000000000"));
2323}
2324
2325TEST_F(IntBuiltinsTest, DunderReprWithLargeIntCarriesReturnsStr) {
2326 HandleScope scope(thread_);
2327 const uword digits[] = {kMaxUword, uword{kMaxWord}, kMaxUword};
2328 Object num(&scope, runtime_->newLargeIntWithDigits(digits));
2329 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2330 EXPECT_TRUE(
2331 isStrEqualsCStr(*result, "-170141183460469231731687303715884105729"));
2332}
2333
2334TEST_F(IntBuiltinsTest, DunderReprWithIntSubclassReturnsStr) {
2335 HandleScope scope(thread_);
2336 ASSERT_FALSE(runFromCStr(runtime_, R"(
2337class X(int): pass
2338num = X(0xdeadbeef)
2339)")
2340 .isError());
2341 Object num(&scope, mainModuleAt(runtime_, "num"));
2342 Object result(&scope, runBuiltin(METH(int, __repr__), num));
2343 EXPECT_TRUE(isStrEqualsCStr(*result, "3735928559"));
2344}
2345
2346TEST_F(IntBuiltinsTest, DunderRdivmodWithSmallIntsReturnsTuple) {
2347 HandleScope scope(thread_);
2348 ASSERT_FALSE(
2349 runFromCStr(runtime_, "result = int.__rdivmod__(3, 11)").isError());
2350 Object result_obj(&scope, mainModuleAt(runtime_, "result"));
2351 ASSERT_TRUE(result_obj.isTuple());
2352 Tuple result(&scope, *result_obj);
2353 ASSERT_EQ(result.length(), 2);
2354 EXPECT_TRUE(isIntEqualsWord(result.at(0), 3));
2355 EXPECT_TRUE(isIntEqualsWord(result.at(1), 2));
2356}
2357
2358TEST_F(IntBuiltinsTest, DunderRfloordivWithSmallIntsReturnsSmallInt) {
2359 HandleScope scope(thread_);
2360 ASSERT_FALSE(
2361 runFromCStr(runtime_, "result = int.__rfloordiv__(3, 11)").isError());
2362 Object result(&scope, mainModuleAt(runtime_, "result"));
2363 EXPECT_TRUE(isIntEqualsWord(*result, 3));
2364}
2365
2366TEST_F(IntBuiltinsTest, DunderRlshiftWithSmallIntsReturnsSmallInt) {
2367 HandleScope scope(thread_);
2368 ASSERT_FALSE(
2369 runFromCStr(runtime_, "result = int.__rlshift__(3, -7)").isError());
2370 Object result(&scope, mainModuleAt(runtime_, "result"));
2371 EXPECT_TRUE(isIntEqualsWord(*result, -56));
2372}
2373
2374TEST_F(IntBuiltinsTest, DunderRmodWithSmallIntsReturnsSmallInt) {
2375 HandleScope scope(thread_);
2376 ASSERT_FALSE(runFromCStr(runtime_, "result = int.__rmod__(3, 11)").isError());
2377 Object result(&scope, mainModuleAt(runtime_, "result"));
2378 EXPECT_TRUE(isIntEqualsWord(*result, 2));
2379}
2380
2381TEST_F(IntBuiltinsTest, DunderRmulWithSmallIntsReturnsSmallInt) {
2382 HandleScope scope(thread_);
2383 ASSERT_FALSE(
2384 runFromCStr(runtime_, "result = int.__rmul__(-321, 123)").isError());
2385 Object result(&scope, mainModuleAt(runtime_, "result"));
2386 EXPECT_TRUE(isIntEqualsWord(*result, -39483));
2387}
2388
2389TEST_F(IntBuiltinsTest, DunderRorWithSmallIntsReturnsSmallInt) {
2390 HandleScope scope(thread_);
2391 ASSERT_FALSE(
2392 runFromCStr(runtime_, "result = int.__ror__(0x123456789, 0x987654321)")
2393 .isError());
2394 Object result(&scope, mainModuleAt(runtime_, "result"));
2395 EXPECT_TRUE(isIntEqualsWord(*result, 0x9a76567a9));
2396}
2397
2398TEST_F(IntBuiltinsTest, DunderRpowWithSmallIntsReturnsSmallInt) {
2399 HandleScope scope(thread_);
2400 ASSERT_FALSE(runFromCStr(runtime_, "result = int.__rpow__(8, 2)").isError());
2401 Object result(&scope, mainModuleAt(runtime_, "result"));
2402 EXPECT_TRUE(isIntEqualsWord(*result, 256));
2403}
2404
2405TEST_F(IntBuiltinsTest, DunderRrshiftWithSmallIntsReturnsSmallInt) {
2406 HandleScope scope(thread_);
2407 ASSERT_FALSE(runFromCStr(runtime_, "result = int.__rrshift__(16, 0xf00ddead)")
2408 .isError());
2409 Object result(&scope, mainModuleAt(runtime_, "result"));
2410 EXPECT_TRUE(isIntEqualsWord(*result, 0xf00d));
2411}
2412
2413TEST_F(IntBuiltinsTest, DunderRshiftWithBoolsReturnsSmallInt) {
2414 HandleScope scope(thread_);
2415 Object left(&scope, Bool::trueObj());
2416 Object right(&scope, Bool::falseObj());
2417 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2418 EXPECT_TRUE(isIntEqualsWord(*result, 1));
2419}
2420
2421TEST_F(IntBuiltinsTest, DunderRshiftWithSmallIntsReturnsSmallInt) {
2422 HandleScope scope(thread_);
2423 Object left(&scope, runtime_->newInt(-1234));
2424 Object right(&scope, runtime_->newInt(3));
2425 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2426 EXPECT_TRUE(isIntEqualsWord(*result, -155));
2427}
2428
2429TEST_F(IntBuiltinsTest, DunderRshiftWithOversizedAmountSmallIntReturnsZero) {
2430 HandleScope scope(thread_);
2431 Object left(&scope, runtime_->newInt(1));
2432 Object right(&scope, runtime_->newInt(kBitsPerWord));
2433 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2434 EXPECT_TRUE(isIntEqualsWord(*result, 0));
2435}
2436
2437TEST_F(IntBuiltinsTest, DunderRshiftWithOversizedAmountLargeIntReturnsZero) {
2438 HandleScope scope(thread_);
2439 Object left(&scope, runtime_->newInt(1));
2440 const uword digits[] = {1, 2};
2441 Object right(&scope, runtime_->newLargeIntWithDigits(digits));
2442 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2443 EXPECT_TRUE(isIntEqualsWord(*result, 0));
2444}
2445
2446TEST_F(IntBuiltinsTest, DunderRshiftWithLargeIntOversizedAmountReturnsZero) {
2447 HandleScope scope(thread_);
2448 const uword digits[] = {1, 2};
2449 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
2450 Object right(&scope, runtime_->newInt(kBitsPerWord * 3));
2451 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2452 EXPECT_TRUE(isIntEqualsWord(*result, 0));
2453}
2454
2455TEST_F(IntBuiltinsTest, DunderRshiftWithLargeIntsReturnsLargeInt) {
2456 HandleScope scope(thread_);
2457 const uword digits[] = {0x188518dcaaa656f7, 0x7459da1092edebab,
2458 0x692e3b38af8dcfbe};
2459 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
2460 Object right(&scope, runtime_->newInt(83));
2461 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2462 const uword expected_digits[] = {0xb9f7ce8b3b42125d, 0xd25c76715f1};
2463 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2464}
2465
2466TEST_F(IntBuiltinsTest, DunderRshiftWithLargeIntWholeWordReturnsLargeInt) {
2467 HandleScope scope(thread_);
2468 const uword digits[] = {0x1c386fefbb1baf3d, 0x379bcaa886c98c13,
2469 0xe0f6379843f98b29, 0};
2470 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
2471 Object right(&scope, runtime_->newInt(kBitsPerWord * 2));
2472 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2473 const uword expected_digits[] = {0xe0f6379843f98b29, 0};
2474 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2475}
2476
2477TEST_F(IntBuiltinsTest, DunderRshiftWithLargeIntNegativeReturnsLargeInt) {
2478 HandleScope scope(thread_);
2479 const uword digits[] = {0x3190ff6fa83269bc, 0xe7a1689a33ca9ae6};
2480 Object left(&scope, runtime_->newLargeIntWithDigits(digits));
2481 Object right(&scope, runtime_->newInt(13));
2482 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2483 const uword expected_digits[] = {0xd7318c87fb7d4193, 0xffff3d0b44d19e54};
2484 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2485}
2486
2487TEST_F(IntBuiltinsTest, DunderRshiftWithNegativeShiftAmountRaisesValueError) {
2488 HandleScope scope(thread_);
2489 Object left(&scope, runtime_->newInt(1));
2490 Object right(&scope, runtime_->newInt(-4));
2491 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2492 EXPECT_TRUE(
2493 raisedWithStr(*result, LayoutId::kValueError, "negative shift count"));
2494}
2495
2496TEST_F(IntBuiltinsTest, DunderRshiftWithNonIntSelfRaisesTypeError) {
2497 HandleScope scope(thread_);
2498 Object left(&scope, Str::empty());
2499 Object right(&scope, runtime_->newInt(0));
2500 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2501 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
2502}
2503
2504TEST_F(IntBuiltinsTest, DunderRshiftWithNonIntReturnsNotImplemented) {
2505 HandleScope scope(thread_);
2506 Object left(&scope, runtime_->newInt(0));
2507 Object right(&scope, Str::empty());
2508 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2509 EXPECT_TRUE(result.isNotImplementedType());
2510}
2511
2512TEST_F(IntBuiltinsTest, DunderRshiftWithIntSubclassReturnsInt) {
2513 HandleScope scope(thread_);
2514 ASSERT_FALSE(runFromCStr(runtime_, R"(
2515class X(int): pass
2516left = X(-1234)
2517right = X(3)
2518)")
2519 .isError());
2520 Object left(&scope, mainModuleAt(runtime_, "left"));
2521 Object right(&scope, mainModuleAt(runtime_, "right"));
2522 Object result(&scope, runBuiltin(METH(int, __rshift__), left, right));
2523 EXPECT_EQ(result, SmallInt::fromWord(-155));
2524}
2525
2526TEST_F(IntBuiltinsTest, DunderStrAliasesDunderRepr) {
2527 Thread* thread = Thread::current();
2528 HandleScope scope(thread);
2529 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
2530 Object str_name(&scope, Runtime::internStrFromCStr(thread_, "__str__"));
2531 Object str_obj(&scope, typeAt(type, str_name));
2532 ASSERT_TRUE(str_obj.isFunction());
2533 Function str(&scope, *str_obj);
2534 Object repr_name(&scope, Runtime::internStrFromCStr(thread_, "__repr__"));
2535 Object repr_obj(&scope, typeAt(type, repr_name));
2536 ASSERT_TRUE(repr_obj.isFunction());
2537 Function repr(&scope, *str_obj);
2538 EXPECT_EQ(Code::cast(str.code()).code(), Code::cast(repr.code()).code());
2539 EXPECT_EQ(str.entry(), repr.entry());
2540 EXPECT_EQ(str.entryKw(), repr.entryKw());
2541 EXPECT_EQ(str.entryEx(), repr.entryEx());
2542}
2543
2544TEST_F(IntBuiltinsTest, DunderSubWithSmallIntsReturnsSmallInt) {
2545 HandleScope scope(thread_);
2546
2547 Int left(&scope, SmallInt::fromWord(42));
2548 Int right(&scope, SmallInt::fromWord(-7));
2549 Object result(&scope, runBuiltin(METH(int, __sub__), left, right));
2550 EXPECT_TRUE(isIntEqualsWord(*result, 49));
2551}
2552
2553TEST_F(IntBuiltinsTest, DunderSubWithSmallIntsOverflowReturnsLargeInt) {
2554 HandleScope scope(thread_);
2555
2556 Int min_small_int(&scope, SmallInt::fromWord(RawSmallInt::kMinValue));
2557 Int one(&scope, SmallInt::fromWord(1));
2558 Object result(&scope, runBuiltin(METH(int, __sub__), min_small_int, one));
2559 EXPECT_TRUE(isIntEqualsWord(*result, RawSmallInt::kMinValue - 1));
2560}
2561
2562TEST_F(IntBuiltinsTest, DunderSubWithLargeIntsReturnsLargeInt) {
2563 HandleScope scope(thread_);
2564
2565 const uword digits_left[] = {0xfedcba0987654321, 0x1234567890abcdef};
2566 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
2567 const uword digits_right[] = {0x9876543210abcdef, 0xfedcba0123456789};
2568 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
2569 Object result(&scope, runBuiltin(METH(int, __sub__), left, right));
2570 const uword expected_digits[] = {0x666665d776b97532, 0x13579c776d666666};
2571 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2572}
2573
2574TEST_F(IntBuiltinsTest,
2575 DunderSubWithPositiveLargeIntsBorrowingReturnsLargeInt) {
2576 HandleScope scope(thread_);
2577
2578 Int left(&scope, runtime_->newInt(1));
2579 const uword digits_right[] = {kMaxUword, kMaxUword, 0};
2580 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
2581 Object result(&scope, runBuiltin(METH(int, __sub__), left, right));
2582 const uword expected_digits[] = {2, 0, kMaxUword};
2583 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2584}
2585
2586TEST_F(IntBuiltinsTest,
2587 DunderSubWithNegativeLargeIntsBorrowingReturnsLargeInt) {
2588 HandleScope scope(thread_);
2589
2590 // The smallest negative number representable with 2 digits.
2591 const uword digits_left[] = {0, static_cast<uword>(kMinWord)};
2592 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
2593 Int right(&scope, runtime_->newInt(1));
2594 Object result(&scope, runBuiltin(METH(int, __sub__), left, right));
2595 const uword expected_digits[] = {kMaxUword, uword{kMaxWord}, kMaxUword};
2596 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2597}
2598
2599TEST_F(IntBuiltinsTest, DunderSubWithNonIntSelfRaisesTypeError) {
2600 HandleScope scope(thread_);
2601
2602 Str str(&scope, Str::empty());
2603 Int right(&scope, runtime_->newInt(1));
2604 Object result(&scope, runBuiltin(METH(int, __sub__), str, right));
2605 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
2606}
2607
2608TEST_F(IntBuiltinsTest, DunderSubWithNonIntRightReturnsNotImplemented) {
2609 HandleScope scope(thread_);
2610
2611 Int left(&scope, runtime_->newInt(1));
2612 Str str(&scope, Str::empty());
2613 Object result(&scope, runBuiltin(METH(int, __sub__), left, str));
2614 EXPECT_TRUE(result.isNotImplementedType());
2615}
2616
2617TEST_F(IntBuiltinsTest, DunderXorWithSmallIntsReturnsSmallInt) {
2618 HandleScope scope(thread_);
2619 Int left(&scope, SmallInt::fromWord(0x15)); // 0b010101
2620 Int right(&scope, SmallInt::fromWord(0x38)); // 0b111000
2621 Object result(&scope, runBuiltin(METH(int, __xor__), left, right));
2622 EXPECT_TRUE(isIntEqualsWord(*result, 0x2D)); // 0b101101
2623}
2624
2625TEST_F(IntBuiltinsTest, DunderXorWithLargeIntsReturnsLargeInt) {
2626 HandleScope scope(thread_);
2627 const uword digits_left[] = {0x0f, 0x30, 0xCAFE};
2628 Int left(&scope, runtime_->newLargeIntWithDigits(digits_left));
2629 const uword digits_right[] = {0x03, 0xf0};
2630 Int right(&scope, runtime_->newLargeIntWithDigits(digits_right));
2631 Object result(&scope, runBuiltin(METH(int, __xor__), left, right));
2632 const uword expected_digits[] = {0x0C, 0xC0, 0xCAFE};
2633 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits));
2634}
2635
2636TEST_F(IntBuiltinsTest, DunderXorWithNonIntReturnsNotImplemented) {
2637 HandleScope scope(thread_);
2638 const uword digits[] = {1, 2};
2639 Int left(&scope, runtime_->newLargeIntWithDigits(digits));
2640 Object right(&scope, Str::empty());
2641 Object result(&scope, runBuiltin(METH(int, __xor__), left, right));
2642 EXPECT_TRUE(result.isNotImplementedType());
2643}
2644
2645TEST_F(IntBuiltinsTest, DunderXorWithInvalidArgumentLeftRaisesException) {
2646 HandleScope scope(thread_);
2647 Object left(&scope, Str::empty());
2648 const uword digits[] = {1, 2};
2649 LargeInt right(&scope, runtime_->newLargeIntWithDigits(digits));
2650 Object result(&scope, runBuiltin(METH(int, __xor__), left, right));
2651 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
2652}
2653
2654TEST_F(IntBuiltinsTest, DunderXorWithIntSubclassReturnsInt) {
2655 HandleScope scope(thread_);
2656 ASSERT_FALSE(runFromCStr(runtime_, R"(
2657class X(int): pass
2658left = X(0b0011)
2659right = X(0b0101)
2660)")
2661 .isError());
2662 Object left(&scope, mainModuleAt(runtime_, "left"));
2663 Object right(&scope, mainModuleAt(runtime_, "right"));
2664 Object result(&scope, runBuiltin(METH(int, __xor__), left, right));
2665 EXPECT_EQ(result, SmallInt::fromWord(6)); // 0b0110
2666}
2667
2668TEST_F(IntBuiltinsTest, ToBytesWithByteorderLittleEndianReturnsBytes) {
2669 HandleScope scope(thread_);
2670
2671 Int num(&scope, SmallInt::fromWord(42));
2672 Int length(&scope, SmallInt::fromWord(3));
2673 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2674 Bool signed_obj(&scope, Bool::falseObj());
2675 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2676 signed_obj));
2677
2678 const byte bytes[] = {42, 0, 0};
2679 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2680}
2681
2682TEST_F(IntBuiltinsTest, ToBytesWithIntSubclassReturnsBytes) {
2683 HandleScope scope(thread_);
2684 ASSERT_FALSE(runFromCStr(runtime_, R"(
2685class X(int): pass
2686num = X(42)
2687length = X(3)
2688)")
2689 .isError());
2690 Object num(&scope, mainModuleAt(runtime_, "num"));
2691 Object length(&scope, mainModuleAt(runtime_, "length"));
2692 Object byteorder(&scope, runtime_->newStrFromCStr("little"));
2693 Object signed_obj(&scope, Bool::falseObj());
2694 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2695 signed_obj));
2696 const byte bytes[] = {42, 0, 0};
2697 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2698}
2699
2700TEST_F(IntBuiltinsTest, ToBytesWithByteorderBigEndianReturnsBytes) {
2701 HandleScope scope(thread_);
2702
2703 Int num(&scope, SmallInt::fromWord(42));
2704 Int length(&scope, SmallInt::fromWord(2));
2705 Str byteorder(&scope, runtime_->newStrFromCStr("big"));
2706 Bool signed_obj(&scope, Bool::falseObj());
2707 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2708 signed_obj));
2709 const byte bytes[] = {0, 42};
2710 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2711}
2712
2713TEST_F(IntBuiltinsTest, ToBytesKwReturnsBytes) {
2714 HandleScope scope(thread_);
2715
2716 ASSERT_FALSE(runFromCStr(runtime_, R"(
2717x0 = (0x1234).to_bytes(2, 'little')
2718x1 = (0x1234).to_bytes(2, 'little', signed=False)
2719x2 = (0x1234).to_bytes(2, 'little', signed=True)
2720x3 = (0x1234).to_bytes(2, byteorder='little')
2721x4 = (0x1234).to_bytes(length=2, byteorder='little')
2722x5 = (0x1234).to_bytes(2, byteorder='little', signed=False)
2723x6 = (0x1234).to_bytes(signed=False, byteorder='little', length=2)
2724)")
2725 .isError());
2726 const byte bytes[] = {0x34, 0x12};
2727 for (const char* name : {"x0", "x1", "x2", "x3", "x4", "x5", "x6"}) {
2728 Object x(&scope, mainModuleAt(runtime_, name));
2729 EXPECT_TRUE(isBytesEqualsBytes(x, bytes)) << name;
2730 }
2731}
2732
2733TEST_F(IntBuiltinsTest, ToBytesKwWithNegativeNumberReturnsBytes) {
2734 HandleScope scope(thread_);
2735
2736 ASSERT_FALSE(runFromCStr(runtime_, R"(
2737x0 = (-777).to_bytes(4, 'little', signed=True)
2738)")
2739 .isError());
2740 Object x(&scope, mainModuleAt(runtime_, "x0"));
2741 const byte bytes[] = {0xf7, 0xfc, 0xff, 0xff};
2742 EXPECT_TRUE(isBytesEqualsBytes(x, bytes));
2743}
2744
2745TEST_F(IntBuiltinsTest, ToBytesWithSignedFalseReturnsBytes) {
2746 HandleScope scope(thread_);
2747
2748 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2749
2750 // Test that the following numbers work fine with `signed=False` (they are the
2751 // same numbers that are expected to overflow with `signed=True` in
2752 // ToBytesWithSignedTrueOverflowRaisesOverflowError)
2753 Int length_1(&scope, SmallInt::fromWord(1));
2754 Int num_128(&scope, SmallInt::fromWord(128));
2755 Bool signed_obj(&scope, Bool::falseObj());
2756 Object result_128(&scope, runBuiltin(METH(int, to_bytes), num_128, length_1,
2757 byteorder, signed_obj));
2758 const byte bytes[] = {0x80};
2759 EXPECT_TRUE(isBytesEqualsBytes(result_128, bytes));
2760
2761 Int length_2(&scope, SmallInt::fromWord(2));
2762 Int num_32768(&scope, SmallInt::fromWord(32768));
2763 Object result_32768(&scope, runBuiltin(METH(int, to_bytes), num_32768,
2764 length_2, byteorder, signed_obj));
2765 const byte bytes2[] = {0, 0x80};
2766 EXPECT_TRUE(isBytesEqualsBytes(result_32768, bytes2));
2767
2768 Int length_8(&scope, SmallInt::fromWord(8));
2769 const uword digits[] = {0x8000000000000000, 0};
2770 Int num_min_word(&scope, runtime_->newLargeIntWithDigits(digits));
2771 Object result_min_word(&scope, runBuiltin(METH(int, to_bytes), num_min_word,
2772 length_8, byteorder, signed_obj));
2773 const byte bytes3[] = {0, 0, 0, 0, 0, 0, 0, 0x80};
2774 EXPECT_TRUE(isBytesEqualsBytes(result_min_word, bytes3));
2775}
2776
2777TEST_F(IntBuiltinsTest, ToBytesWithLargeBufferByteorderBigEndianReturnsBytes) {
2778 HandleScope scope(thread_);
2779
2780 // Test sign extension with zero when the buffer is larger than necessary.
2781 Int num(&scope, SmallInt::fromWord(0xcafebabe));
2782 Int length(&scope, SmallInt::fromWord(10));
2783 Str byteorder(&scope, runtime_->newStrFromCStr("big"));
2784 Bool signed_obj(&scope, Bool::falseObj());
2785 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2786 signed_obj));
2787 const byte bytes[] = {0, 0, 0, 0, 0, 0, 0xca, 0xfe, 0xba, 0xbe};
2788 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2789}
2790
2791TEST_F(IntBuiltinsTest,
2792 ToBytesWithLargeBufferByteorderLittleEndianReturnsBytes) {
2793 HandleScope scope(thread_);
2794
2795 // Test sign extension with zero when the buffer is larger than necessary.
2796 Int num(&scope, SmallInt::fromWord(0xcafebabe));
2797 Int length(&scope, SmallInt::fromWord(10));
2798 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2799 Bool signed_obj(&scope, Bool::falseObj());
2800 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2801 signed_obj));
2802 const byte bytes[] = {0xbe, 0xba, 0xfe, 0xca, 0, 0, 0, 0, 0, 0};
2803 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2804}
2805
2806TEST_F(IntBuiltinsTest, ToBytesWithSignedTrueReturnsBytes) {
2807 HandleScope scope(thread_);
2808
2809 ASSERT_FALSE(runFromCStr(runtime_, R"(
2810result = (0x7fffffffffffffff).to_bytes(8, 'little', signed=True)
2811)")
2812 .isError());
2813 Object result(&scope, mainModuleAt(runtime_, "result"));
2814 const byte bytes[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
2815 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2816
2817 ASSERT_FALSE(runFromCStr(runtime_, R"(
2818result_n_128 = (-128).to_bytes(1, 'little', signed=True)
2819)")
2820 .isError());
2821 Object result_n_128(&scope, mainModuleAt(runtime_, "result_n_128"));
2822 const byte bytes2[] = {0x80};
2823 EXPECT_TRUE(isBytesEqualsBytes(result_n_128, bytes2));
2824
2825 ASSERT_FALSE(runFromCStr(runtime_, R"(
2826result_n_32768 = (-32768).to_bytes(2, 'little', signed=True)
2827)")
2828 .isError());
2829 Object result_n_32768(&scope, mainModuleAt(runtime_, "result_n_32768"));
2830 const byte bytes3[] = {0, 0x80};
2831 EXPECT_TRUE(isBytesEqualsBytes(result_n_32768, bytes3));
2832
2833 ASSERT_FALSE(runFromCStr(runtime_, R"(
2834result_n_min_word = (-9223372036854775808).to_bytes(8, 'little', signed=True)
2835)")
2836 .isError());
2837 Object result_n_min_word(&scope, mainModuleAt(runtime_, "result_n_min_word"));
2838 const byte bytes4[] = {0, 0, 0, 0, 0, 0, 0, 0x80};
2839 EXPECT_TRUE(isBytesEqualsBytes(result_n_min_word, bytes4));
2840}
2841
2842TEST_F(IntBuiltinsTest,
2843 ToBytesWithNegativeNumberLargeBufferBigEndianReturnsBytes) {
2844 HandleScope scope(thread_);
2845
2846 // test sign extension for negative number when buffer is larger than
2847 // necessary.
2848 ASSERT_FALSE(runFromCStr(runtime_, R"(
2849result = (-1024).to_bytes(7, 'big', signed=True)
2850)")
2851 .isError());
2852 Object result(&scope, mainModuleAt(runtime_, "result"));
2853 const byte bytes[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0};
2854 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
2855}
2856
2857TEST_F(IntBuiltinsTest, ToBytesWithZeroLengthBigEndianReturnsEmptyBytes) {
2858 HandleScope scope(thread_);
2859
2860 Int num(&scope, SmallInt::fromWord(0));
2861 Int length(&scope, SmallInt::fromWord(0));
2862 Str byteorder(&scope, runtime_->newStrFromCStr("big"));
2863 Bool signed_obj(&scope, Bool::falseObj());
2864 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2865 signed_obj));
2866 ASSERT_TRUE(isBytesEqualsBytes(result, View<byte>(nullptr, 0)));
2867}
2868
2869TEST_F(IntBuiltinsTest, ToBytesWithZeroLengthLittleEndianReturnsEmptyBytes) {
2870 HandleScope scope(thread_);
2871
2872 Int num(&scope, SmallInt::fromWord(0));
2873 Int length(&scope, SmallInt::fromWord(0));
2874 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2875 Bool signed_obj(&scope, Bool::falseObj());
2876 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2877 signed_obj));
2878 ASSERT_TRUE(isBytesEqualsBytes(result, View<byte>(nullptr, 0)));
2879}
2880
2881TEST_F(IntBuiltinsTest, ToBytesWithSignedFalseRaisesOverflowError) {
2882 HandleScope scope(thread_);
2883
2884 Int num(&scope, SmallInt::fromWord(256));
2885 Int length(&scope, SmallInt::fromWord(1));
2886 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2887 Bool signed_obj(&scope, Bool::falseObj());
2888 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2889 signed_obj));
2890 EXPECT_TRUE(raised(*result, LayoutId::kOverflowError));
2891}
2892
2893TEST_F(IntBuiltinsTest, ToBytesWithBigOverflowRaisesOverflowError) {
2894 HandleScope scope(thread_);
2895
2896 const uword digits[] = {1, 2, 3};
2897 Int num(&scope, runtime_->newLargeIntWithDigits(digits));
2898 Int length(&scope, SmallInt::fromWord(13));
2899 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2900 Bool signed_obj(&scope, Bool::falseObj());
2901 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2902 signed_obj));
2903 EXPECT_TRUE(raised(*result, LayoutId::kOverflowError));
2904}
2905
2906TEST_F(IntBuiltinsTest, ToBytesWithSignedTrueRaisesOverflowError) {
2907 Thread* thread = Thread::current();
2908
2909 // Now check that signed=True with the same inputs triggers an error.
2910 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
2911result = (128).to_bytes(1, 'little', signed=True)
2912)"),
2913 LayoutId::kOverflowError,
2914 "int too big to convert"));
2915 thread->clearPendingException();
2916
2917 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
2918result = (32768).to_bytes(2, 'little', signed=True)
2919)"),
2920 LayoutId::kOverflowError,
2921 "int too big to convert"));
2922 thread->clearPendingException();
2923
2924 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
2925result = (0x8000000000000000).to_bytes(8, 'little', signed=True)
2926)"),
2927 LayoutId::kOverflowError,
2928 "int too big to convert"));
2929}
2930
2931TEST_F(IntBuiltinsTest, ToBytesWithNonIntRaisesTypeError) {
2932 HandleScope scope(thread_);
2933
2934 Str str(&scope, runtime_->newStrFromCStr("not an int"));
2935 Int length(&scope, SmallInt::fromWord(10));
2936 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2937 Bool signed_obj(&scope, Bool::falseObj());
2938 Object result(&scope, runBuiltin(METH(int, to_bytes), str, length, byteorder,
2939 signed_obj));
2940 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
2941}
2942
2943TEST_F(IntBuiltinsTest, ToBytesWithInvalidLengthArgRaisesTypeError) {
2944 HandleScope scope(thread_);
2945 Int num(&scope, SmallInt::fromWord(42));
2946 Str not_a_length(&scope, runtime_->newStrFromCStr("not a length"));
2947 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2948 Bool signed_obj(&scope, Bool::falseObj());
2949 Object result(&scope, runBuiltin(METH(int, to_bytes), num, not_a_length,
2950 byteorder, signed_obj));
2951 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
2952}
2953
2954TEST_F(IntBuiltinsTest, ToBytesWithInvalidLengthArgRaisesValueError) {
2955 HandleScope scope(thread_);
2956 Int num(&scope, SmallInt::fromWord(42));
2957 Int negative_length(&scope, SmallInt::fromWord(-3));
2958 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2959 Bool signed_obj(&scope, Bool::falseObj());
2960 Object result(&scope, runBuiltin(METH(int, to_bytes), num, negative_length,
2961 byteorder, signed_obj));
2962 EXPECT_TRUE(raised(*result, LayoutId::kValueError));
2963}
2964
2965TEST_F(IntBuiltinsTest, ToBytesWithInvalidLengthArgRaisesOverflowError) {
2966 HandleScope scope(thread_);
2967 Int num(&scope, SmallInt::fromWord(42));
2968 const uword digits[] = {0, 1024};
2969 Int huge_length(&scope, runtime_->newLargeIntWithDigits(digits));
2970 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2971 Bool signed_obj(&scope, Bool::falseObj());
2972 Object result(&scope, runBuiltin(METH(int, to_bytes), num, huge_length,
2973 byteorder, signed_obj));
2974 EXPECT_TRUE(raised(*result, LayoutId::kOverflowError));
2975}
2976
2977TEST_F(IntBuiltinsTest, ToBytesWithNegativeNumberRaisesOverflowError) {
2978 HandleScope scope(thread_);
2979
2980 Int num(&scope, SmallInt::fromWord(-1));
2981 Int length(&scope, SmallInt::fromWord(10));
2982 Str byteorder(&scope, runtime_->newStrFromCStr("little"));
2983 Bool signed_obj(&scope, Bool::falseObj());
2984 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length, byteorder,
2985 signed_obj));
2986 EXPECT_TRUE(raised(*result, LayoutId::kOverflowError));
2987}
2988
2989TEST_F(IntBuiltinsTest, ToBytesWithInvalidByteorderStringRaisesValueError) {
2990 HandleScope scope(thread_);
2991
2992 Int num(&scope, SmallInt::fromWord(42));
2993 Int length(&scope, SmallInt::fromWord(3));
2994 Str invalid_byteorder(&scope, runtime_->newStrFromCStr("hello"));
2995 Bool signed_obj(&scope, Bool::falseObj());
2996 Object result(&scope, runBuiltin(METH(int, to_bytes), num, length,
2997 invalid_byteorder, signed_obj));
2998 EXPECT_TRUE(raised(*result, LayoutId::kValueError));
2999}
3000
3001TEST_F(IntBuiltinsTest, ToBytesWithInvalidByteorderTypeRaisesTypeError) {
3002 HandleScope scope(thread_);
3003
3004 Int num(&scope, SmallInt::fromWord(42));
3005 Int length(&scope, SmallInt::fromWord(3));
3006 Bool signed_obj(&scope, Bool::falseObj());
3007 Object result(&scope,
3008 runBuiltin(METH(int, to_bytes), num, length, num, signed_obj));
3009 EXPECT_TRUE(raised(*result, LayoutId::kTypeError));
3010}
3011
3012TEST_F(BoolBuiltinsTest, NewFromNonZeroIntegerReturnsTrue) {
3013 HandleScope scope(thread_);
3014 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3015 Int num(&scope, SmallInt::fromWord(2));
3016
3017 Bool result(&scope, runBuiltin(METH(bool, __new__), type, num));
3018 EXPECT_TRUE(result.value());
3019}
3020
3021TEST_F(BoolBuiltinsTest, NewFromZerorReturnsFalse) {
3022 HandleScope scope(thread_);
3023 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3024 Int num(&scope, SmallInt::fromWord(0));
3025
3026 Bool result(&scope, runBuiltin(METH(bool, __new__), type, num));
3027 EXPECT_FALSE(result.value());
3028}
3029
3030TEST_F(BoolBuiltinsTest, NewFromTrueReturnsTrue) {
3031 HandleScope scope(thread_);
3032 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3033 Object true_obj(&scope, Bool::trueObj());
3034
3035 Bool result(&scope, runBuiltin(METH(bool, __new__), type, true_obj));
3036 EXPECT_TRUE(result.value());
3037}
3038
3039TEST_F(BoolBuiltinsTest, NewFromFalseReturnsTrue) {
3040 HandleScope scope(thread_);
3041 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3042 Object false_obj(&scope, Bool::falseObj());
3043
3044 Bool result(&scope, runBuiltin(METH(bool, __new__), type, false_obj));
3045 EXPECT_FALSE(result.value());
3046}
3047
3048TEST_F(BoolBuiltinsTest, NewFromNoneIsFalse) {
3049 HandleScope scope(thread_);
3050 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3051 Object none(&scope, NoneType::object());
3052
3053 Bool result(&scope, runBuiltin(METH(bool, __new__), type, none));
3054 EXPECT_FALSE(result.value());
3055}
3056
3057TEST_F(BoolBuiltinsTest, NewFromUserDefinedType) {
3058 ASSERT_FALSE(runFromCStr(runtime_, R"(
3059class Foo:
3060 def __bool__(self):
3061 return True
3062
3063class Bar:
3064 def __bool__(self):
3065 return False
3066
3067foo = Foo()
3068bar = Bar()
3069)")
3070 .isError());
3071 HandleScope scope(thread_);
3072 Object foo(&scope, mainModuleAt(runtime_, "foo"));
3073 Object bar(&scope, mainModuleAt(runtime_, "bar"));
3074
3075 {
3076 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3077 Bool result(&scope, runBuiltin(METH(bool, __new__), type, foo));
3078 EXPECT_TRUE(result.value());
3079 }
3080 {
3081 Type type(&scope, runtime_->typeAt(LayoutId::kBool));
3082 Bool result(&scope, runBuiltin(METH(bool, __new__), type, bar));
3083 EXPECT_FALSE(result.value());
3084 }
3085}
3086
3087TEST_F(IntBuiltinsTest, DunderTrueDivWithZeroLeftReturnsZero) {
3088 HandleScope scope(thread_);
3089 Int left(&scope, SmallInt::fromWord(0));
3090 Int right(&scope, SmallInt::fromWord(17));
3091 Object result(&scope, runBuiltin(METH(int, __truediv__), left, right));
3092 ASSERT_TRUE(result.isFloat());
3093 Float flt(&scope, *result);
3094 EXPECT_EQ(flt.value(), 0.0);
3095}
3096
3097TEST_F(IntBuiltinsTest, DunderTrueDivWithBoolFalseRaisesZeroDivisionError) {
3098 HandleScope scope(thread_);
3099 Object numerator(&scope, SmallInt::fromWord(10));
3100 Object denominator(&scope, Bool::falseObj());
3101 EXPECT_TRUE(
3102 raisedWithStr(runBuiltin(METH(int, __truediv__), numerator, denominator),
3103 LayoutId::kZeroDivisionError, "division by zero"));
3104}
3105
3106TEST_F(IntBuiltinsTest, DunderTrueDivWithIntZeroRaisesZeroDivisionError) {
3107 HandleScope scope(thread_);
3108 Object numerator(&scope, SmallInt::fromWord(10));
3109 Object denominator(&scope, SmallInt::fromWord(0));
3110 EXPECT_TRUE(
3111 raisedWithStr(runBuiltin(METH(int, __truediv__), numerator, denominator),
3112 LayoutId::kZeroDivisionError, "division by zero"));
3113}
3114
3115TEST_F(IntBuiltinsTest, DunderTrueDivWithFloatRightReturnsNotImplemented) {
3116 HandleScope scope(thread_);
3117 Object left(&scope, SmallInt::fromWord(100));
3118 Object right(&scope, runtime_->newFloat(1.5));
3119 Object result(&scope, runBuiltin(METH(int, __truediv__), left, right));
3120 EXPECT_EQ(result, NotImplementedType::object());
3121}
3122
3123TEST_F(IntBuiltinsTest, DunderTrueDivWithSmallIntsReturnsFloat) {
3124 HandleScope scope(thread_);
3125
3126 Object num1(&scope, SmallInt::fromWord(6));
3127 Object num2(&scope, SmallInt::fromWord(3));
3128 Float result(&scope, runBuiltin(METH(int, __truediv__), num1, num2));
3129 EXPECT_NEAR(result.value(), 2.0, DBL_EPSILON);
3130
3131 num1 = SmallInt::fromWord(7);
3132 num2 = SmallInt::fromWord(3);
3133 result = runBuiltin(METH(int, __truediv__), num1, num2);
3134 EXPECT_NEAR(result.value(), 2.3333333333333335, DBL_EPSILON);
3135}
3136
3137TEST_F(IntBuiltinsTest, ConjugateAliasesDunderInt) {
3138 Thread* thread = Thread::current();
3139 HandleScope scope(thread);
3140 Type type(&scope, moduleAtByCStr(runtime_, "builtins", "int"));
3141 Object conjugate_name(&scope,
3142 Runtime::internStrFromCStr(thread_, "conjugate"));
3143 Object conjugate_obj(&scope, typeAt(type, conjugate_name));
3144 ASSERT_TRUE(conjugate_obj.isFunction());
3145 Function conjugate(&scope, *conjugate_obj);
3146 Object dint_name(&scope, Runtime::internStrFromCStr(thread_, "__int__"));
3147 Object dint_obj(&scope, typeAt(type, dint_name));
3148 ASSERT_TRUE(dint_obj.isFunction());
3149 Function dint(&scope, *conjugate_obj);
3150 EXPECT_EQ(Code::cast(conjugate.code()).code(),
3151 Code::cast(dint.code()).code());
3152 EXPECT_EQ(conjugate.entry(), dint.entry());
3153 EXPECT_EQ(conjugate.entryKw(), dint.entryKw());
3154 EXPECT_EQ(conjugate.entryEx(), dint.entryEx());
3155}
3156
3157TEST_F(IntBuiltinsTest, DenominatorReturnsOne) {
3158 HandleScope scope(thread_);
3159 ASSERT_FALSE(runFromCStr(runtime_, "result = (44).denominator").isError());
3160 Object result(&scope, mainModuleAt(runtime_, "result"));
3161 EXPECT_TRUE(isIntEqualsWord(*result, 1));
3162}
3163
3164TEST_F(IntBuiltinsTest, ImagReturnsZero) {
3165 HandleScope scope(thread_);
3166 ASSERT_FALSE(runFromCStr(runtime_, "result = (44).imag").isError());
3167 Object result(&scope, mainModuleAt(runtime_, "result"));
3168 EXPECT_TRUE(isIntEqualsWord(*result, 0));
3169}
3170
3171TEST_F(IntBuiltinsTest, NumeratorReturnsInt) {
3172 HandleScope scope(thread_);
3173 ASSERT_FALSE(runFromCStr(runtime_, "result = (44).numerator").isError());
3174 Object result(&scope, mainModuleAt(runtime_, "result"));
3175 EXPECT_TRUE(isIntEqualsWord(*result, 44));
3176}
3177
3178TEST_F(IntBuiltinsTest, RealReturnsInt) {
3179 HandleScope scope(thread_);
3180 ASSERT_FALSE(runFromCStr(runtime_, "result = (44).real").isError());
3181 Object result(&scope, mainModuleAt(runtime_, "result"));
3182 EXPECT_TRUE(isIntEqualsWord(*result, 44));
3183}
3184
3185TEST_F(IntBuiltinsTest, CompareWithBigNegativeNumber) {
3186 ASSERT_FALSE(runFromCStr(runtime_, "a = -46116860184273879030000").isError());
3187 HandleScope scope(thread_);
3188 Int a(&scope, mainModuleAt(runtime_, "a"));
3189 Int b(&scope, SmallInt::fromWord(SmallInt::kMinValue));
3190 EXPECT_LT(a.compare(*b), 0);
3191 EXPECT_GT(b.compare(*a), 0);
3192}
3193
3194} // namespace testing
3195} // namespace py