runtime/under-builtins-module-test.cpp (2,988 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #include <cmath> #include "gtest/gtest.h" #include "attributedict.h" #include "builtins-module.h" #include "builtins.h" #include "bytearray-builtins.h" #include "dict-builtins.h" #include "int-builtins.h" #include "memoryview-builtins.h" #include "module-builtins.h" #include "runtime.h" #include "test-utils.h" #include "trampolines.h" #include "type-builtins.h" namespace py { namespace testing { using UnderBuiltinsModuleTest = RuntimeFixture; using UnderBuiltinsModuleDeathTest = RuntimeFixture; TEST_F(UnderBuiltinsModuleTest, UnderAnysetCheckWithNonSetReturnsFalse) { HandleScope scope(thread_); Object obj(&scope, newTupleWithNone(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _anyset_check), obj)); EXPECT_EQ(result, Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderAnysetCheckWithSetReturnsTrue) { HandleScope scope(thread_); Object obj(&scope, runtime_->newSet()); Object result(&scope, runBuiltin(FUNC(_builtins, _anyset_check), obj)); EXPECT_EQ(result, Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderAnysetCheckWithSetSubclassReturnsTrue) { ASSERT_FALSE(runFromCStr(runtime_, R"( class C(set): pass obj = C() )") .isError()); HandleScope scope(thread_); Object obj(&scope, mainModuleAt(runtime_, "obj")); Object result(&scope, runBuiltin(FUNC(_builtins, _anyset_check), obj)); EXPECT_EQ(result, Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderAnysetCheckWithFrozenSetReturnsTrue) { HandleScope scope(thread_); Object obj(&scope, runtime_->newFrozenSet()); Object result(&scope, runBuiltin(FUNC(_builtins, _anyset_check), obj)); EXPECT_EQ(result, Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderAnysetCheckWithFrozenSetSubclassReturnsTrue) { ASSERT_FALSE(runFromCStr(runtime_, R"( class C(frozenset): pass obj = C() )") .isError()); HandleScope scope(thread_); Object obj(&scope, mainModuleAt(runtime_, "obj")); Object result(&scope, runBuiltin(FUNC(_builtins, _anyset_check), obj)); EXPECT_EQ(result, Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayClearSetsLengthToZero) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); const byte byte_array[] = {'1', '2', '3'}; runtime_->bytearrayExtend(thread_, array, byte_array); ASSERT_EQ(array.numItems(), 3); ASSERT_FALSE(runBuiltin(FUNC(_builtins, _bytearray_clear), array).isError()); EXPECT_EQ(array.numItems(), 0); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsWithEmptyBytearrayReturnsFalse) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); ASSERT_EQ(array.numItems(), 0); Object key(&scope, SmallInt::fromWord('a')); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains), array, key), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsWithIntBiggerThanCharRaisesValueError) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); const byte byte_array[] = {'1', '2', '3'}; runtime_->bytearrayExtend(thread_, array, byte_array); ASSERT_EQ(array.numItems(), 3); Object key(&scope, SmallInt::fromWord(256)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _bytearray_contains), array, key), LayoutId::kValueError, "byte must be in range(0, 256)")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsWithByteInBytearrayReturnsTrue) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); const byte byte_array[] = {'1', '2', '3'}; runtime_->bytearrayExtend(thread_, array, byte_array); ASSERT_EQ(array.numItems(), 3); Object key(&scope, SmallInt::fromWord('2')); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains), array, key), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsWithByteNotInBytearrayReturnsFalse) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); const byte byte_array[] = {'1', '2', '3'}; runtime_->bytearrayExtend(thread_, array, byte_array); ASSERT_EQ(array.numItems(), 3); Object key(&scope, SmallInt::fromWord('x')); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains), array, key), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsByteslikeWithBytearrayInBytearrayReturnsTrue) { HandleScope scope(thread_); Bytearray array(&scope, newBytearrayFromCStr(thread_, "1234")); ASSERT_EQ(array.numItems(), 4); Bytearray array_search(&scope, newBytearrayFromCStr(thread_, "23")); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains_byteslike), array, array_search), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsByteslikeWithBytesInBytearrayReturnsTrue) { HandleScope scope(thread_); Bytearray array(&scope, newBytearrayFromCStr(thread_, "1234")); ASSERT_EQ(array.numItems(), 4); Bytes bytes_search(&scope, newBytesFromCStr(thread_, "23")); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains_byteslike), array, bytes_search), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsByteslikeWithMemeoryViewInBytearrayReturnsTrue) { HandleScope scope(thread_); Bytearray array(&scope, newBytearrayFromCStr(thread_, "1234")); ASSERT_EQ(array.numItems(), 4); const byte view_src[] = {'2', '3'}; MemoryView view_search(&scope, newMemoryView(view_src, "b", ReadOnly::ReadWrite)); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains_byteslike), array, view_search), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsByteslikeWithBytearrayNotInBytearrayReturnsFalse) { HandleScope scope(thread_); Bytearray array(&scope, newBytearrayFromCStr(thread_, "1234")); ASSERT_EQ(array.numItems(), 4); Bytearray array_search(&scope, newBytearrayFromCStr(thread_, "24")); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains_byteslike), array, array_search), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayContainsByteslikeWithBytesNotInBytearrayReturnsFalse) { HandleScope scope(thread_); Bytearray array(&scope, newBytearrayFromCStr(thread_, "1234")); ASSERT_EQ(array.numItems(), 4); Bytes bytes_search(&scope, newBytesFromCStr(thread_, "24")); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains_byteslike), array, bytes_search), Bool::falseObj()); } TEST_F( UnderBuiltinsModuleTest, UnderBytearrayContainsByteslikeWithMemoryviewNotInBytearrayReturnsFalse) { HandleScope scope(thread_); Bytearray array(&scope, newBytearrayFromCStr(thread_, "1234")); ASSERT_EQ(array.numItems(), 4); const byte view_src[] = {'2', '4'}; MemoryView view_search(&scope, newMemoryView(view_src, "b", ReadOnly::ReadWrite)); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytearray_contains_byteslike), array, view_search), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayDelitemDeletesItemAtIndex) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int idx(&scope, SmallInt::fromWord(2)); EXPECT_TRUE( runBuiltin(FUNC(_builtins, _bytearray_delitem), self, idx).isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "abde")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayDelsliceWithStepEqualsOneAndNoGrowthDeletesSlice) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(3)); Int step(&scope, SmallInt::fromWord(1)); EXPECT_TRUE( runBuiltin(FUNC(_builtins, _bytearray_delslice), self, start, stop, step) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "de")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayDelsliceWithStepEqualsTwoAndNoGrowthDeletesSlice) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(3)); Int step(&scope, SmallInt::fromWord(2)); EXPECT_TRUE( runBuiltin(FUNC(_builtins, _bytearray_delslice), self, start, stop, step) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "bde")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayJoinWithEmptyIterableReturnsEmptyBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); Object iter(&scope, runtime_->emptyTuple()); Object result(&scope, runBuiltin(FUNC(_builtins, _bytearray_join), self, iter)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayJoinWithEmptySeparatorReturnsBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Object obj1(&scope, runtime_->newBytes(1, 'A')); Object obj2(&scope, runtime_->newBytes(2, 'B')); Object obj3(&scope, runtime_->newBytes(1, 'A')); Tuple iter(&scope, runtime_->newTupleWith3(obj1, obj2, obj3)); Object result(&scope, runBuiltin(FUNC(_builtins, _bytearray_join), self, iter)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "ABBA")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearrayJoinWithNonEmptyReturnsBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, ' '); List iter(&scope, runtime_->newList()); Bytes value(&scope, runtime_->newBytes(1, '*')); runtime_->listAdd(thread_, iter, value); runtime_->listAdd(thread_, iter, value); runtime_->listAdd(thread_, iter, value); Object result(&scope, runBuiltin(FUNC(_builtins, _bytearray_join), self, iter)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "* * *")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetitemWithLargeIntRaisesIndexError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Int key(&scope, runtime_->newInt(SmallInt::kMaxValue + 1)); Int value(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value), LayoutId::kIndexError, "cannot fit 'int' into an index-sized integer")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetitemWithKeyLargerThanMaxIndexRaisesIndexError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, ' '); Int key(&scope, runtime_->newInt(self.numItems())); Int value(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value), LayoutId::kIndexError, "index out of range")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetitemWithNegativeValueRaisesValueError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, ' '); Int key(&scope, runtime_->newInt(0)); Int value(&scope, SmallInt::fromWord(-1)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value), LayoutId::kValueError, "byte must be in range(0, 256)")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetitemWithKeySmallerThanNegativeLengthValueRaisesValueError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, ' '); Int key(&scope, runtime_->newInt(-self.numItems() - 1)); Int value(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value), LayoutId::kIndexError, "index out of range")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetitemWithValueGreaterThanKMaxByteRaisesValueError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, ' '); Int key(&scope, runtime_->newInt(0)); Int value(&scope, SmallInt::fromWord(kMaxByte + 1)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value), LayoutId::kValueError, "byte must be in range(0, 256)")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetitemWithNegativeKeyIndexesBackwards) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); Int key(&scope, SmallInt::fromWord(-1)); Int value(&scope, SmallInt::fromWord(1)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "ab\001")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetitemWithNegativeKeySetsItemAtIndex) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); Int key(&scope, SmallInt::fromWord(1)); Int value(&scope, SmallInt::fromWord(1)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setitem), self, key, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "a\001c")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndNoGrowthSetsSlice) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(3)); Int step(&scope, SmallInt::fromWord(1)); Bytearray value(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, value, 'A'); bytearrayAdd(thread_, runtime_, value, 'B'); bytearrayAdd(thread_, runtime_, value, 'C'); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "ABCde")); } TEST_F(UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsTwoAndNoGrowthSetsSlice) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(3)); Int step(&scope, SmallInt::fromWord(2)); Bytearray value(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, value, 'A'); bytearrayAdd(thread_, runtime_, value, 'B'); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "AbBde")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndSelfAsSourceSetsSliceAndGrows) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(4)); Int step(&scope, SmallInt::fromWord(1)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, self) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "abcdee")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndSelfAsSourceStartsAtOneSetsSliceAndGrowsLHS) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(4)); Int step(&scope, SmallInt::fromWord(1)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, self) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "aabcdee")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndBytesAsSourceSetsSliceAndGrowsLHS) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(4)); Int step(&scope, SmallInt::fromWord(1)); byte src[] = {'o', 'o', 'o', 'o'}; Bytes value(&scope, runtime_->newBytesWithAll(src)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "aooooe")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndMemoryViewOfBytesAsSourceSetsSliceAndGrowsLHS) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(4)); Int step(&scope, SmallInt::fromWord(1)); const byte src[] = {'o', 'o', 'o', 'o'}; MemoryView value(&scope, newMemoryView(src, "b", ReadOnly::ReadWrite)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "aooooe")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndMemoryViewOfPointerAsSourceSetsSliceAndGrowsLHS) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(4)); Int step(&scope, SmallInt::fromWord(1)); const word length = 4; byte memory[] = {'o', 'o', 'o', 'o'}; Object none(&scope, NoneType::object()); MemoryView value( &scope, runtime_->newMemoryViewFromCPtr(thread_, none, memory, length, ReadOnly::ReadWrite)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "aooooe")); } TEST_F( UnderBuiltinsModuleTest, UnderBytearraySetsliceWithStepEqualsOneAndArrayAsSourceSetsSliceAndGrowsLHS) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); bytearrayAdd(thread_, runtime_, self, 'b'); bytearrayAdd(thread_, runtime_, self, 'c'); bytearrayAdd(thread_, runtime_, self, 'd'); bytearrayAdd(thread_, runtime_, self, 'e'); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(5)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_FALSE(runFromCStr(runtime_, R"( import array arr = array.array('b', [1, 2, 3, 4, 5]) )") .isError()); Object value(&scope, mainModuleAt(runtime_, "arr")); ASSERT_TRUE(value.isArray()); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _bytearray_setslice), self, start, stop, step, value) .isNoneType()); EXPECT_TRUE(isBytearrayEqualsCStr(self, "a\x01\x02\x03\x04\x05")); } TEST_F(UnderBuiltinsModuleTest, UnderBytesContainsWithIntBiggerThanCharRaisesValueError) { HandleScope scope(thread_); const byte contents[] = {'1', '2', '3'}; Bytes bytes(&scope, runtime_->newBytesWithAll(contents)); ASSERT_EQ(bytes.length(), 3); Object key(&scope, SmallInt::fromWord(256)); EXPECT_TRUE( raisedWithStr(runBuiltin(FUNC(_builtins, _bytes_contains), bytes, key), LayoutId::kValueError, "byte must be in range(0, 256)")); } TEST_F(UnderBuiltinsModuleTest, UnderBytesContainsWithByteInBytesReturnsTrue) { HandleScope scope(thread_); const byte contents[] = {'1', '2', '3'}; Bytes bytes(&scope, runtime_->newBytesWithAll(contents)); ASSERT_EQ(bytes.length(), 3); Object key(&scope, SmallInt::fromWord('2')); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytes_contains), bytes, key), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytesContainsWithByteNotInBytesReturnsFalse) { HandleScope scope(thread_); const byte contents[] = {'1', '2', '3'}; Bytes bytes(&scope, runtime_->newBytesWithAll(contents)); ASSERT_EQ(bytes.length(), 3); Object key(&scope, SmallInt::fromWord('x')); EXPECT_EQ(runBuiltin(FUNC(_builtins, _bytes_contains), bytes, key), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderBytesJoinWithEmptyIterableReturnsEmptyBytearray) { Thread* thread = Thread::current(); HandleScope scope(thread); Bytes self(&scope, runtime_->newBytes(3, 'a')); Object iter(&scope, runtime_->emptyTuple()); Object result(&scope, runBuiltin(FUNC(_builtins, _bytes_join), self, iter)); EXPECT_TRUE(isBytesEqualsCStr(result, "")); } TEST_F(UnderBuiltinsModuleTest, UnderBytesJoinWithEmptySeparatorReturnsBytes) { Thread* thread = Thread::current(); HandleScope scope(thread); Bytes self(&scope, Bytes::empty()); Object obj1(&scope, runtime_->newBytes(1, 'A')); Object obj2(&scope, runtime_->newBytes(2, 'B')); Object obj3(&scope, runtime_->newBytes(1, 'A')); Tuple iter(&scope, runtime_->newTupleWith3(obj1, obj2, obj3)); Object result(&scope, runBuiltin(FUNC(_builtins, _bytes_join), self, iter)); EXPECT_TRUE(isBytesEqualsCStr(result, "ABBA")); } TEST_F(UnderBuiltinsModuleTest, UnderBytesJoinWithNonEmptyListReturnsBytes) { Thread* thread = Thread::current(); HandleScope scope(thread); Bytes self(&scope, runtime_->newBytes(1, ' ')); List iter(&scope, runtime_->newList()); Bytes value(&scope, runtime_->newBytes(1, '*')); runtime_->listAdd(thread, iter, value); runtime_->listAdd(thread, iter, value); runtime_->listAdd(thread, iter, value); Object result(&scope, runBuiltin(FUNC(_builtins, _bytes_join), self, iter)); EXPECT_TRUE(isBytesEqualsCStr(result, "* * *")); } TEST_F(UnderBuiltinsModuleTest, UnderBytesJoinWithBytesSubclassesReturnsBytes) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Foo(bytes): def join(self, iterable): # this should not be called - expect bytes.join() instead return 0 sep = Foo(b"-") ac = Foo(b"AC") dc = Foo(b"DC") )") .isError()); HandleScope scope(thread_); Object self(&scope, mainModuleAt(runtime_, "sep")); Object obj1(&scope, mainModuleAt(runtime_, "ac")); Object obj2(&scope, mainModuleAt(runtime_, "dc")); Tuple iter(&scope, runtime_->newTupleWith2(obj1, obj2)); Object result(&scope, runBuiltin(FUNC(_builtins, _bytes_join), self, iter)); EXPECT_TRUE(isBytesEqualsCStr(result, "AC-DC")); } TEST_F(UnderBuiltinsModuleTest, UnderBytesJoinWithMemoryViewReturnsBytes) { Thread* thread = Thread::current(); HandleScope scope(thread); Bytes self(&scope, runtime_->newBytes(1, ' ')); Bytes src1(&scope, newBytesFromCStr(thread_, "hello")); MemoryView obj1(&scope, runtime_->newMemoryView(thread_, src1, src1, src1.length(), ReadOnly::ReadOnly)); Bytes src2(&scope, newBytesFromCStr(thread_, "world")); MemoryView obj2(&scope, runtime_->newMemoryView(thread_, src2, src2, src2.length(), ReadOnly::ReadOnly)); Tuple iter(&scope, runtime_->newTupleWith2(obj1, obj2)); Object result(&scope, runBuiltin(FUNC(_builtins, _bytes_join), self, iter)); EXPECT_TRUE(isBytesEqualsCStr(result, "hello world")); } TEST_F(UnderBuiltinsModuleTest, UnderCallerLocalsDoesNotReturnInternalObjects) { ASSERT_FALSE(runFromCStr(runtime_, R"( def bar(): a = 23 b = 13 l = locals() c = 0 d = 0 e = 0 f = 0 g = 0 return l )") .isError()); // Push arbitrary values to the stack Thread* thread = Thread::current(); for (int a = 0; a < 20; a++) { for (int i = 0; i < 5; i++) { thread->stackPush(Unbound::object()); } thread->stackPush(Error::notFound()); thread->stackPush(runtime_->newMutableBytesUninitialized(1)); thread->stackPush(runtime_->newMutableTuple(1)); thread->stackPush(NoneType::object()); } // Reset the stack pointer thread->stackDrop(9 * 20); /* * When locals is called in bar we expect the stack to look like below Function bar --- Locals ---- int 23 -> assigned to a int 13 -> assigned to b _Unbound -> assigned to l _Unbound -> assigned to c Error::notFound -> assigned to d _mutablebytes -> assigned to e _mutable_tuple -> assigned to f NoneType::object -> assigned to g */ HandleScope scope(thread); Object bar_object(&scope, mainModuleAt(runtime_, "bar")); EXPECT_TRUE(bar_object.isFunction()); Function bar(&scope, *bar_object); Tuple args(&scope, runtime_->emptyTuple()); Object result(&scope, callFunction(bar, args)); EXPECT_TRUE(result.isDict()); Dict locals(&scope, *result); Str a(&scope, runtime_->newStrFromCStr("a")); Object a_val(&scope, dictAtByStr(thread_, locals, a)); EXPECT_TRUE(isIntEqualsWord(*a_val, 23)); Str b(&scope, runtime_->newStrFromCStr("b")); Object b_val(&scope, dictAtByStr(thread_, locals, b)); EXPECT_TRUE(isIntEqualsWord(*b_val, 13)); Str c(&scope, runtime_->newStrFromCStr("c")); Object c_val(&scope, dictAtByStr(thread_, locals, c)); EXPECT_TRUE(c_val.isErrorNotFound()); Str d(&scope, runtime_->newStrFromCStr("d")); Object d_val(&scope, dictAtByStr(thread_, locals, d)); EXPECT_TRUE(d_val.isErrorNotFound()); Str e(&scope, runtime_->newStrFromCStr("e")); Object e_val(&scope, dictAtByStr(thread_, locals, e)); EXPECT_TRUE(e_val.isErrorNotFound()); Str f(&scope, runtime_->newStrFromCStr("f")); Object f_val(&scope, dictAtByStr(thread_, locals, f)); EXPECT_TRUE(f_val.isErrorNotFound()); Str g(&scope, runtime_->newStrFromCStr("g")); Object g_val(&scope, dictAtByStr(thread_, locals, g)); // TODO(T89882231) Expect g_val to be ErrorNotFound EXPECT_TRUE(g_val.isNoneType()); } TEST_F(UnderBuiltinsModuleTest, UnderCodeSetFilenameSetsFilename) { HandleScope scope(thread_); Code code(&scope, newCodeWithBytes(View<byte>(nullptr, 0))); Str filename(&scope, runtime_->newStrFromCStr("foobar")); ASSERT_NE(code.filename(), filename); ASSERT_FALSE(runBuiltin(FUNC(_builtins, _code_set_filename), code, filename) .isError()); EXPECT_EQ(code.filename(), filename); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetWithNotEnoughArgumentsRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "_dict_get()"), LayoutId::kTypeError, "'_dict_get' takes min 2 positional arguments but 0 given")); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetWithTooManyArgumentsRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "_dict_get({}, 123, 456, 789)"), LayoutId::kTypeError, "'_dict_get' takes max 3 positional arguments but 4 given")); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetWithUnhashableTypeRaisesTypeError) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class Foo: __hash__ = 2 key = Foo() )") .isError()); Dict dict(&scope, runtime_->newDict()); Object key(&scope, mainModuleAt(runtime_, "key")); Object default_obj(&scope, NoneType::object()); ASSERT_TRUE( raised(runBuiltin(FUNC(_builtins, _dict_get), dict, key, default_obj), LayoutId::kTypeError)); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetWithIntSubclassHashReturnsDefaultValue) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class N(int): pass class Foo: def __hash__(self): return N(12) key = Foo() )") .isError()); Dict dict(&scope, runtime_->newDict()); Object key(&scope, mainModuleAt(runtime_, "key")); Object default_obj(&scope, runtime_->newInt(5)); EXPECT_EQ(runBuiltin(FUNC(_builtins, _dict_get), dict, key, default_obj), default_obj); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetReturnsDefaultValue) { ASSERT_FALSE( runFromCStr(runtime_, "res = _dict_get({}, 123, 456)").isError()); EXPECT_EQ(mainModuleAt(runtime_, "res"), RawSmallInt::fromWord(456)); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetReturnsNone) { ASSERT_FALSE(runFromCStr(runtime_, "result = _dict_get({}, 123)").isError()); EXPECT_TRUE(mainModuleAt(runtime_, "result").isNoneType()); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetReturnsValue) { HandleScope scope(thread_); Dict dict(&scope, runtime_->newDict()); Object key(&scope, runtime_->newInt(123)); word hash = intHash(*key); Object value(&scope, runtime_->newInt(456)); ASSERT_TRUE(dictAtPut(thread_, dict, key, hash, value).isNoneType()); Object dflt(&scope, runtime_->newInt(789)); Object result(&scope, runBuiltin(FUNC(_builtins, _dict_get), dict, key, dflt)); EXPECT_TRUE(isIntEqualsWord(*result, 456)); } TEST_F(UnderBuiltinsModuleTest, UnderDictGetWithNonDictRaisesTypeError) { HandleScope scope(thread_); Object foo(&scope, runtime_->newInt(123)); Object bar(&scope, runtime_->newInt(456)); Object baz(&scope, runtime_->newInt(789)); EXPECT_TRUE(raised(runBuiltin(FUNC(_builtins, _dict_get), foo, bar, baz), LayoutId::kTypeError)); } TEST_F(UnderBuiltinsModuleTest, UnderDictSetitemWithKeyHashReturningNonIntRaisesTypeError) { EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( class E: def __hash__(self): return "non int" d = {} _dict_setitem(d, E(), 4) )"), LayoutId::kTypeError, "__hash__ method should return an integer")); } TEST_F(UnderBuiltinsModuleTest, UnderDictSetitemWithExistingKey) { HandleScope scope(thread_); Dict dict(&scope, runtime_->newDictWithSize(1)); Str key(&scope, runtime_->newStrFromCStr("foo")); Object val(&scope, runtime_->newInt(0)); Object val2(&scope, runtime_->newInt(1)); dictAtPutByStr(thread_, dict, key, val); Object result(&scope, runBuiltin(FUNC(_builtins, _dict_setitem), dict, key, val2)); ASSERT_TRUE(result.isNoneType()); ASSERT_EQ(dict.numItems(), 1); ASSERT_EQ(dictAtByStr(thread_, dict, key), *val2); } TEST_F(UnderBuiltinsModuleTest, UnderDictSetitemWithNonExistentKey) { HandleScope scope(thread_); Dict dict(&scope, runtime_->newDictWithSize(1)); ASSERT_EQ(dict.numItems(), 0); Str key(&scope, runtime_->newStrFromCStr("foo")); Object val(&scope, runtime_->newInt(0)); Object result(&scope, runBuiltin(FUNC(_builtins, _dict_setitem), dict, key, val)); ASSERT_TRUE(result.isNoneType()); ASSERT_EQ(dict.numItems(), 1); ASSERT_EQ(dictAtByStr(thread_, dict, key), *val); } TEST_F(UnderBuiltinsModuleTest, UnderDictSetitemWithDictSubclassSetsItem) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class foo(dict): pass d = foo() )") .isError()); Dict dict(&scope, mainModuleAt(runtime_, "d")); Str key(&scope, runtime_->newStrFromCStr("a")); Str value(&scope, runtime_->newStrFromCStr("b")); Object result1(&scope, runBuiltin(FUNC(_builtins, _dict_setitem), dict, key, value)); EXPECT_TRUE(result1.isNoneType()); Object result2(&scope, dictAtByStr(thread_, dict, key)); ASSERT_TRUE(result2.isStr()); EXPECT_EQ(Str::cast(*result2), *value); } TEST_F(UnderBuiltinsModuleTest, UnderDivmodReturnsQuotientAndDividend) { HandleScope scope(thread_); Int number(&scope, SmallInt::fromWord(1234)); Int divisor(&scope, SmallInt::fromWord(-5)); Object tuple_obj(&scope, runBuiltin(FUNC(_builtins, _divmod), number, divisor)); ASSERT_TRUE(tuple_obj.isTuple()); Tuple tuple(&scope, *tuple_obj); ASSERT_EQ(tuple.length(), 2); EXPECT_TRUE(isIntEqualsWord(tuple.at(0), -247)); EXPECT_TRUE(isIntEqualsWord(tuple.at(1), -1)); } TEST_F(UnderBuiltinsModuleTest, UnderFloatDivmodReturnsQuotientAndRemainder) { HandleScope scope(thread_); Float number(&scope, runtime_->newFloat(3.25)); Float divisor(&scope, runtime_->newFloat(1.0)); Tuple result(&scope, runBuiltin(FUNC(_builtins, _float_divmod), number, divisor)); ASSERT_EQ(result.length(), 2); Float quotient(&scope, result.at(0)); Float remainder(&scope, result.at(1)); EXPECT_EQ(quotient.value(), 3.0); EXPECT_EQ(remainder.value(), 0.25); } TEST_F(UnderBuiltinsModuleTest, UnderFloatDivmodWithZeroDivisorRaisesZeroDivisionError) { HandleScope scope(thread_); Float number(&scope, runtime_->newFloat(3.25)); Float divisor(&scope, runtime_->newFloat(0.0)); EXPECT_TRUE( raisedWithStr(runBuiltin(FUNC(_builtins, _float_divmod), number, divisor), LayoutId::kZeroDivisionError, "float divmod()")); } TEST_F(UnderBuiltinsModuleTest, UnderFloatDivmodWithNanReturnsNan) { HandleScope scope(thread_); Float number(&scope, runtime_->newFloat(3.25)); double nan = std::numeric_limits<double>::quiet_NaN(); ASSERT_TRUE(std::isnan(nan)); Float divisor(&scope, runtime_->newFloat(nan)); Tuple result(&scope, runBuiltin(FUNC(_builtins, _float_divmod), number, divisor)); ASSERT_EQ(result.length(), 2); Float quotient(&scope, result.at(0)); Float remainder(&scope, result.at(1)); EXPECT_TRUE(std::isnan(quotient.value())); EXPECT_TRUE(std::isnan(remainder.value())); } TEST_F(UnderBuiltinsModuleTest, UnderObjectDunderClassSetterWithTypeSelf) { ASSERT_FALSE(runFromCStr(runtime_, R"( class M(type): pass class C(metaclass=M): pass )") .isError()); HandleScope scope(thread_); Type c(&scope, mainModuleAt(runtime_, "C")); Layout previous_layout(&scope, c.instanceLayout()); EXPECT_EQ(previous_layout.id(), c.instanceLayoutId()); ASSERT_FALSE(runFromCStr(runtime_, R"( C.__class__ = type C_instance = C() )") .isError()); EXPECT_NE(c.instanceLayout(), previous_layout); EXPECT_NE(c.instanceLayoutId(), previous_layout.id()); EXPECT_EQ(Layout::cast(c.instanceLayout()).id(), c.instanceLayoutId()); EXPECT_EQ(runtime_->typeOf(*c), runtime_->typeAt(LayoutId::kType)); Object c_inst(&scope, mainModuleAt(runtime_, "C_instance")); EXPECT_EQ(runtime_->typeOf(*c_inst), c); } // TODO(T64924852): Once module.__setattr__ is fixed, write death test for // setting __class__ of module. TEST_F(UnderBuiltinsModuleTest, UnderObjectKeysWithUnassignedNumInObjectAttributes) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __init__(self, p): if p: self.a = 42 i = C(False) )") .isError()); Object i(&scope, mainModuleAt(runtime_, "i")); Object result(&scope, runBuiltin(FUNC(_builtins, _object_keys), i)); ASSERT_TRUE(result.isList()); EXPECT_EQ(List::cast(*result).numItems(), 0); } TEST_F(UnderBuiltinsModuleTest, UnderObjectKeysWithEmptyDictOverflowReturnsKeys) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: pass instance = C() instance.__dict__ = {} )") .isError()); Object instance(&scope, mainModuleAt(runtime_, "instance")); Layout layout(&scope, runtime_->layoutOf(*instance)); ASSERT_TRUE(layout.hasDictOverflow()); Object result(&scope, runBuiltin(FUNC(_builtins, _object_keys), instance)); ASSERT_TRUE(result.isList()); EXPECT_PYLIST_EQ(result, {}); } TEST_F(UnderBuiltinsModuleTest, UnderObjectKeysWithNonEmptyDictOverflowReturnsKeys) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: pass instance = C() instance.__dict__ = {"hello": "world", "foo": "bar"} )") .isError()); Object instance(&scope, mainModuleAt(runtime_, "instance")); Layout layout(&scope, runtime_->layoutOf(*instance)); ASSERT_TRUE(layout.hasDictOverflow()); Object result(&scope, runBuiltin(FUNC(_builtins, _object_keys), instance)); ASSERT_TRUE(result.isList()); EXPECT_PYLIST_EQ(result, {"hello", "foo"}); } TEST_F(UnderBuiltinsModuleTest, UnderObjectKeysWithInObjectAndDictOverflowReturnsKeys) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( def instance(): pass instance.hello = "world" instance.foo = "bar" )") .isError()); Object instance(&scope, mainModuleAt(runtime_, "instance")); Layout layout(&scope, runtime_->layoutOf(*instance)); Tuple in_object(&scope, layout.inObjectAttributes()); ASSERT_GT(in_object.length(), 0); ASSERT_TRUE(layout.hasDictOverflow()); Object result_obj(&scope, runBuiltin(FUNC(_builtins, _object_keys), instance)); ASSERT_TRUE(result_obj.isList()); List result(&scope, *result_obj); EXPECT_GT(result.numItems(), 2); Str hello(&scope, runtime_->newStrFromCStr("hello")); Str foo(&scope, runtime_->newStrFromCStr("foo")); EXPECT_TRUE(listContains(result, hello)); EXPECT_TRUE(listContains(result, foo)); } TEST_F(UnderBuiltinsModuleTest, UnderObjectKeysWithHiddenAttributesDoesNotReturnKey) { HandleScope scope(thread_); LayoutId layout_id = LayoutId::kUserWarning; Object previous_layout(&scope, runtime_->layoutAt(layout_id)); BuiltinAttribute attrs[] = { {ID(__globals__), 0, AttributeFlags::kHidden}, }; Type type(&scope, addBuiltinType(thread_, ID(UserWarning), layout_id, LayoutId::kObject, attrs, /*size=*/kPointerSize, /*basetype=*/true)); Layout layout(&scope, type.instanceLayout()); runtime_->layoutAtPut(layout_id, *layout); Instance instance(&scope, runtime_->newInstance(layout)); Object result_obj(&scope, runBuiltin(FUNC(_builtins, _object_keys), instance)); ASSERT_TRUE(result_obj.isList()); List result(&scope, *result_obj); Str dunder_globals(&scope, runtime_->newStrFromCStr("__globals__")); EXPECT_FALSE(listContains(result, dunder_globals)); EXPECT_EQ(instance.layoutId(), layout.id()); runtime_->layoutAtPut(layout_id, *previous_layout); } TEST_F(UnderBuiltinsModuleTest, UnderInstanceDunderDictSetterCoalescesAffectedLayoutsIntoSingleOne) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: pass c0 = C() c0.foo = 4 c1 = C() c1.bar = 5 c0.__dict__ = {"a": 4} c1.__dict__ = {"b": 4} )") .isError()); Object c0(&scope, mainModuleAt(runtime_, "c0")); Object c1(&scope, mainModuleAt(runtime_, "c1")); EXPECT_EQ(c0.layoutId(), c1.layoutId()); } TEST_F(UnderBuiltinsModuleTest, UnderInstanceOverflowDictAllocatesDictionary) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( def instance(): pass )") .isError()); Object instance_obj(&scope, mainModuleAt(runtime_, "instance")); ASSERT_TRUE(instance_obj.isHeapObject()); Instance instance(&scope, *instance_obj); Layout layout(&scope, runtime_->layoutOf(*instance)); ASSERT_TRUE(layout.hasDictOverflow()); word offset = layout.dictOverflowOffset(); ASSERT_TRUE(instance.instanceVariableAt(offset).isNoneType()); Object result0( &scope, runBuiltin(FUNC(_builtins, _instance_overflow_dict), instance)); ASSERT_EQ(instance.layoutId(), layout.id()); Object overflow_dict(&scope, instance.instanceVariableAt(offset)); EXPECT_TRUE(result0.isDict()); EXPECT_EQ(result0, overflow_dict); Object result1( &scope, runBuiltin(FUNC(_builtins, _instance_overflow_dict), instance)); EXPECT_EQ(result0, result1); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithLittleEndianReturnsSmallInt) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); const byte bytes_array[] = {0xca, 0xfe}; Bytes bytes(&scope, runtime_->newBytesWithAll(bytes_array)); Bool byteorder_big(&scope, Bool::falseObj()); Bool signed_arg(&scope, Bool::falseObj()); Object result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); EXPECT_TRUE(isIntEqualsWord(*result, 0xfeca)); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithLittleEndianReturnsLargeInt) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); const byte bytes_array[] = {0xca, 0xfe, 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd}; Bytes bytes(&scope, runtime_->newBytesWithAll(bytes_array)); Bool byteorder_big(&scope, Bool::falseObj()); Bool signed_arg(&scope, Bool::falseObj()); Int result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); ASSERT_EQ(result.numDigits(), 2); EXPECT_EQ(result.digitAt(0), 0x67452301bebafecaU); EXPECT_EQ(result.digitAt(1), 0xcdab89U); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithBigEndianReturnsSmallInt) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); const byte bytes_array[] = {0xca, 0xfe}; Bytes bytes(&scope, runtime_->newBytesWithAll(bytes_array)); Bool byteorder_big(&scope, Bool::trueObj()); Bool signed_arg(&scope, Bool::falseObj()); Object result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); EXPECT_TRUE(isIntEqualsWord(*result, 0xcafe)); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithBigEndianReturnsLargeInt) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); const byte bytes_array[] = {0xca, 0xfe, 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd}; Bytes bytes(&scope, runtime_->newBytesWithAll(bytes_array)); Bool byteorder_big(&scope, Bool::trueObj()); Bool signed_arg(&scope, Bool::falseObj()); Int result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); ASSERT_EQ(result.numDigits(), 2); EXPECT_EQ(result.digitAt(0), 0xbe0123456789abcdU); EXPECT_EQ(result.digitAt(1), 0xcafebaU); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithEmptyBytes) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll(View<byte>(nullptr, 0))); Bool bo_big_false(&scope, Bool::falseObj()); Bool signed_arg(&scope, Bool::falseObj()); Object result_little( &scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, bo_big_false, signed_arg)); EXPECT_TRUE(isIntEqualsWord(*result_little, 0)); Bool bo_big_true(&scope, Bool::trueObj()); Object result_big( &scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, bo_big_true, signed_arg)); EXPECT_TRUE(isIntEqualsWord(*result_big, 0)); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithNumberWithDigitHighBitSet) { HandleScope scope(thread_); // Test special case where a positive number having a high bit set at the end // of a "digit" needs an extra digit in the LargeInt representation. Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytes(kWordSize, 0xff)); Bool byteorder_big(&scope, Bool::falseObj()); Bool signed_arg(&scope, Bool::falseObj()); Int result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); const uword expected_digits[] = {kMaxUword, 0}; EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithNegativeNumberReturnsSmallInt) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); const byte bytes_array[] = {0xff}; Bytes bytes(&scope, runtime_->newBytesWithAll(bytes_array)); Bool byteorder_big(&scope, Bool::falseObj()); Bool signed_arg(&scope, Bool::trueObj()); Object result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); EXPECT_TRUE(isIntEqualsWord(*result, -1)); } TEST_F(UnderBuiltinsModuleTest, UnderIntFromBytesWithNegativeNumberReturnsLargeInt) { HandleScope scope(thread_); Type int_type(&scope, runtime_->typeAt(LayoutId::kInt)); const byte bytes_array[] = {0xca, 0xfe, 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd}; Bytes bytes(&scope, runtime_->newBytesWithAll(bytes_array)); Bool byteorder_big(&scope, Bool::trueObj()); Bool signed_arg(&scope, Bool::trueObj()); Object result(&scope, runBuiltin(FUNC(_builtins, _int_from_bytes), int_type, bytes, byteorder_big, signed_arg)); const uword expected_digits[] = {0xbe0123456789abcd, 0xffffffffffcafeba}; EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithZeroBaseReturnsCodeLiteral) { HandleScope scope(thread_); const byte view[] = {'0', 'x', 'b', 'a', '5', 'e'}; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytearray array(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, array, view); Int base(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, array, base)); EXPECT_TRUE(isIntEqualsWord(*result, 0xba5e)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithInvalidByteInBytearrayRaisesValueError) { HandleScope scope(thread_); const byte view[] = {'$'}; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytearray array(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, array, view); Int base(&scope, SmallInt::fromWord(36)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, array, base), LayoutId::kValueError, "invalid literal for int() with base 36: b'$'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithInvalidLiteraRaisesValueError) { HandleScope scope(thread_); const byte view[] = {'a'}; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytearray array(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, array, view); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, array, base), LayoutId::kValueError, "invalid literal for int() with base 10: b'a'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithInvalidByteRaisesValueError) { HandleScope scope(thread_); const byte view[] = {'$'}; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll(view)); Int base(&scope, SmallInt::fromWord(36)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 36: b'$'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithInvalidLiteralRaisesValueError) { HandleScope scope(thread_); const byte view[] = {'8', '6'}; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll(view)); Int base(&scope, SmallInt::fromWord(7)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 7: b'86'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithBytesSubclassReturnsSmallInt) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class Foo(bytes): pass foo = Foo(b"42") )") .isError()); Object type(&scope, runtime_->typeAt(LayoutId::kInt)); Object bytes(&scope, mainModuleAt(runtime_, "foo")); Object base(&scope, SmallInt::fromWord(21)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(86)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithZero) { HandleScope scope(thread_); const byte src[] = {'0'}; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll(src)); Int base(&scope, SmallInt::fromWord(10)); Object result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base)); EXPECT_TRUE(isIntEqualsWord(*result, 0)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLargeInt) { HandleScope scope(thread_); const byte src[] = "1844674407370955161500"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); Object result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base)); ASSERT_FALSE(result.isError()); EXPECT_TRUE(result.isInt()); const uword digits[] = {0xffffffffffffff9c, 0x63}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLargeInt2) { HandleScope scope(thread_); const byte src[] = "46116860184273879030"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); Object result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base)); ASSERT_FALSE(result.isError()); EXPECT_TRUE(result.isInt()); const uword digits[] = {0x7ffffffffffffff6, 0x2}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLargeIntWithInvalidDigitRaisesValueError) { HandleScope scope(thread_); const byte src[] = "461168601$84273879030"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 10: b'461168601$84273879030'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLeadingPlusReturnsInt) { HandleScope scope(thread_); const byte src[] = "+46116860184273879030"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); Int result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base)); ASSERT_FALSE(result.isError()); EXPECT_TRUE(result.isInt()); const uword digits[] = {0x7ffffffffffffff6, 0x2}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithDoubleLeadingPlusRaisesValueError) { HandleScope scope(thread_); const byte src[] = "++1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 10: b'++1'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLeadingNegAndSpaceReturnsInt) { HandleScope scope(thread_); const byte src[] = " -46116860184273879030"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); Int result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base)); ASSERT_FALSE(result.isError()); EXPECT_TRUE(result.isInt()); const uword digits[] = {0x800000000000000a, 0xfffffffffffffffd}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithDoubleLeadingNegRaisesValueError) { HandleScope scope(thread_); const byte src[] = "--1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 10: b'--1'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithHexPrefixAndBaseZeroReturnsInt) { HandleScope scope(thread_); const byte src[] = "0x1f"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(0)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(31)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithHexPrefixAndBaseSixteenReturnsInt) { HandleScope scope(thread_); const byte src[] = "0x1f"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(16)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(31)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithHexPrefixAndBaseNineRaisesValueError) { HandleScope scope(thread_); const byte src[] = "0x1f"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(9)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 9: b'0x1f'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithBaseThreeReturnsInt) { HandleScope scope(thread_); const byte src[] = "221"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(3)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(25)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithUnderscoreReturnsInt) { HandleScope scope(thread_); const byte src[] = "1_000_000"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(1000000)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLeadingUnderscoreRaisesValueError) { HandleScope scope(thread_); const byte src[] = "_1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 0: b'_1'")); } TEST_F( UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithLeadingUnderscoreAndPrefixAndBaseReturnsInt) { HandleScope scope(thread_); const byte src[] = "0b_1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(2)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(1)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithTrailingUnderscoreRaisesValueError) { HandleScope scope(thread_); const byte src[] = "1_000_"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 0: b'1_000_'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithDoubleUnderscoreRaisesValueError) { HandleScope scope(thread_); const byte src[] = "1__000"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), LayoutId::kValueError, "invalid literal for int() with base 0: b'1__000'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithWhitespaceOnLeftReturnsInt) { HandleScope scope(thread_); const byte src[] = " \t\n\t\v-123"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(-123)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithWhitespaceOnRightReturnsInt) { HandleScope scope(thread_); const byte src[] = "-234 \t \f \n\t"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(-234)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithWhitespaceOnLeftAndRightReturnsInt) { HandleScope scope(thread_); const byte src[] = " \n\t\r\n +345 \t \n\t"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Bytes bytes(&scope, runtime_->newBytesWithAll({src, ARRAYSIZE(src) - 1})); Int base(&scope, SmallInt::fromWord(10)); EXPECT_EQ( runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, bytes, base), SmallInt::fromWord(345)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithMemoryviewReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {'-', '1', '2'}; MemoryView memoryview(&scope, newMemoryView(bytes, "b")); MemoryView memoryview_slice( &scope, memoryviewGetslice(thread_, memoryview, /*start=*/1, /*stop=*/2, /*step=*/1)); Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Int base(&scope, SmallInt::fromWord(10)); EXPECT_EQ(runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, memoryview_slice, base), SmallInt::fromWord(1)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromByteslikeWithMemoryviewSliceReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {'-', '1', '2'}; Object memoryview(&scope, newMemoryView(bytes, "b")); Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Int base(&scope, SmallInt::fromWord(10)); EXPECT_EQ(runBuiltin(FUNC(_builtins, _int_new_from_byteslike), type, memoryview, base), SmallInt::fromWord(-12)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromIntWithBoolReturnsSmallInt) { HandleScope scope(thread_); Object type(&scope, runtime_->typeAt(LayoutId::kInt)); Object fls(&scope, Bool::falseObj()); Object tru(&scope, Bool::trueObj()); Object false_result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_int), type, fls)); Object true_result(&scope, runBuiltin(FUNC(_builtins, _int_new_from_int), type, tru)); EXPECT_EQ(false_result, SmallInt::fromWord(0)); EXPECT_EQ(true_result, SmallInt::fromWord(1)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromIntWithSubClassReturnsValueOfSubClass) { ASSERT_FALSE(runFromCStr(runtime_, R"( class SubInt(int): def __new__(cls, value): self = super(SubInt, cls).__new__(cls, value) self.name = "subint instance" return self result = SubInt(50) )") .isError()); HandleScope scope(thread_); Object result(&scope, mainModuleAt(runtime_, "result")); EXPECT_FALSE(result.isInt()); EXPECT_TRUE(isIntEqualsWord(*result, 50)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithZeroBaseReturnsCodeLiteral) { HandleScope scope(thread_); const char* src = "1985"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 1985)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithInvalidCharRaisesValueError) { HandleScope scope(thread_); const char* src = "$"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(36)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 36: '$'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithInvalidLiteralRaisesValueError) { HandleScope scope(thread_); const char* src = "305"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(4)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 4: '305'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithInvalidLiteralRaisesValueErrorBaseSixteen) { HandleScope scope(thread_); const char* src = "g"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: 'g'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeInt) { HandleScope scope(thread_); const char* src = "1844674407370955161500"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); ASSERT_FALSE(result.isError()); EXPECT_TRUE(result.isInt()); const uword digits[] = {0xffffffffffffff9c, 0x63}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeInt2) { HandleScope scope(thread_); const char* src = "46116860184273879030"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); ASSERT_FALSE(result.isError()); EXPECT_TRUE(result.isInt()); const uword digits[] = {0x7ffffffffffffff6, 0x2}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntWithInvalidDigitRaisesValueError) { HandleScope scope(thread_); const char* src = "461168601$84273879030"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: '461168601$84273879030'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithOnlySignRaisesValueError) { HandleScope scope(thread_); const char* src = "-"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: '-'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLengthOneInfersBase10) { HandleScope scope(thread_); const char* src = "8"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 8)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLengthOneBase10) { HandleScope scope(thread_); const char* src = "8"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 8)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntBaseTwo) { HandleScope scope(thread_); const char* src = "100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(2)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 4)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntInfersBaseTen) { HandleScope scope(thread_); const char* src = "100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 100)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLeadingSpacesRemovesSpaces) { HandleScope scope(thread_); const char* src = " 100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 100)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithOnlySpacesRaisesValueError) { HandleScope scope(thread_); const char* src = " "; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: ' '")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithPlusReturnsPositiveInt) { HandleScope scope(thread_); const char* src = "+100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 100)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithTwoPlusSignsRaisesValueError) { HandleScope scope(thread_); const char* src = "++100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '++100'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntBaseEight) { HandleScope scope(thread_); const char* src = "0o77712371237123712371237123777"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(8)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); const uword digits[] = {0xa7ca7ca7ca7ca7ff, 0x7fca7c}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntInfersBaseEight) { HandleScope scope(thread_); const char* src = "0o77712371237123712371237123777"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); const uword digits[] = {0xa7ca7ca7ca7ca7ff, 0x7fca7c}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithOnlyPrefixRaisesValueError) { HandleScope scope(thread_); const char* src = "0x"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '0x'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithMinusAndPrefixRaisesValueError) { HandleScope scope(thread_); const char* src = "-0x"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '-0x'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithPlusAndPrefixRaisesValueError) { HandleScope scope(thread_); const char* src = "+0x"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '+0x'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithJustPrefixAndUnderscoreRaisesValueError) { HandleScope scope(thread_); const char* src = "0x_"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '0x_'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithUnderscoreIgnoresUnderscore) { HandleScope scope(thread_); const char* src = "0x_deadbeef"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 0xdeadbeef)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithUnderscoresIgnoresUnderscoresBaseSixteen) { HandleScope scope(thread_); const char* src = "0x_d_e_a_d_b_eef"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 0xdeadbeef)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithUnderscoresIgnoresUnderscoresBaseTen) { HandleScope scope(thread_); const char* src = "100_000_000_000"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 100000000000)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLeadingUnderscoreBaseTenRaisesValueError) { HandleScope scope(thread_); const char* src = "_100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: '_100'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithTrailingUnderscoreBaseTenRaisesValueError) { HandleScope scope(thread_); const char* src = "100_"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: '100_'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithDoubleUnderscoreBaseTenRaisesValueError) { HandleScope scope(thread_); const char* src = "1__00"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(10)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: '1__00'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLeadingUnderscoreNoPrefixRaisesValueError) { HandleScope scope(thread_); const char* src = "_abc"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '_abc'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithNegativeZeroReturnsZero) { HandleScope scope(thread_); const char* src = "-0"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 0)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithTwoMinusSignsRaisesValueError) { HandleScope scope(thread_); const char* src = "--100"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 16: '--100'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithPositiveZeroReturnsZero) { HandleScope scope(thread_); const char* src = "+0"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 0)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithEmptyStringRaisesValueError) { HandleScope scope(thread_); Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, Str::empty()); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: ''")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithHexLiteralNoPrefixRaisesValueError) { HandleScope scope(thread_); const char* src = "a"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 10: 'a'")); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntBaseSixteen) { HandleScope scope(thread_); const char* src = "0x8000000000000000"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); const uword digits[] = {0x8000000000000000, 0x0}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntInfersBaseSixteen) { HandleScope scope(thread_); const char* src = "0x8000000000000000"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); const uword digits[] = {0x8000000000000000, 0x0}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntBaseSixteenWithLetters) { HandleScope scope(thread_); const char* src = "0x80000000DEADBEEF"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); const uword digits[] = {0x80000000deadbeef, 0x0}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithLargeIntInfersBaseSixteenWithLetters) { HandleScope scope(thread_); const char* src = "0x80000000DEADBEEF"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); const uword digits[] = {0x80000000deadbeef, 0x0}; EXPECT_TRUE(isIntEqualsDigits(*result, digits)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithBinaryLiteralBaseZeroReturnsOne) { HandleScope scope(thread_); const char* src = "0b1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(0)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 1)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithBinaryLiteralBaseTwoReturnsOne) { HandleScope scope(thread_); const char* src = "0b1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(2)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 1)); } TEST_F( UnderBuiltinsModuleTest, UnderIntNewFromStrWithBinaryLiteralBaseSixteenReturnsOneHundredSeventySeven) { HandleScope scope(thread_); const char* src = "0b1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 177)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithBinaryLiteralBaseSixteenReturnsEleven) { HandleScope scope(thread_); const char* src = "0b"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(16)); Object result( &scope, runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base)); EXPECT_TRUE(isIntEqualsWord(*result, 11)); } TEST_F(UnderBuiltinsModuleTest, UnderIntNewFromStrWithBinaryLiteralBaseEightRaisesValueError) { HandleScope scope(thread_); const char* src = "0b1"; Type type(&scope, runtime_->typeAt(LayoutId::kInt)); Str str(&scope, runtime_->newStrFromCStr(src)); Int base(&scope, SmallInt::fromWord(8)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _int_new_from_str), type, str, base), LayoutId::kValueError, "invalid literal for int() with base 8: '0b1'")); } TEST_F(UnderBuiltinsModuleTest, UnderListAppendAppendsObject) { HandleScope scope(thread_); List list(&scope, runtime_->newList()); Object value0(&scope, runtime_->newInt(42)); Object value1(&scope, runtime_->newStrFromCStr("foo")); EXPECT_EQ(list.numItems(), 0); EXPECT_TRUE( runBuiltin(FUNC(_builtins, _list_append), list, value0).isNoneType()); EXPECT_EQ(list.numItems(), 1); EXPECT_TRUE( runBuiltin(FUNC(_builtins, _list_append), list, value1).isNoneType()); ASSERT_EQ(list.numItems(), 2); EXPECT_EQ(list.at(0), value0); EXPECT_EQ(list.at(1), value1); } TEST_F(UnderBuiltinsModuleTest, UnderListCheckExactWithExactListReturnsTrue) { HandleScope scope(thread_); Object obj(&scope, runtime_->newList()); EXPECT_EQ(runBuiltin(FUNC(_builtins, _list_check_exact), obj), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderListCheckExactWithListSubclassReturnsFalse) { ASSERT_FALSE(runFromCStr(runtime_, R"( class C(list): pass obj = C() )") .isError()); HandleScope scope(thread_); Object obj(&scope, mainModuleAt(runtime_, "obj")); EXPECT_EQ(runBuiltin(FUNC(_builtins, _list_check_exact), obj), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderListDelitemWithNegativeIndexRemovesRelativeToEnd) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Object idx(&scope, SmallInt::fromWord(-3)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delitem), list, idx).isNoneType()); EXPECT_PYLIST_EQ(list, {2, 3}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelitemWithLastIndexRemovesLastItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Object idx(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delitem), list, idx).isNoneType()); EXPECT_PYLIST_EQ(list, {0}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelitemWithFirstIndexRemovesFirstItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Object idx(&scope, SmallInt::fromWord(0)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delitem), list, idx).isNoneType()); EXPECT_PYLIST_EQ(list, {1}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelitemWithNegativeFirstIndexRemovesFirstItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Object idx(&scope, SmallInt::fromWord(-2)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delitem), list, idx).isNoneType()); EXPECT_PYLIST_EQ(list, {1}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelitemWithNegativeLastIndexRemovesLastItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Object idx(&scope, SmallInt::fromWord(-1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delitem), list, idx).isNoneType()); EXPECT_PYLIST_EQ(list, {0}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelitemWithNumberGreaterThanSmallIntMaxDoesNotCrash) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Int big(&scope, runtime_->newInt(SmallInt::kMaxValue + 100)); EXPECT_TRUE(raised(runBuiltin(FUNC(_builtins, _list_delitem), list, big), LayoutId::kIndexError)); EXPECT_PYLIST_EQ(list, {0, 1}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceRemovesItems) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(1)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {2, 3}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceRemovesFirstItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(1)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {1}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceRemovesLastItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 2)); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(2)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {0}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceWithStopEqualsLengthRemovesTrailingItems) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(3)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {1}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceWithStartEqualsZeroRemovesStartingItems) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(1)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {2, 3}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceWithStartEqualsZeroAndStopEqualsLengthRemovesAllItems) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(3)); Int step(&scope, SmallInt::fromWord(1)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_EQ(list.numItems(), 0); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceWithStepEqualsTwoDeletesEveryEvenItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 5)); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(5)); Int step(&scope, SmallInt::fromWord(2)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {1, 3}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceWithStepEqualsTwoDeletesEveryOddItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 5)); Int start(&scope, SmallInt::fromWord(1)); Int stop(&scope, SmallInt::fromWord(5)); Int step(&scope, SmallInt::fromWord(2)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {0, 2, 4}); } TEST_F(UnderBuiltinsModuleTest, UnderListDelsliceWithStepGreaterThanLengthDeletesOneItem) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 5)); Int start(&scope, SmallInt::fromWord(0)); Int stop(&scope, SmallInt::fromWord(5)); Int step(&scope, SmallInt::fromWord(1000)); ASSERT_TRUE( runBuiltin(FUNC(_builtins, _list_delslice), list, start, stop, step) .isNoneType()); EXPECT_PYLIST_EQ(list, {1, 2, 3, 4}); } TEST_F(UnderBuiltinsModuleTest, UnderListGetitemWithNegativeIndex) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Object idx(&scope, SmallInt::fromWord(-3)); Object result(&scope, runBuiltin(FUNC(_builtins, _list_getitem), list, idx)); EXPECT_TRUE(isIntEqualsWord(*result, 1)); } TEST_F(UnderBuiltinsModuleTest, UnderListGetitemWithInvalidNegativeIndexRaisesIndexError) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Object idx(&scope, SmallInt::fromWord(-4)); EXPECT_TRUE( raisedWithStr(runBuiltin(FUNC(_builtins, _list_getitem), list, idx), LayoutId::kIndexError, "list index out of range")); } TEST_F(UnderBuiltinsModuleTest, UnderListGetitemWithInvalidPositiveIndexRaisesIndexError) { HandleScope scope(thread_); List list(&scope, listFromRange(1, 4)); Object idx(&scope, SmallInt::fromWord(3)); EXPECT_TRUE( raisedWithStr(runBuiltin(FUNC(_builtins, _list_getitem), list, idx), LayoutId::kIndexError, "list index out of range")); } TEST_F(UnderBuiltinsModuleTest, UnderListSwapSwapsItemsAtIndices) { HandleScope scope(thread_); List list(&scope, listFromRange(0, 4)); Object i(&scope, SmallInt::fromWord(1)); Object j(&scope, SmallInt::fromWord(2)); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _list_swap), list, i, j).isNoneType()); EXPECT_PYLIST_EQ(list, {0, 2, 1, 3}); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatbReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xab, 0xc5}; Object view(&scope, newMemoryView(bytes, "b")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, -59)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatBReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xee, 0xd8}; Object view(&scope, newMemoryView(bytes, "B")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 216)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatcReturnsBytes) { HandleScope scope(thread_); const byte bytes[] = {0x03, 0x62}; Object view(&scope, newMemoryView(bytes, "c")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); const byte expected_bytes[] = {0x62}; EXPECT_TRUE(isBytesEqualsBytes(result, expected_bytes)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormathReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xcd, 0x2c, 0x5c, 0xfc}; Object view(&scope, newMemoryView(bytes, "h")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, -932)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatHReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xb2, 0x11, 0x94, 0xc0}; Object view(&scope, newMemoryView(bytes, "H")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 49300)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatiReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0x30, 0x8A, 0x43, 0xF2, 0xE1, 0xD6, 0x56, 0xE4}; Object view(&scope, newMemoryView(bytes, "i")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, -464070943)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatAtiReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0x30, 0x8A, 0x43, 0xF2, 0xE1, 0xD6, 0x56, 0xE4}; Object view(&scope, newMemoryView(bytes, "@i")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, -464070943)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatIReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0x2, 0xBE, 0xA8, 0x3D, 0x74, 0x18, 0xEB, 0x8}; Object view(&scope, newMemoryView(bytes, "I")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 149624948)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatlReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xD8, 0x76, 0x97, 0xD1, 0x8B, 0xA1, 0xD2, 0x62, 0xD9, 0xD2, 0x50, 0x47, 0xC0, 0xA8, 0xB7, 0x81}; Object view(&scope, newMemoryView(bytes, "l")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, -9099618978295131431)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatLReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0x24, 0x37, 0x8B, 0x51, 0xCB, 0xB2, 0x16, 0xFB, 0xA6, 0xA9, 0x49, 0xB3, 0x59, 0x6A, 0x48, 0x62}; Object view(&scope, newMemoryView(bytes, "L")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 7082027347532687782)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatqReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0x7, 0xE2, 0x42, 0x9E, 0x8F, 0xBF, 0xDB, 0x1B, 0x8C, 0x1C, 0x34, 0x40, 0x86, 0x41, 0x2B, 0x23}; Object view(&scope, newMemoryView(bytes, "q")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 2534191260184616076)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatQReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xD9, 0xC6, 0xD2, 0x40, 0xBD, 0x19, 0xA9, 0xC8, 0x8A, 0x1, 0x8B, 0xAF, 0x15, 0x36, 0xC7, 0xBD}; Object view(&scope, newMemoryView(bytes, "Q")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); const uword expected_digits[] = {0xbdc73615af8b018aul, 0}; EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatnReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0xF2, 0x6F, 0xFA, 0x8B, 0x93, 0xC0, 0xED, 0x9D, 0x6D, 0x7C, 0xE3, 0xDC, 0x26, 0xEF, 0xB8, 0xEB}; Object view(&scope, newMemoryView(bytes, "n")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, -1461155128888034195l)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatNReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0x6B, 0x8F, 0x6, 0xA2, 0xE0, 0x13, 0x88, 0x47, 0x7E, 0xB6, 0x40, 0x7E, 0x6B, 0x2, 0x9, 0xC0}; Object view(&scope, newMemoryView(bytes, "N")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); const uword expected_digits[] = {0xc009026b7e40b67eul, 0}; EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatfReturnsFloat) { HandleScope scope(thread_); const byte bytes[] = {0x67, 0x32, 0x23, 0x31, 0xB9, 0x70, 0xBC, 0x83}; Object view(&scope, newMemoryView(bytes, "f")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isFloatEqualsDouble( *result, std::strtod("-0x1.78e1720000000p-120", nullptr))); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatdReturnsFloat) { HandleScope scope(thread_); const byte bytes[] = {0xEA, 0x43, 0xAD, 0x6F, 0x9D, 0x31, 0xE, 0x96, 0x28, 0x80, 0x1A, 0xD, 0x87, 0xC, 0xAC, 0x4B}; Object view(&scope, newMemoryView(bytes, "d")); Int index(&scope, runtime_->newInt(1)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isFloatEqualsDouble( *result, std::strtod("0x1.c0c870d1a8028p+187", nullptr))); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatQuestionmarkReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {0x92, 0xE1, 0x57, 0xEA, 0x81, 0xA8}; Object view(&scope, newMemoryView(bytes, "?")); Int index(&scope, runtime_->newInt(3)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_EQ(result, Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithFormatQuestionmarkReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {0x92, 0xE1, 0, 0xEA, 0x81, 0xA8}; Object view(&scope, newMemoryView(bytes, "?")); Int index(&scope, runtime_->newInt(2)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_EQ(result, Bool::falseObj()); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithNegativeIndexReturnsInt) { HandleScope scope(thread_); const byte bytes[] = {0, 1, 2, 3, 4, 5, 6, 7}; Object view(&scope, newMemoryView(bytes, "h")); Int index(&scope, runtime_->newInt(-2)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 0x504)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithTooBigIndexRaisesIndexError) { HandleScope scope(thread_); const byte bytes[] = {0, 1, 2, 3, 4, 5, 6, 7}; Object view(&scope, newMemoryView(bytes, "I")); Int index(&scope, runtime_->newInt(2)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE( raisedWithStr(*result, LayoutId::kIndexError, "index out of bounds")); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithOverflowingIndexRaisesIndexError) { HandleScope scope(thread_); const byte bytes[] = {0, 1, 2, 3, 4, 5, 6, 7}; Object view(&scope, newMemoryView(bytes, "I")); Int index(&scope, runtime_->newInt(kMaxWord / 2)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE( raisedWithStr(*result, LayoutId::kIndexError, "index out of bounds")); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithMemoryBufferReadsMemory) { HandleScope scope(thread_); const word length = 5; byte memory[length]; for (word i = 0; i < length; i++) { memory[i] = i; } Object none(&scope, NoneType::object()); Object view(&scope, runtime_->newMemoryViewFromCPtr( thread_, none, memory, length, ReadOnly::ReadOnly)); Int idx(&scope, SmallInt::fromWord(0)); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _memoryview_getitem), view, idx), 0)); idx = Int::cast(SmallInt::fromWord(1)); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _memoryview_getitem), view, idx), 1)); idx = Int::cast(SmallInt::fromWord(2)); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _memoryview_getitem), view, idx), 2)); idx = Int::cast(SmallInt::fromWord(3)); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _memoryview_getitem), view, idx), 3)); idx = Int::cast(SmallInt::fromWord(4)); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _memoryview_getitem), view, idx), 4)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewGetitemWithBytearrayReadsFromMutableBytes) { Thread* thread = Thread::current(); HandleScope scope(thread); Type type(&scope, runtime_->typeAt(LayoutId::kMemoryView)); Bytearray bytearray(&scope, runtime_->newBytearray()); const byte byte_array[] = {0xce}; runtime_->bytearrayExtend(thread, bytearray, byte_array); Object result_obj(&scope, runBuiltin(METH(memoryview, __new__), type, bytearray)); ASSERT_TRUE(result_obj.isMemoryView()); Object view(&scope, *result_obj); Int index(&scope, runtime_->newInt(0)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_getitem), view, index)); EXPECT_TRUE(isIntEqualsWord(*result, 0xce)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewItemsizeReturnsSizeOfMemoryItems) { HandleScope scope(thread_); Bytes bytes(&scope, runtime_->newBytes(5, 'x')); MemoryView view(&scope, runtime_->newMemoryView(thread_, bytes, bytes, 5, ReadOnly::ReadOnly)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_itemsize), view)); EXPECT_TRUE(isIntEqualsWord(*result, 1)); } TEST_F(UnderBuiltinsModuleTest, UnderMemoryViewNbytesReturnsSizeOfMemoryView) { HandleScope scope(thread_); Bytes bytes(&scope, runtime_->newBytes(5, 'x')); MemoryView view(&scope, runtime_->newMemoryView(thread_, bytes, bytes, 5, ReadOnly::ReadOnly)); Object result(&scope, runBuiltin(FUNC(_builtins, _memoryview_nbytes), view)); EXPECT_TRUE(isIntEqualsWord(*result, 5)); } TEST_F(UnderBuiltinsModuleTest, UnderModuleDirListWithFilteredOutPlaceholders) { HandleScope scope(thread_); Str module_name(&scope, runtime_->newStrFromCStr("module")); Module module(&scope, runtime_->newModule(module_name)); attributeDictInit(thread_, module); Object foo(&scope, Runtime::internStrFromCStr(thread_, "foo")); Object bar(&scope, Runtime::internStrFromCStr(thread_, "bar")); Object baz(&scope, Runtime::internStrFromCStr(thread_, "baz")); Str value(&scope, runtime_->newStrFromCStr("value")); moduleAtPut(thread_, module, foo, value); moduleAtPut(thread_, module, bar, value); moduleAtPut(thread_, module, baz, value); ValueCell::cast(moduleValueCellAt(thread_, module, bar)).makePlaceholder(); List keys(&scope, runBuiltin(FUNC(_builtins, _module_dir), module)); EXPECT_EQ(keys.numItems(), 2); EXPECT_EQ(keys.at(0), *foo); EXPECT_EQ(keys.at(1), *baz); } TEST_F(UnderBuiltinsModuleTest, UnderObjectTypeHasattrWithNonexistentAttrReturnsFalse) { HandleScope scope(thread_); Object obj(&scope, SmallInt::fromWord(0)); Str name(&scope, runtime_->newStrFromCStr("__foo_bar_baz__")); Object result(&scope, runBuiltin(FUNC(_builtins, _object_type_hasattr), obj, name)); EXPECT_EQ(result, Bool::falseObj()); EXPECT_FALSE(thread_->hasPendingException()); } TEST_F(UnderBuiltinsModuleTest, UnderObjectTypeHasattrWithInstanceAttrReturnsFalse) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __init__(self): self.foobarbaz = 5 obj = C() )") .isError()); Object obj(&scope, mainModuleAt(runtime_, "obj")); Str name(&scope, runtime_->newStrFromCStr("foobarbaz")); Object result(&scope, runBuiltin(FUNC(_builtins, _object_type_hasattr), obj, name)); EXPECT_EQ(result, Bool::falseObj()); EXPECT_FALSE(thread_->hasPendingException()); } TEST_F(UnderBuiltinsModuleTest, UnderObjectTypeHasattrWithExistentAttrReturnsTrue) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: foobarbaz = 5 obj = C() )") .isError()); Object obj(&scope, mainModuleAt(runtime_, "obj")); Str name(&scope, runtime_->newStrFromCStr("foobarbaz")); Object result(&scope, runBuiltin(FUNC(_builtins, _object_type_hasattr), obj, name)); EXPECT_EQ(result, Bool::trueObj()); EXPECT_FALSE(thread_->hasPendingException()); } TEST_F(UnderBuiltinsModuleTest, UnderObjectTypeHasattrWithRaisingDescriptorDoesNotRaise) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class Desc: def __get__(self, obj, type): raise UserWarning("foo") class C: foobarbaz = Desc() obj = C() )") .isError()); Object obj(&scope, mainModuleAt(runtime_, "obj")); Str name(&scope, runtime_->newStrFromCStr("foobarbaz")); Object result(&scope, runBuiltin(FUNC(_builtins, _object_type_hasattr), obj, name)); EXPECT_EQ(result, Bool::trueObj()); EXPECT_FALSE(thread_->hasPendingException()); } TEST_F(UnderBuiltinsModuleTest, UnderOsWriteWithBadFdRaisesOSError) { HandleScope scope(thread_); Int fd(&scope, SmallInt::fromWord(-1)); const byte buf[] = {0x1, 0x2}; Bytes bytes_buf(&scope, runtime_->newBytesWithAll(buf)); EXPECT_TRUE(raised(runBuiltin(FUNC(_builtins, _os_write), fd, bytes_buf), LayoutId::kOSError)); } TEST_F(UnderBuiltinsModuleTest, UnderOsWriteWithFdNotOpenedForWritingRaisesOSError) { HandleScope scope(thread_); int fds[2]; int result = ::pipe(fds); ASSERT_EQ(result, 0); Int fd(&scope, SmallInt::fromWord(fds[0])); const byte buf[] = {0x1, 0x2}; Bytes bytes_buf(&scope, runtime_->newBytesWithAll(buf)); EXPECT_TRUE(raised(runBuiltin(FUNC(_builtins, _os_write), fd, bytes_buf), LayoutId::kOSError)); ::close(fds[0]); ::close(fds[1]); } TEST_F(UnderBuiltinsModuleTest, UnderOsWriteWritesSizeBytes) { HandleScope scope(thread_); int fds[2]; int result = ::pipe(fds); ASSERT_EQ(result, 0); Int fd(&scope, SmallInt::fromWord(fds[1])); byte to_write[] = "hello"; word count = std::strlen(reinterpret_cast<char*>(to_write)); Bytes bytes_buf(&scope, runtime_->newBytesWithAll(View<byte>(to_write, count))); Object result_obj(&scope, runBuiltin(FUNC(_builtins, _os_write), fd, bytes_buf)); EXPECT_TRUE(isIntEqualsWord(*result_obj, count)); ::close(fds[1]); // Send EOF std::unique_ptr<char[]> buf(new char[count + 1]{0}); result = ::read(fds[0], buf.get(), count); EXPECT_EQ(result, count); EXPECT_STREQ(buf.get(), reinterpret_cast<char*>(to_write)); ::close(fds[0]); } TEST_F(UnderBuiltinsModuleTest, UnderOsWriteWritesSizeMemoryView) { HandleScope scope(thread_); int fds[2]; int result = ::pipe(fds); ASSERT_EQ(result, 0); Int fd(&scope, SmallInt::fromWord(fds[1])); const byte bytes[] = "hello_there"; MemoryView memoryview(&scope, newMemoryView(bytes, "b")); MemoryView memoryview_slice( &scope, memoryviewGetslice(thread_, memoryview, /*start=*/0, /*stop=*/5, /*step=*/1)); Object result_obj( &scope, runBuiltin(FUNC(_builtins, _os_write), fd, memoryview_slice)); EXPECT_TRUE(isIntEqualsWord(*result_obj, 5)); ::close(fds[1]); // Send EOF std::unique_ptr<char[]> buf(new char[6]{0}); result = ::read(fds[0], buf.get(), 5); EXPECT_EQ(result, 5); EXPECT_STREQ(buf.get(), "hello"); ::close(fds[0]); } TEST_F(UnderBuiltinsModuleTest, UnderStrCompareDigestWithNonASCIIRaisesTypeError) { HandleScope scope(thread_); Str left(&scope, runtime_->newStrFromCStr("foo\u00E4")); Str right(&scope, runtime_->newStrFromCStr("foo\u00E4")); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _str_compare_digest), left, right), LayoutId::kTypeError, "comparing strings with non-ASCII characters is not supported")); } TEST_F(UnderBuiltinsModuleTest, UnderStrCountWithStartAndEndSearchesWithinBounds) { HandleScope scope(thread_); Str haystack(&scope, runtime_->newStrFromCStr("ofoodo")); Str needle(&scope, runtime_->newStrFromCStr("o")); Object start(&scope, SmallInt::fromWord(2)); Object end(&scope, SmallInt::fromWord(4)); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _str_count), haystack, needle, start, end), 2)); } TEST_F(UnderBuiltinsModuleTest, UnderStrCountWithNoneStartStartsFromZero) { HandleScope scope(thread_); Str haystack(&scope, runtime_->newStrFromCStr("foo")); Str needle(&scope, runtime_->newStrFromCStr("o")); Object start(&scope, NoneType::object()); Object end(&scope, SmallInt::fromWord(haystack.codePointLength())); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _str_count), haystack, needle, start, end), 2)); } TEST_F(UnderBuiltinsModuleTest, UnderStrCountWithNoneEndSetsEndToHaystackLength) { HandleScope scope(thread_); Str haystack(&scope, runtime_->newStrFromCStr("foo")); Str needle(&scope, runtime_->newStrFromCStr("o")); Object start(&scope, SmallInt::fromWord(0)); Object end(&scope, NoneType::object()); EXPECT_TRUE(isIntEqualsWord( runBuiltin(FUNC(_builtins, _str_count), haystack, needle, start, end), 2)); } TEST_F(UnderBuiltinsModuleTest, UnderStrFromStrWithStrTypeReturnsValueOfStrType) { ASSERT_FALSE(runFromCStr(runtime_, R"( result = _str_from_str(str, 'value') )") .isError()); HandleScope scope(thread_); Object result(&scope, mainModuleAt(runtime_, "result")); ASSERT_TRUE(runtime_->isInstanceOfStr(*result)); EXPECT_TRUE(result.isStr()); } TEST_F(UnderBuiltinsModuleTest, UnderStrFromStrWithSubClassTypeReturnsValueOfSubClassType) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Sub(str): pass result = _str_from_str(Sub, 'value') )") .isError()); HandleScope scope(thread_); Object result(&scope, mainModuleAt(runtime_, "result")); Object sub(&scope, mainModuleAt(runtime_, "Sub")); EXPECT_EQ(runtime_->typeOf(*result), sub); EXPECT_TRUE(isStrEqualsCStr(*result, "value")); } TEST_F(UnderBuiltinsModuleTest, UnderStrCountWithStrNeedleSubClassTypeReturnsSubstr) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Sub(str): pass result = Sub("value u") count = result.count('u') )") .isError()); HandleScope scope(thread_); Object count(&scope, mainModuleAt(runtime_, "count")); EXPECT_TRUE(isIntEqualsWord(*count, 2)); } TEST_F(UnderBuiltinsModuleTest, UnderStrCountWithSubNeedleSubClassTypeReturnsSubstr) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Sub(str): pass result = Sub("value") count = result.count(result) )") .isError()); HandleScope scope(thread_); Object count(&scope, mainModuleAt(runtime_, "count")); EXPECT_TRUE(isIntEqualsWord(*count, 1)); } TEST_F(UnderBuiltinsModuleTest, UnderStrGetitemWithSubClassTypeReturnsSubstr) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Sub(str): pass result = Sub("value") result = result[:2] )") .isError()); HandleScope scope(thread_); Object result(&scope, mainModuleAt(runtime_, "result")); EXPECT_TRUE(isStrEqualsCStr(*result, "va")); } TEST_F(UnderBuiltinsModuleTest, UnderStrArrayClearSetsNumItemsToZero) { HandleScope scope(thread_); StrArray self(&scope, runtime_->newStrArray()); Str other(&scope, runtime_->newStrFromCStr("hello")); runtime_->strArrayAddStr(thread_, self, other); ASSERT_EQ(self.numItems(), 5); EXPECT_TRUE(runBuiltin(FUNC(_builtins, _str_array_clear), self).isNoneType()); EXPECT_EQ(self.numItems(), 0); // Make sure that str does not show up again other = runtime_->newStrFromCStr("abcd"); runtime_->strArrayAddStr(thread_, self, other); EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(self), "abcd")); } TEST_F(UnderBuiltinsModuleTest, UnderStrArrayIaddWithStrReturnsStrArray) { HandleScope scope(thread_); StrArray self(&scope, runtime_->newStrArray()); const char* test_str = "hello"; Str other(&scope, runtime_->newStrFromCStr(test_str)); StrArray result(&scope, runBuiltin(FUNC(_builtins, _str_array_iadd), self, other)); EXPECT_TRUE(isStrEqualsCStr(runtime_->strFromStrArray(result), test_str)); EXPECT_EQ(self, result); } TEST_F(UnderBuiltinsModuleTest, UnderStrJoinWithNonStrRaisesTypeError) { HandleScope scope(thread_); Str sep(&scope, runtime_->newStrFromCStr(",")); Object obj1(&scope, runtime_->newStrFromCStr("foo")); Object obj2(&scope, runtime_->newInt(4)); Object obj3(&scope, runtime_->newStrFromCStr("bar")); Tuple elts(&scope, runtime_->newTupleWith3(obj1, obj2, obj3)); EXPECT_TRUE(raisedWithStr( runBuiltin(FUNC(_builtins, _str_join), sep, elts), LayoutId::kTypeError, "sequence item 1: expected str instance, int found")); } TEST_F(UnderBuiltinsModuleTest, PartitionOnSingleCharStr) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("l")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "he")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "l")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "lo")); } TEST_F(UnderBuiltinsModuleTest, PartitionOnMultiCharStr) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("ll")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "he")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "ll")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "o")); } TEST_F(UnderBuiltinsModuleTest, PartitionOnExistingSuffix) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("lo")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "hel")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "lo")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, PartitionOnNonExistentSuffix) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("lop")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "hello")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, PartitionOnExistingPrefix) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("he")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "he")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "llo")); } TEST_F(UnderBuiltinsModuleTest, PartitionOnNonExistentPrefix) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("hex")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "hello")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, PartitionLargerStr) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("abcdefghijk")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "hello")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, PartitionEmptyStr) { HandleScope scope(thread_); Str str(&scope, Str::empty()); Str sep(&scope, runtime_->newStrFromCStr("a")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_partition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, RpartitionOnSingleCharStrPartitionsCorrectly) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("l")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "hel")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "l")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "o")); } TEST_F(UnderBuiltinsModuleTest, RpartitionOnMultiCharStrPartitionsCorrectly) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("ll")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "he")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "ll")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "o")); } TEST_F(UnderBuiltinsModuleTest, RpartitionOnSuffixPutsEmptyStrAtEndOfResult) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("lo")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "hel")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "lo")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, RpartitionOnNonExistentSuffixPutsStrAtEndOfResult) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("lop")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "hello")); } TEST_F(UnderBuiltinsModuleTest, RpartitionOnPrefixPutsEmptyStrAtBeginningOfResult) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("he")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "he")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "llo")); } TEST_F(UnderBuiltinsModuleTest, RpartitionOnNonExistentPrefixPutsStrAtEndOfResult) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("hex")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "hello")); } TEST_F(UnderBuiltinsModuleTest, RpartitionLargerStrPutsStrAtEndOfResult) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello")); Str sep(&scope, runtime_->newStrFromCStr("foobarbaz")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "hello")); } TEST_F(UnderBuiltinsModuleTest, RpartitionEmptyStrReturnsTupleOfEmptyStrings) { HandleScope scope(thread_); Str str(&scope, Str::empty()); Str sep(&scope, runtime_->newStrFromCStr("a")); Tuple result(&scope, runBuiltin(FUNC(_builtins, _str_rpartition), str, sep)); ASSERT_EQ(result.length(), 3); EXPECT_TRUE(isStrEqualsCStr(result.at(0), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(1), "")); EXPECT_TRUE(isStrEqualsCStr(result.at(2), "")); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWithStrEqualsSepReturnsTwoEmptyStrings) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("haystack")); Str sep(&scope, runtime_->newStrFromCStr("haystack")); Int maxsplit(&scope, SmallInt::fromWord(100)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); EXPECT_PYLIST_EQ(result, {"", ""}); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWithSepNotInStrReturnsListOfStr) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("haystack")); Str sep(&scope, runtime_->newStrFromCStr("foobar")); Int maxsplit(&scope, SmallInt::fromWord(100)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); ASSERT_EQ(result.numItems(), 1); EXPECT_EQ(result.at(0), *str); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWithSepInUnderStrSplitsOnSep) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("hello world hello world")); Str sep(&scope, runtime_->newStrFromCStr(" w")); Int maxsplit(&scope, SmallInt::fromWord(100)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); EXPECT_PYLIST_EQ(result, {"hello", "orld hello", "orld"}); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWithSepInUnderStrSplitsOnSepMaxsplit) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("a b c d e")); Str sep(&scope, runtime_->newStrFromCStr(" ")); Int maxsplit(&scope, SmallInt::fromWord(2)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); EXPECT_PYLIST_EQ(result, {"a", "b", "c d e"}); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWithSepInUnderStrSplitsOnSepMaxsplitZero) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("a b c d e")); Str sep(&scope, runtime_->newStrFromCStr(" ")); Int maxsplit(&scope, SmallInt::fromWord(0)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); EXPECT_PYLIST_EQ(result, {"a b c d e"}); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWhitespaceSplitsOnUnicodeWhitespace) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr(u8"a \u3000 \t b\u205fc")); Object sep(&scope, NoneType::object()); Int maxsplit(&scope, SmallInt::fromWord(100)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); EXPECT_PYLIST_EQ(result, {"a", "b", "c"}); } TEST_F(UnderBuiltinsModuleTest, UnderStrSplitWhitespaceSplitsOnWhitespaceAtEnd) { HandleScope scope(thread_); Str str(&scope, runtime_->newStrFromCStr("a \t b c ")); Object sep(&scope, NoneType::object()); Int maxsplit(&scope, SmallInt::fromWord(100)); List result(&scope, runBuiltin(FUNC(_builtins, _str_split), str, sep, maxsplit)); EXPECT_PYLIST_EQ(result, {"a", "b", "c"}); } TEST_F(UnderBuiltinsModuleTest, UnderTupleCheckExactWithExactTupleReturnsTrue) { HandleScope scope(thread_); Object obj(&scope, runtime_->emptyTuple()); EXPECT_EQ(runBuiltin(FUNC(_builtins, _tuple_check_exact), obj), Bool::trueObj()); } TEST_F(UnderBuiltinsModuleTest, UnderTupleCheckExactWithTupleSubclassReturnsFalse) { ASSERT_FALSE(runFromCStr(runtime_, R"( class C(tuple): pass obj = C() )") .isError()); HandleScope scope(thread_); Object obj(&scope, mainModuleAt(runtime_, "obj")); EXPECT_EQ(runBuiltin(FUNC(_builtins, _tuple_check_exact), obj), Bool::falseObj()); } TEST_F(UnderBuiltinsModuleDeathTest, UnderUnimplementedAbortsProgram) { ASSERT_DEATH(static_cast<void>(runFromCStr(runtime_, "_unimplemented()")), ".*'_unimplemented' called."); } TEST_F(UnderBuiltinsModuleDeathTest, UnderUnimplementedPrintsFunctionName) { ASSERT_DEATH(static_cast<void>(runFromCStr(runtime_, R"( def foobar(): _unimplemented() foobar() )")), ".*'_unimplemented' called in function 'foobar'."); } } // namespace testing } // namespace py