this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "byteslike.h"
3
4#include "gtest/gtest.h"
5
6#include "handles.h"
7#include "objects.h"
8#include "test-utils.h"
9#include "view.h"
10
11namespace py {
12namespace testing {
13
14using ByteslikeTest = RuntimeFixture;
15
16TEST_F(ByteslikeTest, ConstructWithSmallBytes) {
17 HandleScope scope(thread_);
18 View<byte> bytes(reinterpret_cast<const byte*>("hello"), 5);
19 Object value(&scope, SmallBytes::fromBytes(bytes));
20 Byteslike byteslike(&scope, thread_, *value);
21 EXPECT_TRUE(byteslike.isValid());
22 EXPECT_EQ(byteslike.length(), 5);
23 EXPECT_EQ(byteslike.byteAt(0), 'h');
24 EXPECT_EQ(byteslike.byteAt(4), 'o');
25 EXPECT_EQ(std::memcmp(reinterpret_cast<const byte*>(byteslike.address()),
26 "hello", 5),
27 0);
28}
29
30TEST_F(ByteslikeTest, ConstructWithLargeBytes) {
31 HandleScope scope(thread_);
32 byte bytes[] = "hello foo bar\0baz\n";
33 Object value(&scope, runtime_->newBytesWithAll(bytes));
34 EXPECT_TRUE(value.isLargeBytes());
35 Byteslike byteslike(&scope, thread_, *value);
36 EXPECT_TRUE(byteslike.isValid());
37 runtime_->collectGarbage();
38 EXPECT_EQ(byteslike.length(), static_cast<word>(ARRAYSIZE(bytes)));
39 EXPECT_EQ(byteslike.byteAt(0), 'h');
40 EXPECT_EQ(byteslike.byteAt(4), 'o');
41 EXPECT_EQ(byteslike.byteAt(13), '\0');
42 EXPECT_EQ(byteslike.byteAt(15), 'a');
43 EXPECT_EQ(byteslike.byteAt(17), '\n');
44 EXPECT_EQ(byteslike.address(), LargeBytes::cast(*value).address());
45}
46
47TEST_F(ByteslikeTest, ConstructWithMutableBytes) {
48 HandleScope scope(thread_);
49 byte bytes[] = "hello foo bar\0baz\n";
50 MutableBytes value(&scope,
51 runtime_->newMutableBytesUninitialized(ARRAYSIZE(bytes)));
52 value.replaceFromWithAll(0, {bytes, ARRAYSIZE(bytes)});
53 Byteslike byteslike(&scope, thread_, *value);
54 EXPECT_TRUE(byteslike.isValid());
55 runtime_->collectGarbage();
56 EXPECT_EQ(byteslike.length(), static_cast<word>(ARRAYSIZE(bytes)));
57 EXPECT_EQ(byteslike.byteAt(0), 'h');
58 EXPECT_EQ(byteslike.byteAt(4), 'o');
59 EXPECT_EQ(byteslike.byteAt(13), '\0');
60 EXPECT_EQ(byteslike.byteAt(15), 'a');
61 EXPECT_EQ(byteslike.byteAt(17), '\n');
62 EXPECT_EQ(byteslike.address(), value.address());
63}
64
65TEST_F(ByteslikeTest, ConstructWithByteSubclassWithSmallBytes) {
66 HandleScope scope(thread_);
67 ASSERT_FALSE(runFromCStr(runtime_, R"(
68class C(bytes): pass
69value = C(b"hello")
70)")
71 .isError());
72 Object value(&scope, mainModuleAt(runtime_, "value"));
73 EXPECT_TRUE(bytesUnderlying(*value).isSmallBytes());
74 Byteslike byteslike(&scope, thread_, *value);
75 EXPECT_TRUE(byteslike.isValid());
76 EXPECT_EQ(byteslike.length(), 5);
77 EXPECT_EQ(byteslike.byteAt(0), 'h');
78 EXPECT_EQ(byteslike.byteAt(4), 'o');
79 EXPECT_EQ(std::memcmp(reinterpret_cast<const byte*>(byteslike.address()),
80 "hello", 5),
81 0);
82}
83
84TEST_F(ByteslikeTest, ConstructWithByteSubclassWithLargeBytes) {
85 HandleScope scope(thread_);
86 ASSERT_FALSE(runFromCStr(runtime_, R"(
87class C(bytes): pass
88value = C(b"hello foo bar\0baz\n")
89)")
90 .isError());
91 Object value(&scope, mainModuleAt(runtime_, "value"));
92 EXPECT_TRUE(bytesUnderlying(*value).isLargeBytes());
93 Byteslike byteslike(&scope, thread_, *value);
94 EXPECT_TRUE(byteslike.isValid());
95 runtime_->collectGarbage();
96 EXPECT_EQ(byteslike.length(), 18);
97 EXPECT_EQ(byteslike.byteAt(0), 'h');
98 EXPECT_EQ(byteslike.byteAt(4), 'o');
99 EXPECT_EQ(byteslike.byteAt(13), '\0');
100 EXPECT_EQ(byteslike.byteAt(15), 'a');
101 EXPECT_EQ(byteslike.byteAt(17), '\n');
102 EXPECT_EQ(byteslike.address(),
103 LargeBytes::cast(bytesUnderlying(*value)).address());
104}
105
106TEST_F(ByteslikeTest, ConstructWithBytearray) {
107 HandleScope scope(thread_);
108 Bytearray value(&scope, runtime_->newBytearray());
109 runtime_->bytearrayEnsureCapacity(thread_, value, 32);
110 byte bytes[] = "hello foo bar\0baz\n";
111 runtime_->bytearrayExtend(thread_, value, bytes);
112 // We want to test the case where numItems() != items.length
113 EXPECT_NE(value.numItems(), MutableBytes::cast(value.items()).length());
114 Byteslike byteslike(&scope, thread_, *value);
115 EXPECT_TRUE(byteslike.isValid());
116 runtime_->collectGarbage();
117 EXPECT_EQ(byteslike.length(), static_cast<word>(ARRAYSIZE(bytes)));
118 EXPECT_EQ(byteslike.byteAt(0), 'h');
119 EXPECT_EQ(byteslike.byteAt(4), 'o');
120 EXPECT_EQ(byteslike.byteAt(13), '\0');
121 EXPECT_EQ(byteslike.byteAt(15), 'a');
122 EXPECT_EQ(byteslike.byteAt(17), '\n');
123 EXPECT_EQ(byteslike.address(), MutableBytes::cast(value.items()).address());
124}
125
126TEST_F(ByteslikeTest, ConstructWithArray) {
127 HandleScope scope(thread_);
128 ASSERT_FALSE(runFromCStr(runtime_, R"(
129import array
130value = array.array("Q")
131value.append(0xcafebabe12345678)
132)")
133 .isError());
134 Array value(&scope, mainModuleAt(runtime_, "value"));
135 ASSERT_EQ(value.length(), 1);
136 // We want to test the case where the array buffer is bigger than the
137 // contents. If this fails adjust test.
138 ASSERT_TRUE(MutableBytes::cast(value.buffer()).length() > 8);
139
140 static_assert(endian::native == endian::little,
141 "test designed for little endian systems");
142 Byteslike byteslike(&scope, thread_, *value);
143 EXPECT_TRUE(byteslike.isValid());
144 runtime_->collectGarbage();
145 EXPECT_EQ(byteslike.length(), 8);
146 EXPECT_EQ(byteslike.byteAt(0), 0x78);
147 EXPECT_EQ(byteslike.byteAt(7), 0xca);
148 EXPECT_EQ(byteslike.byteAt(6), 0xfe);
149 EXPECT_EQ(byteslike.address(), MutableBytes::cast(value.buffer()).address());
150}
151
152TEST_F(ByteslikeTest, ConstructWithMemoryviewWithSmallBytes) {
153 HandleScope scope(thread_);
154 byte bytes[] = "hello!";
155 Object bytes_obj(&scope, SmallBytes::fromBytes(bytes));
156 MemoryView value(&scope,
157 runtime_->newMemoryView(thread_, bytes_obj, bytes_obj, 3,
158 ReadOnly::ReadOnly));
159 value.setStart(3);
160 Byteslike byteslike(&scope, thread_, *value);
161 EXPECT_TRUE(byteslike.isValid());
162 EXPECT_EQ(byteslike.length(), 3);
163 EXPECT_EQ(byteslike.byteAt(0), 'l');
164 EXPECT_EQ(byteslike.byteAt(1), 'o');
165 EXPECT_EQ(byteslike.byteAt(2), '!');
166}
167
168TEST_F(ByteslikeTest, ConstructWithMemoryviewWithLargeBytes) {
169 HandleScope scope(thread_);
170 byte bytes[] = "hello foo bar\0baz\n";
171 LargeBytes bytes_obj(&scope, runtime_->newBytesWithAll(bytes));
172 MemoryView value(&scope,
173 runtime_->newMemoryView(thread_, bytes_obj, bytes_obj, 11,
174 ReadOnly::ReadOnly));
175 Byteslike byteslike(&scope, thread_, *value);
176 EXPECT_TRUE(byteslike.isValid());
177 EXPECT_EQ(byteslike.length(), 11);
178 EXPECT_EQ(byteslike.byteAt(0), 'h');
179 EXPECT_EQ(byteslike.byteAt(4), 'o');
180 EXPECT_EQ(byteslike.address(), bytes_obj.address());
181}
182
183TEST_F(ByteslikeTest, ConstructWithMemoryviewWithPointer) {
184 HandleScope scope(thread_);
185 byte bytes[] = "hello foo bar\0baz\n";
186 Pointer pointer(&scope, runtime_->newPointer(bytes, sizeof(bytes)));
187 MemoryView value(&scope, runtime_->newMemoryView(thread_, pointer, pointer,
188 15, ReadOnly::ReadOnly));
189 word start = 1;
190 value.setStart(start);
191 Byteslike byteslike(&scope, thread_, *value);
192 EXPECT_TRUE(byteslike.isValid());
193 EXPECT_EQ(byteslike.length(), 15);
194 EXPECT_EQ(byteslike.byteAt(0), 'e');
195 EXPECT_EQ(byteslike.byteAt(5), 'f');
196 EXPECT_EQ(byteslike.byteAt(12), '\0');
197 EXPECT_EQ(byteslike.byteAt(14), 'a');
198 EXPECT_EQ(byteslike.address(), bit_cast<uword>(&bytes) + start);
199}
200
201TEST_F(ByteslikeTest, IsValidWithNonByteslikeReturnsFalse) {
202 HandleScope scope(thread_);
203 Object value(&scope, runtime_->newFloat(42.42));
204 Byteslike byteslike(&scope, thread_, *value);
205 EXPECT_FALSE(byteslike.isValid());
206}
207
208} // namespace testing
209} // namespace py