runtime/bytearray-builtins-test.cpp (1,038 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #include "bytearray-builtins.h" #include "gtest/gtest.h" #include "builtins.h" #include "test-utils.h" namespace py { namespace testing { using BytearrayBuiltinsTest = RuntimeFixture; TEST_F(BytearrayBuiltinsTest, Add) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, array, 0); bytearrayAdd(thread_, runtime_, array, 1); bytearrayAdd(thread_, runtime_, array, 2); EXPECT_GE(array.capacity(), 3); EXPECT_EQ(array.numItems(), 3); EXPECT_EQ(array.byteAt(0), 0); EXPECT_EQ(array.byteAt(1), 1); EXPECT_EQ(array.byteAt(2), 2); } TEST_F(BytearrayBuiltinsTest, AsBytes) { HandleScope scope(thread_); Bytearray array(&scope, runtime_->newBytearray()); Bytes bytes(&scope, bytearrayAsBytes(thread_, array)); EXPECT_TRUE(isBytesEqualsBytes(bytes, View<byte>(nullptr, 0))); array.setItems(runtime_->mutableBytesWith(10, 0)); array.setNumItems(3); bytes = bytearrayAsBytes(thread_, array); const byte expected_bytes[] = {0, 0, 0}; EXPECT_TRUE(isBytesEqualsBytes(bytes, expected_bytes)); } TEST_F(BytearrayBuiltinsTest, ClearSetsLengthToZero) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( array = bytearray(b'foo') array.clear() )") .isError()); Bytearray array(&scope, mainModuleAt(runtime_, "array")); EXPECT_EQ(array.numItems(), 0); } TEST_F(BytearrayBuiltinsTest, DunderAddWithNonBytesLikeRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "bytearray(b'') + None"), LayoutId::kTypeError, "can only concatenate bytearray or bytes to bytearray")); } TEST_F(BytearrayBuiltinsTest, DunderAddWithBytearrayOtherReturnsNewBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); const byte byte_array[] = {'1', '2', '3'}; runtime_->bytearrayExtend(thread_, other, byte_array); Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other)); EXPECT_TRUE(isBytearrayEqualsCStr(self, "")); EXPECT_TRUE(isBytearrayEqualsCStr(result, "123")); } TEST_F(BytearrayBuiltinsTest, DunderAddWithBytesOtherReturnsNewBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Bytes other(&scope, runtime_->newBytes(4, '1')); Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other)); EXPECT_TRUE(isBytearrayEqualsCStr(self, "")); EXPECT_TRUE(isBytearrayEqualsCStr(result, "1111")); } TEST_F(BytearrayBuiltinsTest, DunderAddWithBytesSubclassOtherReturnsNewBytearray) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Foo(bytes): pass other = Foo(b"1234") )") .isError()); HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, mainModuleAt(runtime_, "other")); Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other)); EXPECT_TRUE(isBytearrayEqualsCStr(self, "")); EXPECT_TRUE(isBytearrayEqualsCStr(result, "1234")); } TEST_F(BytearrayBuiltinsTest, DunderAddReturnsConcatenatedBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte byte_array[] = {'f', 'o', 'o'}; runtime_->bytearrayExtend(thread_, self, byte_array); Bytes other(&scope, runtime_->newBytes(1, 'd')); Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other)); EXPECT_TRUE(isBytearrayEqualsCStr(self, "foo")); EXPECT_TRUE(isBytearrayEqualsCStr(result, "food")); } TEST_F(BytearrayBuiltinsTest, DunderEqWithNonBytesOtherReturnsNotImplemented) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __eq__), self, other)); EXPECT_TRUE(result.isNotImplementedType()); } TEST_F(BytearrayBuiltinsTest, DunderEqWithEmptyBytearraysReturnsTrue) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, runtime_->newBytearray()); EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderEqWithEqualBytesReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderEqWithEqualBytearrayReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderEqWithDifferentLengthsReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, {bytes, 2}); EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderEqWithDifferentContentsReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'f')); EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithNonBytesOtherReturnsNotImplemented) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __ge__), self, other)); EXPECT_TRUE(result.isNotImplementedType()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithEmptyBytearraysReturnsTrue) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, runtime_->newBytearray()); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeithEqualBytesReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithEqualBytearrayReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithLongerOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, {bytes, 2}); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithShorterOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, {bytes, 2}); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithEarlierOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'f')); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGeWithLaterOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'o', 'o', 'f'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'o')); EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithNonBytesOtherReturnsNotImplemented) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __gt__), self, other)); EXPECT_TRUE(result.isNotImplementedType()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithEmptyBytearraysReturnsFalse) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, runtime_->newBytearray()); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtithEqualBytesReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithEqualBytearrayReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithLongerOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, {bytes, 2}); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithShorterOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, {bytes, 2}); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithEarlierOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'f')); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderGtWithLaterOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'o', 'o', 'f'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'o')); EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderIaddWithNonBytesLikeRaisesTypeError) { const char* test = R"( array = bytearray(b'') array += None )"; EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, test), LayoutId::kTypeError, "can't concat NoneType to bytearray")); } TEST_F(BytearrayBuiltinsTest, DunderIaddWithBytearrayOtherConcatenatesToSelf) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); const byte bytes[] = {'1', '2', '3'}; runtime_->bytearrayExtend(thread_, other, bytes); Object result(&scope, runBuiltin(METH(bytearray, __iadd__), self, other)); EXPECT_TRUE(isBytearrayEqualsBytes(self, bytes)); EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes)); } TEST_F(BytearrayBuiltinsTest, DunderIaddWithBytesOtherConcatenatesToSelf) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'1', '2', '3'}; Bytes other(&scope, runtime_->newBytesWithAll(bytes)); Object result(&scope, runBuiltin(METH(bytearray, __iadd__), self, other)); EXPECT_TRUE(isBytearrayEqualsBytes(self, bytes)); EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes)); } TEST_F(BytearrayBuiltinsTest, DunderIaddWithBytesSubclassOtherConcatenatesToSelf) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Foo(bytes): pass other = Foo(b"1234") )") .isError()); HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, mainModuleAt(runtime_, "other")); Object result(&scope, runBuiltin(METH(bytearray, __iadd__), self, other)); const char* expected = "1234"; EXPECT_TRUE(isBytearrayEqualsCStr(self, expected)); EXPECT_TRUE(isBytearrayEqualsCStr(result, expected)); } TEST_F(BytearrayBuiltinsTest, DunderImulWithNonIntRaisesTypeError) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object count(&scope, runtime_->newList()); EXPECT_TRUE(raisedWithStr( runBuiltin(METH(bytearray, __imul__), self, count), LayoutId::kTypeError, "'list' object cannot be interpreted as an integer")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithIntSubclassReturnsRepeatedBytes) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); ASSERT_FALSE(runFromCStr(runtime_, R"( class C(int): pass count = C(5) )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "aaaaa")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithDunderIndexReturnsRepeatedBytes) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __index__(self): return 2 count = C() )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "aa")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithBadDunderIndexRaisesTypeError) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __index__(self): return "foo" count = C() )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __imul__), self, count), LayoutId::kTypeError, "__index__ returned non-int (type str)")); } TEST_F(BytearrayBuiltinsTest, DunderImulPropagatesDunderIndexError) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __index__(self): raise ArithmeticError("called __index__") count = C() )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __imul__), self, count), LayoutId::kArithmeticError, "called __index__")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithLargeIntRaisesOverflowError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const uword digits[] = {1, 1}; Object count(&scope, runtime_->newLargeIntWithDigits(digits)); EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __imul__), self, count), LayoutId::kOverflowError, "cannot fit 'int' into an index-sized integer")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithOverflowRaisesMemoryError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'a', 'b', 'c'}; runtime_->bytearrayExtend(thread_, self, bytes); Object count(&scope, SmallInt::fromWord(SmallInt::kMaxValue / 2)); EXPECT_TRUE(raised(runBuiltin(METH(bytearray, __imul__), self, count), LayoutId::kMemoryError)); } TEST_F(BytearrayBuiltinsTest, DunderImulWithEmptyBytearrayReturnsEmptyBytearray) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object count(&scope, SmallInt::fromWord(5)); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithNegativeReturnsEmptyBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); self.setItems(runtime_->mutableBytesWith(8, 'a')); self.setNumItems(8); Object count(&scope, SmallInt::fromWord(-5)); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithZeroReturnsEmptyBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); self.setItems(runtime_->mutableBytesWith(8, 'a')); self.setNumItems(8); Object count(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderImulWithOneReturnsSameBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'a', 'b'}; runtime_->bytearrayExtend(thread_, self, bytes); Object count(&scope, SmallInt::fromWord(1)); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes)); } TEST_F(BytearrayBuiltinsTest, DunderImulReturnsRepeatedBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'a', 'b'}; runtime_->bytearrayExtend(thread_, self, bytes); Object count(&scope, SmallInt::fromWord(3)); Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "ababab")); } TEST_F(BytearrayBuiltinsTest, DunderLeWithNonBytesOtherReturnsNotImplemented) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __le__), self, other)); EXPECT_TRUE(result.isNotImplementedType()); } TEST_F(BytearrayBuiltinsTest, DunderLeWithEmptyBytearraysReturnsTrue) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, runtime_->newBytearray()); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderLeithEqualBytesReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderLeWithEqualBytearrayReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderLeWithLongerOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, {bytes, 2}); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderLeWithShorterOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, {bytes, 2}); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLeWithEarlierOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'f')); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLeWithLaterOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'o', 'o', 'f'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'o')); EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderLenWithEmptyBytearrayReturnsZero) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Object result(&scope, runBuiltin(METH(bytearray, __len__), self)); EXPECT_TRUE(isIntEqualsWord(*result, 0)); } TEST_F(BytearrayBuiltinsTest, DunderLenWithNonEmptyBytearrayReturnsPositive) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {1, 2, 3, 4, 5}; runtime_->bytearrayExtend(thread_, self, bytes); Object result(&scope, runBuiltin(METH(bytearray, __len__), self)); EXPECT_TRUE(isIntEqualsWord(*result, 5)); const byte bytes2[] = {6, 7}; runtime_->bytearrayExtend(thread_, self, bytes2); result = runBuiltin(METH(bytearray, __len__), self); EXPECT_TRUE(isIntEqualsWord(*result, 7)); } TEST_F(BytearrayBuiltinsTest, DunderLtWithNonBytesOtherReturnsNotImplemented) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __lt__), self, other)); EXPECT_TRUE(result.isNotImplementedType()); } TEST_F(BytearrayBuiltinsTest, DunderLtWithEmptyBytearraysReturnsFalse) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, runtime_->newBytearray()); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLtithEqualBytesReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLtWithEqualBytearrayReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLtWithLongerOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, {bytes, 2}); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderLtWithShorterOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, {bytes, 2}); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLtWithEarlierOtherReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'f')); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderLtWithLaterOtherReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'o', 'o', 'f'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'o')); EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderMulWithNonIntRaisesTypeError) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object count(&scope, runtime_->newList()); EXPECT_TRUE(raisedWithStr( runBuiltin(METH(bytearray, __mul__), self, count), LayoutId::kTypeError, "'list' object cannot be interpreted as an integer")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithIntSubclassReturnsRepeatedBytes) { HandleScope scope(thread_); const byte view[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, view); ASSERT_FALSE(runFromCStr(runtime_, R"( class C(int): pass count = C(3) )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "foofoofoo")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithDunderIndexReturnsRepeatedBytes) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); bytearrayAdd(thread_, runtime_, self, 'a'); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __index__(self): return 2 count = C() )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "aa")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithBadDunderIndexRaisesTypeError) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __index__(self): return "foo" count = C() )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __mul__), self, count), LayoutId::kTypeError, "__index__ returned non-int (type str)")); } TEST_F(BytearrayBuiltinsTest, DunderMulPropagatesDunderIndexError) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); ASSERT_FALSE(runFromCStr(runtime_, R"( class C: def __index__(self): raise ArithmeticError("called __index__") count = C() )") .isError()); Object count(&scope, mainModuleAt(runtime_, "count")); EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __mul__), self, count), LayoutId::kArithmeticError, "called __index__")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithLargeIntRaisesOverflowError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const uword digits[] = {1, 1}; Object count(&scope, runtime_->newLargeIntWithDigits(digits)); EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __mul__), self, count), LayoutId::kOverflowError, "cannot fit 'int' into an index-sized integer")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithOverflowRaisesMemoryError) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'a', 'b', 'c'}; runtime_->bytearrayExtend(thread_, self, bytes); Object count(&scope, SmallInt::fromWord(SmallInt::kMaxValue / 2)); EXPECT_TRUE(raised(runBuiltin(METH(bytearray, __mul__), self, count), LayoutId::kMemoryError)); } TEST_F(BytearrayBuiltinsTest, DunderMulWithEmptyBytearrayReturnsEmptyBytearray) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object count(&scope, SmallInt::fromWord(5)); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithNegativeReturnsEmptyBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); self.setItems(runtime_->mutableBytesWith(8, 'a')); self.setNumItems(8); Object count(&scope, SmallInt::fromWord(-5)); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithZeroReturnsEmptyBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); self.setItems(runtime_->mutableBytesWith(8, 'a')); self.setNumItems(8); Object count(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderMulWithOneReturnsSameBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'a', 'b'}; runtime_->bytearrayExtend(thread_, self, bytes); Object count(&scope, SmallInt::fromWord(1)); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes)); } TEST_F(BytearrayBuiltinsTest, DunderMulReturnsRepeatedBytearray) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'a', 'b'}; runtime_->bytearrayExtend(thread_, self, bytes); Object count(&scope, SmallInt::fromWord(3)); Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "ababab")); } TEST_F(BytearrayBuiltinsTest, DunderNeWithNonBytesOtherReturnsNotImplemented) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, SmallInt::fromWord(0)); Object result(&scope, runBuiltin(METH(bytearray, __ne__), self, other)); EXPECT_TRUE(result.isNotImplementedType()); } TEST_F(BytearrayBuiltinsTest, DunderNeWithEmptyBytearraysReturnsFalse) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object other(&scope, runtime_->newBytearray()); EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderNeWithEqualBytesReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderNeWithEqualBytearrayReturnsFalse) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, bytes); EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::falseObj()); } TEST_F(BytearrayBuiltinsTest, DunderNeWithDifferentLengthsReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); Bytearray other(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); runtime_->bytearrayExtend(thread_, other, {bytes, 2}); EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderNeWithDifferentContentsReturnsTrue) { HandleScope scope(thread_); const byte bytes[] = {'f', 'o', 'o'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, bytes); Object other(&scope, runtime_->newBytes(3, 'f')); EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, DunderNewWithNonTypeRaisesTypeError) { EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray.__new__(3)"), LayoutId::kTypeError, "not a type object")); } TEST_F(BytearrayBuiltinsTest, DunderNewWithNonBytearrayRaisesTypeError) { EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray.__new__(int)"), LayoutId::kTypeError, "not a subtype of bytearray")); } TEST_F(BytearrayBuiltinsTest, DunderNewReturnsEmptyBytearray) { HandleScope scope(thread_); Type cls(&scope, runtime_->typeAt(LayoutId::kBytearray)); Object self(&scope, runBuiltin(METH(bytearray, __new__), cls)); EXPECT_TRUE(isBytearrayEqualsCStr(self, "")); } TEST_F(BytearrayBuiltinsTest, NewBytearray) { HandleScope scope(thread_); ASSERT_FALSE( runFromCStr(runtime_, "obj = bytearray(b'Hello world!')").isError()); Bytearray self(&scope, mainModuleAt(runtime_, "obj")); EXPECT_TRUE(isBytearrayEqualsCStr(self, "Hello world!")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithEmptyBytearrayReturnsEmptyRepr) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, "bytearray(b'')")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithSimpleBytearrayReturnsRepr) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'f', 'o', 'o'}; runtime_->bytearrayExtend(thread_, self, bytes); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, "bytearray(b'foo')")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithDoubleQuoteUsesSingleQuoteDelimiters) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'_', '"', '_'}; runtime_->bytearrayExtend(thread_, self, bytes); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'_"_'))")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithSingleQuoteUsesDoubleQuoteDelimiters) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'_', '\'', '_'}; runtime_->bytearrayExtend(thread_, self, bytes); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b"_\'_"))")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithBothQuotesUsesSingleQuoteDelimiters) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'_', '"', '_', '\'', '_'}; runtime_->bytearrayExtend(thread_, self, bytes); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'_"_\'_'))")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithSpecialBytesUsesEscapeSequences) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {'\\', '\t', '\n', '\r'}; runtime_->bytearrayExtend(thread_, self, bytes); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'\\\t\n\r'))")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithSmallAndLargeBytesUsesHex) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {0, 0x1f, 0x80, 0xff}; runtime_->bytearrayExtend(thread_, self, bytes); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self)); EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'\x00\x1f\x80\xff'))")); } TEST_F(BytearrayBuiltinsTest, DunderReprWithSubclassUsesClassName) { ASSERT_FALSE(runFromCStr(runtime_, R"( class C(bytearray): pass obj = C(b'hello world') )") .isError()); HandleScope scope(thread_); Object obj(&scope, mainModuleAt(runtime_, "obj")); Object repr(&scope, runBuiltin(METH(bytearray, __repr__), obj)); EXPECT_TRUE(isStrEqualsCStr(*repr, "C(b'hello world')")); } TEST_F(BytearrayBuiltinsTest, DunderRmulCallsDunderMul) { HandleScope scope(thread_); ASSERT_FALSE( runFromCStr(runtime_, "result = 3 * bytearray(b'123')").isError()); Object result(&scope, mainModuleAt(runtime_, "result")); EXPECT_TRUE(isBytearrayEqualsCStr(result, "123123123")); } TEST_F(BytearrayBuiltinsTest, HexWithEmptyBytearrayReturnsEmptyString) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object result(&scope, runBuiltin(METH(bytearray, hex), self)); EXPECT_TRUE(isStrEqualsCStr(*result, "")); } TEST_F(BytearrayBuiltinsTest, HexWithNonEmptyBytesReturnsString) { HandleScope scope(thread_); Bytearray self(&scope, runtime_->newBytearray()); const byte bytes[] = {0x60, 0xe, 0x18, 0x21}; runtime_->bytearrayExtend(thread_, self, bytes); Object result(&scope, runBuiltin(METH(bytearray, hex), self)); EXPECT_TRUE(isStrEqualsCStr(*result, "600e1821")); } TEST_F(BytearrayBuiltinsTest, JoinWithNonIterableRaisesTypeError) { EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray(b'').join(0)"), LayoutId::kTypeError, "'int' object is not iterable")); } TEST_F(BytearrayBuiltinsTest, JoinWithMistypedIterableRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "bytearray(b' ').join([1])"), LayoutId::kTypeError, "sequence item 0: expected a bytes-like object, 'int' found")); } TEST_F(BytearrayBuiltinsTest, JoinWithIterableReturnsBytearray) { ASSERT_FALSE(runFromCStr(runtime_, R"( class Foo: def __iter__(self): return [b'ab', b'c', b'def'].__iter__() result = bytearray(b' ').join(Foo()) )") .isError()); HandleScope scope(thread_); Object result(&scope, mainModuleAt(runtime_, "result")); EXPECT_TRUE(isBytearrayEqualsCStr(result, "ab c def")); } TEST_F(BytearrayBuiltinsTest, MaketransWithNonBytesLikeFromRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "bytearray.maketrans([1,2], b'ab')"), LayoutId::kTypeError, "a bytes-like object is required, not 'list'")); } TEST_F(BytearrayBuiltinsTest, MaketransWithNonBytesLikeToRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "bytearray.maketrans(b'1', 2)"), LayoutId::kTypeError, "a bytes-like object is required, not 'int'")); } TEST_F(BytearrayBuiltinsTest, MaketransWithDifferentLengthsRaisesValueError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "bytearray.maketrans(b'12', bytearray())"), LayoutId::kValueError, "maketrans arguments must have same length")); } TEST_F(BytearrayBuiltinsTest, MaketransWithEmptyReturnsDefaultBytes) { HandleScope scope(thread_); ASSERT_FALSE( runFromCStr(runtime_, "result = bytearray.maketrans(bytearray(), b'')") .isError()); Object result(&scope, mainModuleAt(runtime_, "result")); byte expected[256]; for (word i = 0; i < 256; i++) { expected[i] = i; } EXPECT_TRUE(isBytesEqualsBytes(result, expected)); } TEST_F(BytearrayBuiltinsTest, MaketransWithNonEmptyReturnsBytes) { HandleScope scope(thread_); ASSERT_FALSE( runFromCStr(runtime_, "result = bytearray.maketrans(bytearray(b'abc'), b'123')") .isError()); Object result(&scope, mainModuleAt(runtime_, "result")); ASSERT_TRUE(result.isBytes()); LargeBytes actual(&scope, *result); EXPECT_EQ(actual.byteAt('a'), '1'); EXPECT_EQ(actual.byteAt('b'), '2'); EXPECT_EQ(actual.byteAt('c'), '3'); } TEST_F(BytearrayBuiltinsTest, TranslateWithNonBytesLikeTableRaisesTypeError) { EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray().translate(42)"), LayoutId::kTypeError, "a bytes-like object is required, not 'int'")); } TEST_F(BytearrayBuiltinsTest, TranslateWithNonBytesLikeDeleteRaisesTypeError) { EXPECT_TRUE(raisedWithStr( runFromCStr(runtime_, "bytearray().translate(None, 42)"), LayoutId::kTypeError, "a bytes-like object is required, not 'int'")); } TEST_F(BytearrayBuiltinsTest, TranslateWithShortTableRaisesValueError) { EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray().translate(b'')"), LayoutId::kValueError, "translation table must be 256 characters long")); } TEST_F(BytearrayBuiltinsTest, TranslateWithEmptyBytearrayReturnsNewBytearray) { HandleScope scope(thread_); Object self(&scope, runtime_->newBytearray()); Object table(&scope, NoneType::object()); Object del(&scope, runtime_->newBytearray()); Object result(&scope, runBuiltin(METH(bytearray, translate), self, table, del)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); EXPECT_NE(result, self); } TEST_F(BytearrayBuiltinsTest, TranslateWithNonEmptySecondArgDeletesBytes) { HandleScope scope(thread_); const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'}; const byte abc[] = {'a', 'b', 'c'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, alabama); Object table(&scope, NoneType::object()); Object del(&scope, runtime_->newBytesWithAll(abc)); Object result(&scope, runBuiltin(METH(bytearray, translate), self, table, del)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "Alm")); } TEST_F(BytearrayBuiltinsTest, TranslateWithTableTranslatesBytes) { HandleScope scope(thread_); ASSERT_FALSE( runFromCStr(runtime_, "table = bytes.maketrans(b'Aa', b'12')").isError()); const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, alabama); Object table(&scope, mainModuleAt(runtime_, "table")); Object del(&scope, runtime_->newBytearray()); Object result(&scope, runBuiltin(METH(bytearray, translate), self, table, del)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "1l2b2m2")); } TEST_F(BytearrayBuiltinsTest, TranslateWithTableAndDeleteTranslatesAndDeletesBytes) { HandleScope scope(thread_); ASSERT_FALSE( runFromCStr(runtime_, "table = bytes.maketrans(b'Aa', b'12')").isError()); const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'}; const byte abc[] = {'a', 'b', 'c'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, alabama); Object table(&scope, mainModuleAt(runtime_, "table")); Object del(&scope, runtime_->newBytesWithAll(abc)); Object result(&scope, runBuiltin(METH(bytearray, translate), self, table, del)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "1lm")); } TEST_F(BytearrayBuiltinsTest, TranslateDeletesAllBytes) { HandleScope scope(thread_); const byte alabama[] = {'b', 'a', 'c', 'a', 'a', 'c', 'a'}; const byte abc[] = {'a', 'b', 'c'}; Bytearray self(&scope, runtime_->newBytearray()); runtime_->bytearrayExtend(thread_, self, alabama); Object table(&scope, NoneType::object()); Object del(&scope, runtime_->newBytesWithAll(abc)); Object result(&scope, runBuiltin(METH(bytearray, translate), self, table, del)); EXPECT_TRUE(isBytearrayEqualsCStr(result, "")); } TEST_F(BytearrayBuiltinsTest, DunderIterReturnsBytearrayIterator) { ASSERT_FALSE( runFromCStr(runtime_, "result = type(bytearray().__iter__())").isError()); HandleScope scope(thread_); Object result(&scope, mainModuleAt(runtime_, "result")); EXPECT_EQ(*result, runtime_->typeAt(LayoutId::kBytearrayIterator)); } TEST_F(BytearrayBuiltinsTest, IteratorDunderNextReturnsNextElement) { ASSERT_FALSE(runFromCStr(runtime_, R"( ba = bytearray(b'abc') it = iter(ba) r0 = it.__next__() r1 = it.__next__() r2 = it.__next__() try: it.__next__() r3 = False except StopIteration: r3 = True )") .isError()); EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "r0"), 'a')); EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "r1"), 'b')); EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "r2"), 'c')); EXPECT_EQ(mainModuleAt(runtime_, "r3"), Bool::trueObj()); } TEST_F(BytearrayBuiltinsTest, IteratorDunderNextStopsIterationWhenBytearrayIsShrunk) { ASSERT_FALSE(runFromCStr(runtime_, R"( ba = bytearray(b'abc') it = iter(ba) )") .isError()); HandleScope scope(thread_); Bytearray ba(&scope, mainModuleAt(runtime_, "ba")); BytearrayIterator it(&scope, mainModuleAt(runtime_, "it")); ba.setNumItems(0); EXPECT_TRUE(raised(thread_->invokeMethod1(it, ID(__next__)), LayoutId::kStopIteration)); } } // namespace testing } // namespace py