runtime/byteslike-test.cpp (188 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) #include "byteslike.h" #include "gtest/gtest.h" #include "handles.h" #include "objects.h" #include "test-utils.h" #include "view.h" namespace py { namespace testing { using ByteslikeTest = RuntimeFixture; TEST_F(ByteslikeTest, ConstructWithSmallBytes) { HandleScope scope(thread_); View<byte> bytes(reinterpret_cast<const byte*>("hello"), 5); Object value(&scope, SmallBytes::fromBytes(bytes)); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); EXPECT_EQ(byteslike.length(), 5); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(std::memcmp(reinterpret_cast<const byte*>(byteslike.address()), "hello", 5), 0); } TEST_F(ByteslikeTest, ConstructWithLargeBytes) { HandleScope scope(thread_); byte bytes[] = "hello foo bar\0baz\n"; Object value(&scope, runtime_->newBytesWithAll(bytes)); EXPECT_TRUE(value.isLargeBytes()); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); runtime_->collectGarbage(); EXPECT_EQ(byteslike.length(), static_cast<word>(ARRAYSIZE(bytes))); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(byteslike.byteAt(13), '\0'); EXPECT_EQ(byteslike.byteAt(15), 'a'); EXPECT_EQ(byteslike.byteAt(17), '\n'); EXPECT_EQ(byteslike.address(), LargeBytes::cast(*value).address()); } TEST_F(ByteslikeTest, ConstructWithMutableBytes) { HandleScope scope(thread_); byte bytes[] = "hello foo bar\0baz\n"; MutableBytes value(&scope, runtime_->newMutableBytesUninitialized(ARRAYSIZE(bytes))); value.replaceFromWithAll(0, {bytes, ARRAYSIZE(bytes)}); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); runtime_->collectGarbage(); EXPECT_EQ(byteslike.length(), static_cast<word>(ARRAYSIZE(bytes))); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(byteslike.byteAt(13), '\0'); EXPECT_EQ(byteslike.byteAt(15), 'a'); EXPECT_EQ(byteslike.byteAt(17), '\n'); EXPECT_EQ(byteslike.address(), value.address()); } TEST_F(ByteslikeTest, ConstructWithByteSubclassWithSmallBytes) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C(bytes): pass value = C(b"hello") )") .isError()); Object value(&scope, mainModuleAt(runtime_, "value")); EXPECT_TRUE(bytesUnderlying(*value).isSmallBytes()); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); EXPECT_EQ(byteslike.length(), 5); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(std::memcmp(reinterpret_cast<const byte*>(byteslike.address()), "hello", 5), 0); } TEST_F(ByteslikeTest, ConstructWithByteSubclassWithLargeBytes) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( class C(bytes): pass value = C(b"hello foo bar\0baz\n") )") .isError()); Object value(&scope, mainModuleAt(runtime_, "value")); EXPECT_TRUE(bytesUnderlying(*value).isLargeBytes()); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); runtime_->collectGarbage(); EXPECT_EQ(byteslike.length(), 18); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(byteslike.byteAt(13), '\0'); EXPECT_EQ(byteslike.byteAt(15), 'a'); EXPECT_EQ(byteslike.byteAt(17), '\n'); EXPECT_EQ(byteslike.address(), LargeBytes::cast(bytesUnderlying(*value)).address()); } TEST_F(ByteslikeTest, ConstructWithBytearray) { HandleScope scope(thread_); Bytearray value(&scope, runtime_->newBytearray()); runtime_->bytearrayEnsureCapacity(thread_, value, 32); byte bytes[] = "hello foo bar\0baz\n"; runtime_->bytearrayExtend(thread_, value, bytes); // We want to test the case where numItems() != items.length EXPECT_NE(value.numItems(), MutableBytes::cast(value.items()).length()); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); runtime_->collectGarbage(); EXPECT_EQ(byteslike.length(), static_cast<word>(ARRAYSIZE(bytes))); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(byteslike.byteAt(13), '\0'); EXPECT_EQ(byteslike.byteAt(15), 'a'); EXPECT_EQ(byteslike.byteAt(17), '\n'); EXPECT_EQ(byteslike.address(), MutableBytes::cast(value.items()).address()); } TEST_F(ByteslikeTest, ConstructWithArray) { HandleScope scope(thread_); ASSERT_FALSE(runFromCStr(runtime_, R"( import array value = array.array("Q") value.append(0xcafebabe12345678) )") .isError()); Array value(&scope, mainModuleAt(runtime_, "value")); ASSERT_EQ(value.length(), 1); // We want to test the case where the array buffer is bigger than the // contents. If this fails adjust test. ASSERT_TRUE(MutableBytes::cast(value.buffer()).length() > 8); static_assert(endian::native == endian::little, "test designed for little endian systems"); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); runtime_->collectGarbage(); EXPECT_EQ(byteslike.length(), 8); EXPECT_EQ(byteslike.byteAt(0), 0x78); EXPECT_EQ(byteslike.byteAt(7), 0xca); EXPECT_EQ(byteslike.byteAt(6), 0xfe); EXPECT_EQ(byteslike.address(), MutableBytes::cast(value.buffer()).address()); } TEST_F(ByteslikeTest, ConstructWithMemoryviewWithSmallBytes) { HandleScope scope(thread_); byte bytes[] = "hello!"; Object bytes_obj(&scope, SmallBytes::fromBytes(bytes)); MemoryView value(&scope, runtime_->newMemoryView(thread_, bytes_obj, bytes_obj, 3, ReadOnly::ReadOnly)); value.setStart(3); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); EXPECT_EQ(byteslike.length(), 3); EXPECT_EQ(byteslike.byteAt(0), 'l'); EXPECT_EQ(byteslike.byteAt(1), 'o'); EXPECT_EQ(byteslike.byteAt(2), '!'); } TEST_F(ByteslikeTest, ConstructWithMemoryviewWithLargeBytes) { HandleScope scope(thread_); byte bytes[] = "hello foo bar\0baz\n"; LargeBytes bytes_obj(&scope, runtime_->newBytesWithAll(bytes)); MemoryView value(&scope, runtime_->newMemoryView(thread_, bytes_obj, bytes_obj, 11, ReadOnly::ReadOnly)); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); EXPECT_EQ(byteslike.length(), 11); EXPECT_EQ(byteslike.byteAt(0), 'h'); EXPECT_EQ(byteslike.byteAt(4), 'o'); EXPECT_EQ(byteslike.address(), bytes_obj.address()); } TEST_F(ByteslikeTest, ConstructWithMemoryviewWithPointer) { HandleScope scope(thread_); byte bytes[] = "hello foo bar\0baz\n"; Pointer pointer(&scope, runtime_->newPointer(bytes, sizeof(bytes))); MemoryView value(&scope, runtime_->newMemoryView(thread_, pointer, pointer, 15, ReadOnly::ReadOnly)); word start = 1; value.setStart(start); Byteslike byteslike(&scope, thread_, *value); EXPECT_TRUE(byteslike.isValid()); EXPECT_EQ(byteslike.length(), 15); EXPECT_EQ(byteslike.byteAt(0), 'e'); EXPECT_EQ(byteslike.byteAt(5), 'f'); EXPECT_EQ(byteslike.byteAt(12), '\0'); EXPECT_EQ(byteslike.byteAt(14), 'a'); EXPECT_EQ(byteslike.address(), bit_cast<uword>(&bytes) + start); } TEST_F(ByteslikeTest, IsValidWithNonByteslikeReturnsFalse) { HandleScope scope(thread_); Object value(&scope, runtime_->newFloat(42.42)); Byteslike byteslike(&scope, thread_, *value); EXPECT_FALSE(byteslike.isValid()); } } // namespace testing } // namespace py