this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "bytearray-builtins.h"
3
4#include "gtest/gtest.h"
5
6#include "builtins.h"
7#include "test-utils.h"
8
9namespace py {
10namespace testing {
11
12using BytearrayBuiltinsTest = RuntimeFixture;
13
14TEST_F(BytearrayBuiltinsTest, Add) {
15 HandleScope scope(thread_);
16
17 Bytearray array(&scope, runtime_->newBytearray());
18 bytearrayAdd(thread_, runtime_, array, 0);
19 bytearrayAdd(thread_, runtime_, array, 1);
20 bytearrayAdd(thread_, runtime_, array, 2);
21 EXPECT_GE(array.capacity(), 3);
22 EXPECT_EQ(array.numItems(), 3);
23 EXPECT_EQ(array.byteAt(0), 0);
24 EXPECT_EQ(array.byteAt(1), 1);
25 EXPECT_EQ(array.byteAt(2), 2);
26}
27
28TEST_F(BytearrayBuiltinsTest, AsBytes) {
29 HandleScope scope(thread_);
30
31 Bytearray array(&scope, runtime_->newBytearray());
32 Bytes bytes(&scope, bytearrayAsBytes(thread_, array));
33 EXPECT_TRUE(isBytesEqualsBytes(bytes, View<byte>(nullptr, 0)));
34
35 array.setItems(runtime_->mutableBytesWith(10, 0));
36 array.setNumItems(3);
37 bytes = bytearrayAsBytes(thread_, array);
38 const byte expected_bytes[] = {0, 0, 0};
39 EXPECT_TRUE(isBytesEqualsBytes(bytes, expected_bytes));
40}
41
42TEST_F(BytearrayBuiltinsTest, ClearSetsLengthToZero) {
43 HandleScope scope(thread_);
44 ASSERT_FALSE(runFromCStr(runtime_, R"(
45array = bytearray(b'foo')
46array.clear()
47)")
48 .isError());
49 Bytearray array(&scope, mainModuleAt(runtime_, "array"));
50 EXPECT_EQ(array.numItems(), 0);
51}
52
53TEST_F(BytearrayBuiltinsTest, DunderAddWithNonBytesLikeRaisesTypeError) {
54 EXPECT_TRUE(raisedWithStr(
55 runFromCStr(runtime_, "bytearray(b'') + None"), LayoutId::kTypeError,
56 "can only concatenate bytearray or bytes to bytearray"));
57}
58
59TEST_F(BytearrayBuiltinsTest, DunderAddWithBytearrayOtherReturnsNewBytearray) {
60 HandleScope scope(thread_);
61 Bytearray self(&scope, runtime_->newBytearray());
62 Bytearray other(&scope, runtime_->newBytearray());
63 const byte byte_array[] = {'1', '2', '3'};
64 runtime_->bytearrayExtend(thread_, other, byte_array);
65 Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other));
66 EXPECT_TRUE(isBytearrayEqualsCStr(self, ""));
67 EXPECT_TRUE(isBytearrayEqualsCStr(result, "123"));
68}
69
70TEST_F(BytearrayBuiltinsTest, DunderAddWithBytesOtherReturnsNewBytearray) {
71 HandleScope scope(thread_);
72 Bytearray self(&scope, runtime_->newBytearray());
73 Bytes other(&scope, runtime_->newBytes(4, '1'));
74 Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other));
75 EXPECT_TRUE(isBytearrayEqualsCStr(self, ""));
76 EXPECT_TRUE(isBytearrayEqualsCStr(result, "1111"));
77}
78
79TEST_F(BytearrayBuiltinsTest,
80 DunderAddWithBytesSubclassOtherReturnsNewBytearray) {
81 ASSERT_FALSE(runFromCStr(runtime_, R"(
82class Foo(bytes): pass
83other = Foo(b"1234")
84)")
85 .isError());
86 HandleScope scope(thread_);
87 Object self(&scope, runtime_->newBytearray());
88 Object other(&scope, mainModuleAt(runtime_, "other"));
89 Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other));
90 EXPECT_TRUE(isBytearrayEqualsCStr(self, ""));
91 EXPECT_TRUE(isBytearrayEqualsCStr(result, "1234"));
92}
93
94TEST_F(BytearrayBuiltinsTest, DunderAddReturnsConcatenatedBytearray) {
95 HandleScope scope(thread_);
96 Bytearray self(&scope, runtime_->newBytearray());
97 const byte byte_array[] = {'f', 'o', 'o'};
98 runtime_->bytearrayExtend(thread_, self, byte_array);
99 Bytes other(&scope, runtime_->newBytes(1, 'd'));
100 Object result(&scope, runBuiltin(METH(bytearray, __add__), self, other));
101 EXPECT_TRUE(isBytearrayEqualsCStr(self, "foo"));
102 EXPECT_TRUE(isBytearrayEqualsCStr(result, "food"));
103}
104
105TEST_F(BytearrayBuiltinsTest, DunderEqWithNonBytesOtherReturnsNotImplemented) {
106 HandleScope scope(thread_);
107 Object self(&scope, runtime_->newBytearray());
108 Object other(&scope, SmallInt::fromWord(0));
109 Object result(&scope, runBuiltin(METH(bytearray, __eq__), self, other));
110 EXPECT_TRUE(result.isNotImplementedType());
111}
112
113TEST_F(BytearrayBuiltinsTest, DunderEqWithEmptyBytearraysReturnsTrue) {
114 HandleScope scope(thread_);
115 Object self(&scope, runtime_->newBytearray());
116 Object other(&scope, runtime_->newBytearray());
117 EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::trueObj());
118}
119
120TEST_F(BytearrayBuiltinsTest, DunderEqWithEqualBytesReturnsTrue) {
121 HandleScope scope(thread_);
122 const byte bytes[] = {'f', 'o', 'o'};
123 Bytearray self(&scope, runtime_->newBytearray());
124 runtime_->bytearrayExtend(thread_, self, bytes);
125 Object other(&scope, runtime_->newBytesWithAll(bytes));
126 EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::trueObj());
127}
128
129TEST_F(BytearrayBuiltinsTest, DunderEqWithEqualBytearrayReturnsTrue) {
130 HandleScope scope(thread_);
131 const byte bytes[] = {'f', 'o', 'o'};
132 Bytearray self(&scope, runtime_->newBytearray());
133 Bytearray other(&scope, runtime_->newBytearray());
134 runtime_->bytearrayExtend(thread_, self, bytes);
135 runtime_->bytearrayExtend(thread_, other, bytes);
136 EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::trueObj());
137}
138
139TEST_F(BytearrayBuiltinsTest, DunderEqWithDifferentLengthsReturnsFalse) {
140 HandleScope scope(thread_);
141 const byte bytes[] = {'f', 'o', 'o'};
142 Bytearray self(&scope, runtime_->newBytearray());
143 Bytearray other(&scope, runtime_->newBytearray());
144 runtime_->bytearrayExtend(thread_, self, bytes);
145 runtime_->bytearrayExtend(thread_, other, {bytes, 2});
146 EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::falseObj());
147}
148
149TEST_F(BytearrayBuiltinsTest, DunderEqWithDifferentContentsReturnsFalse) {
150 HandleScope scope(thread_);
151 const byte bytes[] = {'f', 'o', 'o'};
152 Bytearray self(&scope, runtime_->newBytearray());
153 runtime_->bytearrayExtend(thread_, self, bytes);
154 Object other(&scope, runtime_->newBytes(3, 'f'));
155 EXPECT_EQ(runBuiltin(METH(bytearray, __eq__), self, other), Bool::falseObj());
156}
157
158TEST_F(BytearrayBuiltinsTest, DunderGeWithNonBytesOtherReturnsNotImplemented) {
159 HandleScope scope(thread_);
160 Object self(&scope, runtime_->newBytearray());
161 Object other(&scope, SmallInt::fromWord(0));
162 Object result(&scope, runBuiltin(METH(bytearray, __ge__), self, other));
163 EXPECT_TRUE(result.isNotImplementedType());
164}
165
166TEST_F(BytearrayBuiltinsTest, DunderGeWithEmptyBytearraysReturnsTrue) {
167 HandleScope scope(thread_);
168 Object self(&scope, runtime_->newBytearray());
169 Object other(&scope, runtime_->newBytearray());
170 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj());
171}
172
173TEST_F(BytearrayBuiltinsTest, DunderGeithEqualBytesReturnsTrue) {
174 HandleScope scope(thread_);
175 const byte bytes[] = {'f', 'o', 'o'};
176 Bytearray self(&scope, runtime_->newBytearray());
177 runtime_->bytearrayExtend(thread_, self, bytes);
178 Object other(&scope, runtime_->newBytesWithAll(bytes));
179 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj());
180}
181
182TEST_F(BytearrayBuiltinsTest, DunderGeWithEqualBytearrayReturnsTrue) {
183 HandleScope scope(thread_);
184 const byte bytes[] = {'f', 'o', 'o'};
185 Bytearray self(&scope, runtime_->newBytearray());
186 Bytearray other(&scope, runtime_->newBytearray());
187 runtime_->bytearrayExtend(thread_, self, bytes);
188 runtime_->bytearrayExtend(thread_, other, bytes);
189 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj());
190}
191
192TEST_F(BytearrayBuiltinsTest, DunderGeWithLongerOtherReturnsFalse) {
193 HandleScope scope(thread_);
194 const byte bytes[] = {'f', 'o', 'o'};
195 Bytearray self(&scope, runtime_->newBytearray());
196 Bytearray other(&scope, runtime_->newBytearray());
197 runtime_->bytearrayExtend(thread_, self, {bytes, 2});
198 runtime_->bytearrayExtend(thread_, other, bytes);
199 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::falseObj());
200}
201
202TEST_F(BytearrayBuiltinsTest, DunderGeWithShorterOtherReturnsTrue) {
203 HandleScope scope(thread_);
204 const byte bytes[] = {'f', 'o', 'o'};
205 Bytearray self(&scope, runtime_->newBytearray());
206 Bytearray other(&scope, runtime_->newBytearray());
207 runtime_->bytearrayExtend(thread_, self, bytes);
208 runtime_->bytearrayExtend(thread_, other, {bytes, 2});
209 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj());
210}
211
212TEST_F(BytearrayBuiltinsTest, DunderGeWithEarlierOtherReturnsTrue) {
213 HandleScope scope(thread_);
214 const byte bytes[] = {'f', 'o', 'o'};
215 Bytearray self(&scope, runtime_->newBytearray());
216 runtime_->bytearrayExtend(thread_, self, bytes);
217 Object other(&scope, runtime_->newBytes(3, 'f'));
218 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::trueObj());
219}
220
221TEST_F(BytearrayBuiltinsTest, DunderGeWithLaterOtherReturnsFalse) {
222 HandleScope scope(thread_);
223 const byte bytes[] = {'o', 'o', 'f'};
224 Bytearray self(&scope, runtime_->newBytearray());
225 runtime_->bytearrayExtend(thread_, self, bytes);
226 Object other(&scope, runtime_->newBytes(3, 'o'));
227 EXPECT_EQ(runBuiltin(METH(bytearray, __ge__), self, other), Bool::falseObj());
228}
229
230TEST_F(BytearrayBuiltinsTest, DunderGtWithNonBytesOtherReturnsNotImplemented) {
231 HandleScope scope(thread_);
232 Object self(&scope, runtime_->newBytearray());
233 Object other(&scope, SmallInt::fromWord(0));
234 Object result(&scope, runBuiltin(METH(bytearray, __gt__), self, other));
235 EXPECT_TRUE(result.isNotImplementedType());
236}
237
238TEST_F(BytearrayBuiltinsTest, DunderGtWithEmptyBytearraysReturnsFalse) {
239 HandleScope scope(thread_);
240 Object self(&scope, runtime_->newBytearray());
241 Object other(&scope, runtime_->newBytearray());
242 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj());
243}
244
245TEST_F(BytearrayBuiltinsTest, DunderGtithEqualBytesReturnsFalse) {
246 HandleScope scope(thread_);
247 const byte bytes[] = {'f', 'o', 'o'};
248 Bytearray self(&scope, runtime_->newBytearray());
249 runtime_->bytearrayExtend(thread_, self, bytes);
250 Object other(&scope, runtime_->newBytesWithAll(bytes));
251 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj());
252}
253
254TEST_F(BytearrayBuiltinsTest, DunderGtWithEqualBytearrayReturnsFalse) {
255 HandleScope scope(thread_);
256 const byte bytes[] = {'f', 'o', 'o'};
257 Bytearray self(&scope, runtime_->newBytearray());
258 Bytearray other(&scope, runtime_->newBytearray());
259 runtime_->bytearrayExtend(thread_, self, bytes);
260 runtime_->bytearrayExtend(thread_, other, bytes);
261 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj());
262}
263
264TEST_F(BytearrayBuiltinsTest, DunderGtWithLongerOtherReturnsFalse) {
265 HandleScope scope(thread_);
266 const byte bytes[] = {'f', 'o', 'o'};
267 Bytearray self(&scope, runtime_->newBytearray());
268 Bytearray other(&scope, runtime_->newBytearray());
269 runtime_->bytearrayExtend(thread_, self, {bytes, 2});
270 runtime_->bytearrayExtend(thread_, other, bytes);
271 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj());
272}
273
274TEST_F(BytearrayBuiltinsTest, DunderGtWithShorterOtherReturnsTrue) {
275 HandleScope scope(thread_);
276 const byte bytes[] = {'f', 'o', 'o'};
277 Bytearray self(&scope, runtime_->newBytearray());
278 Bytearray other(&scope, runtime_->newBytearray());
279 runtime_->bytearrayExtend(thread_, self, bytes);
280 runtime_->bytearrayExtend(thread_, other, {bytes, 2});
281 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::trueObj());
282}
283
284TEST_F(BytearrayBuiltinsTest, DunderGtWithEarlierOtherReturnsTrue) {
285 HandleScope scope(thread_);
286 const byte bytes[] = {'f', 'o', 'o'};
287 Bytearray self(&scope, runtime_->newBytearray());
288 runtime_->bytearrayExtend(thread_, self, bytes);
289 Object other(&scope, runtime_->newBytes(3, 'f'));
290 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::trueObj());
291}
292
293TEST_F(BytearrayBuiltinsTest, DunderGtWithLaterOtherReturnsFalse) {
294 HandleScope scope(thread_);
295 const byte bytes[] = {'o', 'o', 'f'};
296 Bytearray self(&scope, runtime_->newBytearray());
297 runtime_->bytearrayExtend(thread_, self, bytes);
298 Object other(&scope, runtime_->newBytes(3, 'o'));
299 EXPECT_EQ(runBuiltin(METH(bytearray, __gt__), self, other), Bool::falseObj());
300}
301
302TEST_F(BytearrayBuiltinsTest, DunderIaddWithNonBytesLikeRaisesTypeError) {
303 const char* test = R"(
304array = bytearray(b'')
305array += None
306)";
307 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, test), LayoutId::kTypeError,
308 "can't concat NoneType to bytearray"));
309}
310
311TEST_F(BytearrayBuiltinsTest, DunderIaddWithBytearrayOtherConcatenatesToSelf) {
312 HandleScope scope(thread_);
313 Bytearray self(&scope, runtime_->newBytearray());
314 Bytearray other(&scope, runtime_->newBytearray());
315 const byte bytes[] = {'1', '2', '3'};
316 runtime_->bytearrayExtend(thread_, other, bytes);
317 Object result(&scope, runBuiltin(METH(bytearray, __iadd__), self, other));
318 EXPECT_TRUE(isBytearrayEqualsBytes(self, bytes));
319 EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes));
320}
321
322TEST_F(BytearrayBuiltinsTest, DunderIaddWithBytesOtherConcatenatesToSelf) {
323 HandleScope scope(thread_);
324 Bytearray self(&scope, runtime_->newBytearray());
325 const byte bytes[] = {'1', '2', '3'};
326 Bytes other(&scope, runtime_->newBytesWithAll(bytes));
327 Object result(&scope, runBuiltin(METH(bytearray, __iadd__), self, other));
328 EXPECT_TRUE(isBytearrayEqualsBytes(self, bytes));
329 EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes));
330}
331
332TEST_F(BytearrayBuiltinsTest,
333 DunderIaddWithBytesSubclassOtherConcatenatesToSelf) {
334 ASSERT_FALSE(runFromCStr(runtime_, R"(
335class Foo(bytes): pass
336other = Foo(b"1234")
337)")
338 .isError());
339 HandleScope scope(thread_);
340 Object self(&scope, runtime_->newBytearray());
341 Object other(&scope, mainModuleAt(runtime_, "other"));
342 Object result(&scope, runBuiltin(METH(bytearray, __iadd__), self, other));
343 const char* expected = "1234";
344 EXPECT_TRUE(isBytearrayEqualsCStr(self, expected));
345 EXPECT_TRUE(isBytearrayEqualsCStr(result, expected));
346}
347
348TEST_F(BytearrayBuiltinsTest, DunderImulWithNonIntRaisesTypeError) {
349 HandleScope scope(thread_);
350 Object self(&scope, runtime_->newBytearray());
351 Object count(&scope, runtime_->newList());
352 EXPECT_TRUE(raisedWithStr(
353 runBuiltin(METH(bytearray, __imul__), self, count), LayoutId::kTypeError,
354 "'list' object cannot be interpreted as an integer"));
355}
356
357TEST_F(BytearrayBuiltinsTest, DunderImulWithIntSubclassReturnsRepeatedBytes) {
358 HandleScope scope(thread_);
359 Bytearray self(&scope, runtime_->newBytearray());
360 bytearrayAdd(thread_, runtime_, self, 'a');
361 ASSERT_FALSE(runFromCStr(runtime_, R"(
362class C(int): pass
363count = C(5)
364)")
365 .isError());
366 Object count(&scope, mainModuleAt(runtime_, "count"));
367 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
368 EXPECT_TRUE(isBytearrayEqualsCStr(result, "aaaaa"));
369}
370
371TEST_F(BytearrayBuiltinsTest, DunderImulWithDunderIndexReturnsRepeatedBytes) {
372 HandleScope scope(thread_);
373 Bytearray self(&scope, runtime_->newBytearray());
374 bytearrayAdd(thread_, runtime_, self, 'a');
375 ASSERT_FALSE(runFromCStr(runtime_, R"(
376class C:
377 def __index__(self):
378 return 2
379count = C()
380)")
381 .isError());
382 Object count(&scope, mainModuleAt(runtime_, "count"));
383 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
384 EXPECT_TRUE(isBytearrayEqualsCStr(result, "aa"));
385}
386
387TEST_F(BytearrayBuiltinsTest, DunderImulWithBadDunderIndexRaisesTypeError) {
388 HandleScope scope(thread_);
389 Object self(&scope, runtime_->newBytearray());
390 ASSERT_FALSE(runFromCStr(runtime_, R"(
391class C:
392 def __index__(self):
393 return "foo"
394count = C()
395)")
396 .isError());
397 Object count(&scope, mainModuleAt(runtime_, "count"));
398 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __imul__), self, count),
399 LayoutId::kTypeError,
400 "__index__ returned non-int (type str)"));
401}
402
403TEST_F(BytearrayBuiltinsTest, DunderImulPropagatesDunderIndexError) {
404 HandleScope scope(thread_);
405 Object self(&scope, runtime_->newBytearray());
406 ASSERT_FALSE(runFromCStr(runtime_, R"(
407class C:
408 def __index__(self):
409 raise ArithmeticError("called __index__")
410count = C()
411)")
412 .isError());
413 Object count(&scope, mainModuleAt(runtime_, "count"));
414 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __imul__), self, count),
415 LayoutId::kArithmeticError, "called __index__"));
416}
417
418TEST_F(BytearrayBuiltinsTest, DunderImulWithLargeIntRaisesOverflowError) {
419 HandleScope scope(thread_);
420 Bytearray self(&scope, runtime_->newBytearray());
421 const uword digits[] = {1, 1};
422 Object count(&scope, runtime_->newLargeIntWithDigits(digits));
423 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __imul__), self, count),
424 LayoutId::kOverflowError,
425 "cannot fit 'int' into an index-sized integer"));
426}
427
428TEST_F(BytearrayBuiltinsTest, DunderImulWithOverflowRaisesMemoryError) {
429 HandleScope scope(thread_);
430 Bytearray self(&scope, runtime_->newBytearray());
431 const byte bytes[] = {'a', 'b', 'c'};
432 runtime_->bytearrayExtend(thread_, self, bytes);
433 Object count(&scope, SmallInt::fromWord(SmallInt::kMaxValue / 2));
434 EXPECT_TRUE(raised(runBuiltin(METH(bytearray, __imul__), self, count),
435 LayoutId::kMemoryError));
436}
437
438TEST_F(BytearrayBuiltinsTest,
439 DunderImulWithEmptyBytearrayReturnsEmptyBytearray) {
440 HandleScope scope(thread_);
441 Object self(&scope, runtime_->newBytearray());
442 Object count(&scope, SmallInt::fromWord(5));
443 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
444 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
445}
446
447TEST_F(BytearrayBuiltinsTest, DunderImulWithNegativeReturnsEmptyBytearray) {
448 HandleScope scope(thread_);
449 Bytearray self(&scope, runtime_->newBytearray());
450 self.setItems(runtime_->mutableBytesWith(8, 'a'));
451 self.setNumItems(8);
452 Object count(&scope, SmallInt::fromWord(-5));
453 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
454 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
455}
456
457TEST_F(BytearrayBuiltinsTest, DunderImulWithZeroReturnsEmptyBytearray) {
458 HandleScope scope(thread_);
459 Bytearray self(&scope, runtime_->newBytearray());
460 self.setItems(runtime_->mutableBytesWith(8, 'a'));
461 self.setNumItems(8);
462 Object count(&scope, SmallInt::fromWord(0));
463 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
464 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
465}
466
467TEST_F(BytearrayBuiltinsTest, DunderImulWithOneReturnsSameBytearray) {
468 HandleScope scope(thread_);
469 Bytearray self(&scope, runtime_->newBytearray());
470 const byte bytes[] = {'a', 'b'};
471 runtime_->bytearrayExtend(thread_, self, bytes);
472 Object count(&scope, SmallInt::fromWord(1));
473 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
474 EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes));
475}
476
477TEST_F(BytearrayBuiltinsTest, DunderImulReturnsRepeatedBytearray) {
478 HandleScope scope(thread_);
479 Bytearray self(&scope, runtime_->newBytearray());
480 const byte bytes[] = {'a', 'b'};
481 runtime_->bytearrayExtend(thread_, self, bytes);
482 Object count(&scope, SmallInt::fromWord(3));
483 Object result(&scope, runBuiltin(METH(bytearray, __imul__), self, count));
484 EXPECT_TRUE(isBytearrayEqualsCStr(result, "ababab"));
485}
486
487TEST_F(BytearrayBuiltinsTest, DunderLeWithNonBytesOtherReturnsNotImplemented) {
488 HandleScope scope(thread_);
489 Object self(&scope, runtime_->newBytearray());
490 Object other(&scope, SmallInt::fromWord(0));
491 Object result(&scope, runBuiltin(METH(bytearray, __le__), self, other));
492 EXPECT_TRUE(result.isNotImplementedType());
493}
494
495TEST_F(BytearrayBuiltinsTest, DunderLeWithEmptyBytearraysReturnsTrue) {
496 HandleScope scope(thread_);
497 Object self(&scope, runtime_->newBytearray());
498 Object other(&scope, runtime_->newBytearray());
499 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj());
500}
501
502TEST_F(BytearrayBuiltinsTest, DunderLeithEqualBytesReturnsTrue) {
503 HandleScope scope(thread_);
504 const byte bytes[] = {'f', 'o', 'o'};
505 Bytearray self(&scope, runtime_->newBytearray());
506 runtime_->bytearrayExtend(thread_, self, bytes);
507 Object other(&scope, runtime_->newBytesWithAll(bytes));
508 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj());
509}
510
511TEST_F(BytearrayBuiltinsTest, DunderLeWithEqualBytearrayReturnsTrue) {
512 HandleScope scope(thread_);
513 const byte bytes[] = {'f', 'o', 'o'};
514 Bytearray self(&scope, runtime_->newBytearray());
515 Bytearray other(&scope, runtime_->newBytearray());
516 runtime_->bytearrayExtend(thread_, self, bytes);
517 runtime_->bytearrayExtend(thread_, other, bytes);
518 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj());
519}
520
521TEST_F(BytearrayBuiltinsTest, DunderLeWithLongerOtherReturnsTrue) {
522 HandleScope scope(thread_);
523 const byte bytes[] = {'f', 'o', 'o'};
524 Bytearray self(&scope, runtime_->newBytearray());
525 Bytearray other(&scope, runtime_->newBytearray());
526 runtime_->bytearrayExtend(thread_, self, {bytes, 2});
527 runtime_->bytearrayExtend(thread_, other, bytes);
528 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj());
529}
530
531TEST_F(BytearrayBuiltinsTest, DunderLeWithShorterOtherReturnsFalse) {
532 HandleScope scope(thread_);
533 const byte bytes[] = {'f', 'o', 'o'};
534 Bytearray self(&scope, runtime_->newBytearray());
535 Bytearray other(&scope, runtime_->newBytearray());
536 runtime_->bytearrayExtend(thread_, self, bytes);
537 runtime_->bytearrayExtend(thread_, other, {bytes, 2});
538 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::falseObj());
539}
540
541TEST_F(BytearrayBuiltinsTest, DunderLeWithEarlierOtherReturnsFalse) {
542 HandleScope scope(thread_);
543 const byte bytes[] = {'f', 'o', 'o'};
544 Bytearray self(&scope, runtime_->newBytearray());
545 runtime_->bytearrayExtend(thread_, self, bytes);
546 Object other(&scope, runtime_->newBytes(3, 'f'));
547 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::falseObj());
548}
549
550TEST_F(BytearrayBuiltinsTest, DunderLeWithLaterOtherReturnsTrue) {
551 HandleScope scope(thread_);
552 const byte bytes[] = {'o', 'o', 'f'};
553 Bytearray self(&scope, runtime_->newBytearray());
554 runtime_->bytearrayExtend(thread_, self, bytes);
555 Object other(&scope, runtime_->newBytes(3, 'o'));
556 EXPECT_EQ(runBuiltin(METH(bytearray, __le__), self, other), Bool::trueObj());
557}
558
559TEST_F(BytearrayBuiltinsTest, DunderLenWithEmptyBytearrayReturnsZero) {
560 HandleScope scope(thread_);
561 Bytearray self(&scope, runtime_->newBytearray());
562 Object result(&scope, runBuiltin(METH(bytearray, __len__), self));
563 EXPECT_TRUE(isIntEqualsWord(*result, 0));
564}
565
566TEST_F(BytearrayBuiltinsTest, DunderLenWithNonEmptyBytearrayReturnsPositive) {
567 HandleScope scope(thread_);
568 Bytearray self(&scope, runtime_->newBytearray());
569 const byte bytes[] = {1, 2, 3, 4, 5};
570 runtime_->bytearrayExtend(thread_, self, bytes);
571 Object result(&scope, runBuiltin(METH(bytearray, __len__), self));
572 EXPECT_TRUE(isIntEqualsWord(*result, 5));
573
574 const byte bytes2[] = {6, 7};
575 runtime_->bytearrayExtend(thread_, self, bytes2);
576 result = runBuiltin(METH(bytearray, __len__), self);
577 EXPECT_TRUE(isIntEqualsWord(*result, 7));
578}
579
580TEST_F(BytearrayBuiltinsTest, DunderLtWithNonBytesOtherReturnsNotImplemented) {
581 HandleScope scope(thread_);
582 Object self(&scope, runtime_->newBytearray());
583 Object other(&scope, SmallInt::fromWord(0));
584 Object result(&scope, runBuiltin(METH(bytearray, __lt__), self, other));
585 EXPECT_TRUE(result.isNotImplementedType());
586}
587
588TEST_F(BytearrayBuiltinsTest, DunderLtWithEmptyBytearraysReturnsFalse) {
589 HandleScope scope(thread_);
590 Object self(&scope, runtime_->newBytearray());
591 Object other(&scope, runtime_->newBytearray());
592 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj());
593}
594
595TEST_F(BytearrayBuiltinsTest, DunderLtithEqualBytesReturnsFalse) {
596 HandleScope scope(thread_);
597 const byte bytes[] = {'f', 'o', 'o'};
598 Bytearray self(&scope, runtime_->newBytearray());
599 runtime_->bytearrayExtend(thread_, self, bytes);
600 Object other(&scope, runtime_->newBytesWithAll(bytes));
601 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj());
602}
603
604TEST_F(BytearrayBuiltinsTest, DunderLtWithEqualBytearrayReturnsFalse) {
605 HandleScope scope(thread_);
606 const byte bytes[] = {'f', 'o', 'o'};
607 Bytearray self(&scope, runtime_->newBytearray());
608 Bytearray other(&scope, runtime_->newBytearray());
609 runtime_->bytearrayExtend(thread_, self, bytes);
610 runtime_->bytearrayExtend(thread_, other, bytes);
611 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj());
612}
613
614TEST_F(BytearrayBuiltinsTest, DunderLtWithLongerOtherReturnsTrue) {
615 HandleScope scope(thread_);
616 const byte bytes[] = {'f', 'o', 'o'};
617 Bytearray self(&scope, runtime_->newBytearray());
618 Bytearray other(&scope, runtime_->newBytearray());
619 runtime_->bytearrayExtend(thread_, self, {bytes, 2});
620 runtime_->bytearrayExtend(thread_, other, bytes);
621 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::trueObj());
622}
623
624TEST_F(BytearrayBuiltinsTest, DunderLtWithShorterOtherReturnsFalse) {
625 HandleScope scope(thread_);
626 const byte bytes[] = {'f', 'o', 'o'};
627 Bytearray self(&scope, runtime_->newBytearray());
628 Bytearray other(&scope, runtime_->newBytearray());
629 runtime_->bytearrayExtend(thread_, self, bytes);
630 runtime_->bytearrayExtend(thread_, other, {bytes, 2});
631 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj());
632}
633
634TEST_F(BytearrayBuiltinsTest, DunderLtWithEarlierOtherReturnsFalse) {
635 HandleScope scope(thread_);
636 const byte bytes[] = {'f', 'o', 'o'};
637 Bytearray self(&scope, runtime_->newBytearray());
638 runtime_->bytearrayExtend(thread_, self, bytes);
639 Object other(&scope, runtime_->newBytes(3, 'f'));
640 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::falseObj());
641}
642
643TEST_F(BytearrayBuiltinsTest, DunderLtWithLaterOtherReturnsTrue) {
644 HandleScope scope(thread_);
645 const byte bytes[] = {'o', 'o', 'f'};
646 Bytearray self(&scope, runtime_->newBytearray());
647 runtime_->bytearrayExtend(thread_, self, bytes);
648 Object other(&scope, runtime_->newBytes(3, 'o'));
649 EXPECT_EQ(runBuiltin(METH(bytearray, __lt__), self, other), Bool::trueObj());
650}
651
652TEST_F(BytearrayBuiltinsTest, DunderMulWithNonIntRaisesTypeError) {
653 HandleScope scope(thread_);
654 Object self(&scope, runtime_->newBytearray());
655 Object count(&scope, runtime_->newList());
656 EXPECT_TRUE(raisedWithStr(
657 runBuiltin(METH(bytearray, __mul__), self, count), LayoutId::kTypeError,
658 "'list' object cannot be interpreted as an integer"));
659}
660
661TEST_F(BytearrayBuiltinsTest, DunderMulWithIntSubclassReturnsRepeatedBytes) {
662 HandleScope scope(thread_);
663 const byte view[] = {'f', 'o', 'o'};
664 Bytearray self(&scope, runtime_->newBytearray());
665 runtime_->bytearrayExtend(thread_, self, view);
666 ASSERT_FALSE(runFromCStr(runtime_, R"(
667class C(int): pass
668count = C(3)
669)")
670 .isError());
671 Object count(&scope, mainModuleAt(runtime_, "count"));
672 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
673 EXPECT_TRUE(isBytearrayEqualsCStr(result, "foofoofoo"));
674}
675
676TEST_F(BytearrayBuiltinsTest, DunderMulWithDunderIndexReturnsRepeatedBytes) {
677 HandleScope scope(thread_);
678 Bytearray self(&scope, runtime_->newBytearray());
679 bytearrayAdd(thread_, runtime_, self, 'a');
680 ASSERT_FALSE(runFromCStr(runtime_, R"(
681class C:
682 def __index__(self):
683 return 2
684count = C()
685)")
686 .isError());
687 Object count(&scope, mainModuleAt(runtime_, "count"));
688 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
689 EXPECT_TRUE(isBytearrayEqualsCStr(result, "aa"));
690}
691
692TEST_F(BytearrayBuiltinsTest, DunderMulWithBadDunderIndexRaisesTypeError) {
693 HandleScope scope(thread_);
694 Object self(&scope, runtime_->newBytearray());
695 ASSERT_FALSE(runFromCStr(runtime_, R"(
696class C:
697 def __index__(self):
698 return "foo"
699count = C()
700)")
701 .isError());
702 Object count(&scope, mainModuleAt(runtime_, "count"));
703 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __mul__), self, count),
704 LayoutId::kTypeError,
705 "__index__ returned non-int (type str)"));
706}
707
708TEST_F(BytearrayBuiltinsTest, DunderMulPropagatesDunderIndexError) {
709 HandleScope scope(thread_);
710 Object self(&scope, runtime_->newBytearray());
711 ASSERT_FALSE(runFromCStr(runtime_, R"(
712class C:
713 def __index__(self):
714 raise ArithmeticError("called __index__")
715count = C()
716)")
717 .isError());
718 Object count(&scope, mainModuleAt(runtime_, "count"));
719 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __mul__), self, count),
720 LayoutId::kArithmeticError, "called __index__"));
721}
722
723TEST_F(BytearrayBuiltinsTest, DunderMulWithLargeIntRaisesOverflowError) {
724 HandleScope scope(thread_);
725 Bytearray self(&scope, runtime_->newBytearray());
726 const uword digits[] = {1, 1};
727 Object count(&scope, runtime_->newLargeIntWithDigits(digits));
728 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytearray, __mul__), self, count),
729 LayoutId::kOverflowError,
730 "cannot fit 'int' into an index-sized integer"));
731}
732
733TEST_F(BytearrayBuiltinsTest, DunderMulWithOverflowRaisesMemoryError) {
734 HandleScope scope(thread_);
735 Bytearray self(&scope, runtime_->newBytearray());
736 const byte bytes[] = {'a', 'b', 'c'};
737 runtime_->bytearrayExtend(thread_, self, bytes);
738 Object count(&scope, SmallInt::fromWord(SmallInt::kMaxValue / 2));
739 EXPECT_TRUE(raised(runBuiltin(METH(bytearray, __mul__), self, count),
740 LayoutId::kMemoryError));
741}
742
743TEST_F(BytearrayBuiltinsTest,
744 DunderMulWithEmptyBytearrayReturnsEmptyBytearray) {
745 HandleScope scope(thread_);
746 Object self(&scope, runtime_->newBytearray());
747 Object count(&scope, SmallInt::fromWord(5));
748 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
749 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
750}
751
752TEST_F(BytearrayBuiltinsTest, DunderMulWithNegativeReturnsEmptyBytearray) {
753 HandleScope scope(thread_);
754 Bytearray self(&scope, runtime_->newBytearray());
755 self.setItems(runtime_->mutableBytesWith(8, 'a'));
756 self.setNumItems(8);
757 Object count(&scope, SmallInt::fromWord(-5));
758 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
759 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
760}
761
762TEST_F(BytearrayBuiltinsTest, DunderMulWithZeroReturnsEmptyBytearray) {
763 HandleScope scope(thread_);
764 Bytearray self(&scope, runtime_->newBytearray());
765 self.setItems(runtime_->mutableBytesWith(8, 'a'));
766 self.setNumItems(8);
767 Object count(&scope, SmallInt::fromWord(0));
768 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
769 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
770}
771
772TEST_F(BytearrayBuiltinsTest, DunderMulWithOneReturnsSameBytearray) {
773 HandleScope scope(thread_);
774 Bytearray self(&scope, runtime_->newBytearray());
775 const byte bytes[] = {'a', 'b'};
776 runtime_->bytearrayExtend(thread_, self, bytes);
777 Object count(&scope, SmallInt::fromWord(1));
778 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
779 EXPECT_TRUE(isBytearrayEqualsBytes(result, bytes));
780}
781
782TEST_F(BytearrayBuiltinsTest, DunderMulReturnsRepeatedBytearray) {
783 HandleScope scope(thread_);
784 Bytearray self(&scope, runtime_->newBytearray());
785 const byte bytes[] = {'a', 'b'};
786 runtime_->bytearrayExtend(thread_, self, bytes);
787 Object count(&scope, SmallInt::fromWord(3));
788 Object result(&scope, runBuiltin(METH(bytearray, __mul__), self, count));
789 EXPECT_TRUE(isBytearrayEqualsCStr(result, "ababab"));
790}
791
792TEST_F(BytearrayBuiltinsTest, DunderNeWithNonBytesOtherReturnsNotImplemented) {
793 HandleScope scope(thread_);
794 Object self(&scope, runtime_->newBytearray());
795 Object other(&scope, SmallInt::fromWord(0));
796 Object result(&scope, runBuiltin(METH(bytearray, __ne__), self, other));
797 EXPECT_TRUE(result.isNotImplementedType());
798}
799
800TEST_F(BytearrayBuiltinsTest, DunderNeWithEmptyBytearraysReturnsFalse) {
801 HandleScope scope(thread_);
802 Object self(&scope, runtime_->newBytearray());
803 Object other(&scope, runtime_->newBytearray());
804 EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::falseObj());
805}
806
807TEST_F(BytearrayBuiltinsTest, DunderNeWithEqualBytesReturnsFalse) {
808 HandleScope scope(thread_);
809 const byte bytes[] = {'f', 'o', 'o'};
810 Bytearray self(&scope, runtime_->newBytearray());
811 runtime_->bytearrayExtend(thread_, self, bytes);
812 Object other(&scope, runtime_->newBytesWithAll(bytes));
813 EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::falseObj());
814}
815
816TEST_F(BytearrayBuiltinsTest, DunderNeWithEqualBytearrayReturnsFalse) {
817 HandleScope scope(thread_);
818 const byte bytes[] = {'f', 'o', 'o'};
819 Bytearray self(&scope, runtime_->newBytearray());
820 Bytearray other(&scope, runtime_->newBytearray());
821 runtime_->bytearrayExtend(thread_, self, bytes);
822 runtime_->bytearrayExtend(thread_, other, bytes);
823 EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::falseObj());
824}
825
826TEST_F(BytearrayBuiltinsTest, DunderNeWithDifferentLengthsReturnsTrue) {
827 HandleScope scope(thread_);
828 const byte bytes[] = {'f', 'o', 'o'};
829 Bytearray self(&scope, runtime_->newBytearray());
830 Bytearray other(&scope, runtime_->newBytearray());
831 runtime_->bytearrayExtend(thread_, self, bytes);
832 runtime_->bytearrayExtend(thread_, other, {bytes, 2});
833 EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::trueObj());
834}
835
836TEST_F(BytearrayBuiltinsTest, DunderNeWithDifferentContentsReturnsTrue) {
837 HandleScope scope(thread_);
838 const byte bytes[] = {'f', 'o', 'o'};
839 Bytearray self(&scope, runtime_->newBytearray());
840 runtime_->bytearrayExtend(thread_, self, bytes);
841 Object other(&scope, runtime_->newBytes(3, 'f'));
842 EXPECT_EQ(runBuiltin(METH(bytearray, __ne__), self, other), Bool::trueObj());
843}
844
845TEST_F(BytearrayBuiltinsTest, DunderNewWithNonTypeRaisesTypeError) {
846 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray.__new__(3)"),
847 LayoutId::kTypeError, "not a type object"));
848}
849
850TEST_F(BytearrayBuiltinsTest, DunderNewWithNonBytearrayRaisesTypeError) {
851 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray.__new__(int)"),
852 LayoutId::kTypeError,
853 "not a subtype of bytearray"));
854}
855
856TEST_F(BytearrayBuiltinsTest, DunderNewReturnsEmptyBytearray) {
857 HandleScope scope(thread_);
858 Type cls(&scope, runtime_->typeAt(LayoutId::kBytearray));
859 Object self(&scope, runBuiltin(METH(bytearray, __new__), cls));
860 EXPECT_TRUE(isBytearrayEqualsCStr(self, ""));
861}
862
863TEST_F(BytearrayBuiltinsTest, NewBytearray) {
864 HandleScope scope(thread_);
865 ASSERT_FALSE(
866 runFromCStr(runtime_, "obj = bytearray(b'Hello world!')").isError());
867 Bytearray self(&scope, mainModuleAt(runtime_, "obj"));
868 EXPECT_TRUE(isBytearrayEqualsCStr(self, "Hello world!"));
869}
870
871TEST_F(BytearrayBuiltinsTest, DunderReprWithEmptyBytearrayReturnsEmptyRepr) {
872 HandleScope scope(thread_);
873 Bytearray self(&scope, runtime_->newBytearray());
874 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
875 EXPECT_TRUE(isStrEqualsCStr(*repr, "bytearray(b'')"));
876}
877
878TEST_F(BytearrayBuiltinsTest, DunderReprWithSimpleBytearrayReturnsRepr) {
879 HandleScope scope(thread_);
880 Bytearray self(&scope, runtime_->newBytearray());
881 const byte bytes[] = {'f', 'o', 'o'};
882 runtime_->bytearrayExtend(thread_, self, bytes);
883 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
884 EXPECT_TRUE(isStrEqualsCStr(*repr, "bytearray(b'foo')"));
885}
886
887TEST_F(BytearrayBuiltinsTest,
888 DunderReprWithDoubleQuoteUsesSingleQuoteDelimiters) {
889 HandleScope scope(thread_);
890 Bytearray self(&scope, runtime_->newBytearray());
891 const byte bytes[] = {'_', '"', '_'};
892 runtime_->bytearrayExtend(thread_, self, bytes);
893 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
894 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'_"_'))"));
895}
896
897TEST_F(BytearrayBuiltinsTest,
898 DunderReprWithSingleQuoteUsesDoubleQuoteDelimiters) {
899 HandleScope scope(thread_);
900 Bytearray self(&scope, runtime_->newBytearray());
901 const byte bytes[] = {'_', '\'', '_'};
902 runtime_->bytearrayExtend(thread_, self, bytes);
903 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
904 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b"_\'_"))"));
905}
906
907TEST_F(BytearrayBuiltinsTest,
908 DunderReprWithBothQuotesUsesSingleQuoteDelimiters) {
909 HandleScope scope(thread_);
910 Bytearray self(&scope, runtime_->newBytearray());
911 const byte bytes[] = {'_', '"', '_', '\'', '_'};
912 runtime_->bytearrayExtend(thread_, self, bytes);
913 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
914 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'_"_\'_'))"));
915}
916
917TEST_F(BytearrayBuiltinsTest, DunderReprWithSpecialBytesUsesEscapeSequences) {
918 HandleScope scope(thread_);
919 Bytearray self(&scope, runtime_->newBytearray());
920 const byte bytes[] = {'\\', '\t', '\n', '\r'};
921 runtime_->bytearrayExtend(thread_, self, bytes);
922 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
923 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'\\\t\n\r'))"));
924}
925
926TEST_F(BytearrayBuiltinsTest, DunderReprWithSmallAndLargeBytesUsesHex) {
927 HandleScope scope(thread_);
928 Bytearray self(&scope, runtime_->newBytearray());
929 const byte bytes[] = {0, 0x1f, 0x80, 0xff};
930 runtime_->bytearrayExtend(thread_, self, bytes);
931 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), self));
932 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(bytearray(b'\x00\x1f\x80\xff'))"));
933}
934
935TEST_F(BytearrayBuiltinsTest, DunderReprWithSubclassUsesClassName) {
936 ASSERT_FALSE(runFromCStr(runtime_, R"(
937class C(bytearray): pass
938obj = C(b'hello world')
939)")
940 .isError());
941 HandleScope scope(thread_);
942 Object obj(&scope, mainModuleAt(runtime_, "obj"));
943 Object repr(&scope, runBuiltin(METH(bytearray, __repr__), obj));
944 EXPECT_TRUE(isStrEqualsCStr(*repr, "C(b'hello world')"));
945}
946
947TEST_F(BytearrayBuiltinsTest, DunderRmulCallsDunderMul) {
948 HandleScope scope(thread_);
949 ASSERT_FALSE(
950 runFromCStr(runtime_, "result = 3 * bytearray(b'123')").isError());
951 Object result(&scope, mainModuleAt(runtime_, "result"));
952 EXPECT_TRUE(isBytearrayEqualsCStr(result, "123123123"));
953}
954
955TEST_F(BytearrayBuiltinsTest, HexWithEmptyBytearrayReturnsEmptyString) {
956 HandleScope scope(thread_);
957 Object self(&scope, runtime_->newBytearray());
958 Object result(&scope, runBuiltin(METH(bytearray, hex), self));
959 EXPECT_TRUE(isStrEqualsCStr(*result, ""));
960}
961
962TEST_F(BytearrayBuiltinsTest, HexWithNonEmptyBytesReturnsString) {
963 HandleScope scope(thread_);
964 Bytearray self(&scope, runtime_->newBytearray());
965 const byte bytes[] = {0x60, 0xe, 0x18, 0x21};
966 runtime_->bytearrayExtend(thread_, self, bytes);
967 Object result(&scope, runBuiltin(METH(bytearray, hex), self));
968 EXPECT_TRUE(isStrEqualsCStr(*result, "600e1821"));
969}
970
971TEST_F(BytearrayBuiltinsTest, JoinWithNonIterableRaisesTypeError) {
972 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray(b'').join(0)"),
973 LayoutId::kTypeError,
974 "'int' object is not iterable"));
975}
976
977TEST_F(BytearrayBuiltinsTest, JoinWithMistypedIterableRaisesTypeError) {
978 EXPECT_TRUE(raisedWithStr(
979 runFromCStr(runtime_, "bytearray(b' ').join([1])"), LayoutId::kTypeError,
980 "sequence item 0: expected a bytes-like object, 'int' found"));
981}
982
983TEST_F(BytearrayBuiltinsTest, JoinWithIterableReturnsBytearray) {
984 ASSERT_FALSE(runFromCStr(runtime_, R"(
985class Foo:
986 def __iter__(self):
987 return [b'ab', b'c', b'def'].__iter__()
988result = bytearray(b' ').join(Foo())
989)")
990 .isError());
991 HandleScope scope(thread_);
992 Object result(&scope, mainModuleAt(runtime_, "result"));
993 EXPECT_TRUE(isBytearrayEqualsCStr(result, "ab c def"));
994}
995
996TEST_F(BytearrayBuiltinsTest, MaketransWithNonBytesLikeFromRaisesTypeError) {
997 EXPECT_TRUE(raisedWithStr(
998 runFromCStr(runtime_, "bytearray.maketrans([1,2], b'ab')"),
999 LayoutId::kTypeError, "a bytes-like object is required, not 'list'"));
1000}
1001
1002TEST_F(BytearrayBuiltinsTest, MaketransWithNonBytesLikeToRaisesTypeError) {
1003 EXPECT_TRUE(raisedWithStr(
1004 runFromCStr(runtime_, "bytearray.maketrans(b'1', 2)"),
1005 LayoutId::kTypeError, "a bytes-like object is required, not 'int'"));
1006}
1007
1008TEST_F(BytearrayBuiltinsTest, MaketransWithDifferentLengthsRaisesValueError) {
1009 EXPECT_TRUE(raisedWithStr(
1010 runFromCStr(runtime_, "bytearray.maketrans(b'12', bytearray())"),
1011 LayoutId::kValueError, "maketrans arguments must have same length"));
1012}
1013
1014TEST_F(BytearrayBuiltinsTest, MaketransWithEmptyReturnsDefaultBytes) {
1015 HandleScope scope(thread_);
1016 ASSERT_FALSE(
1017 runFromCStr(runtime_, "result = bytearray.maketrans(bytearray(), b'')")
1018 .isError());
1019 Object result(&scope, mainModuleAt(runtime_, "result"));
1020 byte expected[256];
1021 for (word i = 0; i < 256; i++) {
1022 expected[i] = i;
1023 }
1024 EXPECT_TRUE(isBytesEqualsBytes(result, expected));
1025}
1026
1027TEST_F(BytearrayBuiltinsTest, MaketransWithNonEmptyReturnsBytes) {
1028 HandleScope scope(thread_);
1029 ASSERT_FALSE(
1030 runFromCStr(runtime_,
1031 "result = bytearray.maketrans(bytearray(b'abc'), b'123')")
1032 .isError());
1033 Object result(&scope, mainModuleAt(runtime_, "result"));
1034 ASSERT_TRUE(result.isBytes());
1035 LargeBytes actual(&scope, *result);
1036 EXPECT_EQ(actual.byteAt('a'), '1');
1037 EXPECT_EQ(actual.byteAt('b'), '2');
1038 EXPECT_EQ(actual.byteAt('c'), '3');
1039}
1040
1041TEST_F(BytearrayBuiltinsTest, TranslateWithNonBytesLikeTableRaisesTypeError) {
1042 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray().translate(42)"),
1043 LayoutId::kTypeError,
1044 "a bytes-like object is required, not 'int'"));
1045}
1046
1047TEST_F(BytearrayBuiltinsTest, TranslateWithNonBytesLikeDeleteRaisesTypeError) {
1048 EXPECT_TRUE(raisedWithStr(
1049 runFromCStr(runtime_, "bytearray().translate(None, 42)"),
1050 LayoutId::kTypeError, "a bytes-like object is required, not 'int'"));
1051}
1052
1053TEST_F(BytearrayBuiltinsTest, TranslateWithShortTableRaisesValueError) {
1054 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytearray().translate(b'')"),
1055 LayoutId::kValueError,
1056 "translation table must be 256 characters long"));
1057}
1058
1059TEST_F(BytearrayBuiltinsTest, TranslateWithEmptyBytearrayReturnsNewBytearray) {
1060 HandleScope scope(thread_);
1061 Object self(&scope, runtime_->newBytearray());
1062 Object table(&scope, NoneType::object());
1063 Object del(&scope, runtime_->newBytearray());
1064 Object result(&scope,
1065 runBuiltin(METH(bytearray, translate), self, table, del));
1066 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
1067 EXPECT_NE(result, self);
1068}
1069
1070TEST_F(BytearrayBuiltinsTest, TranslateWithNonEmptySecondArgDeletesBytes) {
1071 HandleScope scope(thread_);
1072 const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'};
1073 const byte abc[] = {'a', 'b', 'c'};
1074 Bytearray self(&scope, runtime_->newBytearray());
1075 runtime_->bytearrayExtend(thread_, self, alabama);
1076 Object table(&scope, NoneType::object());
1077 Object del(&scope, runtime_->newBytesWithAll(abc));
1078 Object result(&scope,
1079 runBuiltin(METH(bytearray, translate), self, table, del));
1080 EXPECT_TRUE(isBytearrayEqualsCStr(result, "Alm"));
1081}
1082
1083TEST_F(BytearrayBuiltinsTest, TranslateWithTableTranslatesBytes) {
1084 HandleScope scope(thread_);
1085 ASSERT_FALSE(
1086 runFromCStr(runtime_, "table = bytes.maketrans(b'Aa', b'12')").isError());
1087 const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'};
1088 Bytearray self(&scope, runtime_->newBytearray());
1089 runtime_->bytearrayExtend(thread_, self, alabama);
1090 Object table(&scope, mainModuleAt(runtime_, "table"));
1091 Object del(&scope, runtime_->newBytearray());
1092 Object result(&scope,
1093 runBuiltin(METH(bytearray, translate), self, table, del));
1094 EXPECT_TRUE(isBytearrayEqualsCStr(result, "1l2b2m2"));
1095}
1096
1097TEST_F(BytearrayBuiltinsTest,
1098 TranslateWithTableAndDeleteTranslatesAndDeletesBytes) {
1099 HandleScope scope(thread_);
1100 ASSERT_FALSE(
1101 runFromCStr(runtime_, "table = bytes.maketrans(b'Aa', b'12')").isError());
1102 const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'};
1103 const byte abc[] = {'a', 'b', 'c'};
1104 Bytearray self(&scope, runtime_->newBytearray());
1105 runtime_->bytearrayExtend(thread_, self, alabama);
1106 Object table(&scope, mainModuleAt(runtime_, "table"));
1107 Object del(&scope, runtime_->newBytesWithAll(abc));
1108 Object result(&scope,
1109 runBuiltin(METH(bytearray, translate), self, table, del));
1110 EXPECT_TRUE(isBytearrayEqualsCStr(result, "1lm"));
1111}
1112
1113TEST_F(BytearrayBuiltinsTest, TranslateDeletesAllBytes) {
1114 HandleScope scope(thread_);
1115 const byte alabama[] = {'b', 'a', 'c', 'a', 'a', 'c', 'a'};
1116 const byte abc[] = {'a', 'b', 'c'};
1117 Bytearray self(&scope, runtime_->newBytearray());
1118 runtime_->bytearrayExtend(thread_, self, alabama);
1119 Object table(&scope, NoneType::object());
1120 Object del(&scope, runtime_->newBytesWithAll(abc));
1121 Object result(&scope,
1122 runBuiltin(METH(bytearray, translate), self, table, del));
1123 EXPECT_TRUE(isBytearrayEqualsCStr(result, ""));
1124}
1125
1126TEST_F(BytearrayBuiltinsTest, DunderIterReturnsBytearrayIterator) {
1127 ASSERT_FALSE(
1128 runFromCStr(runtime_, "result = type(bytearray().__iter__())").isError());
1129 HandleScope scope(thread_);
1130 Object result(&scope, mainModuleAt(runtime_, "result"));
1131 EXPECT_EQ(*result, runtime_->typeAt(LayoutId::kBytearrayIterator));
1132}
1133
1134TEST_F(BytearrayBuiltinsTest, IteratorDunderNextReturnsNextElement) {
1135 ASSERT_FALSE(runFromCStr(runtime_, R"(
1136ba = bytearray(b'abc')
1137it = iter(ba)
1138r0 = it.__next__()
1139r1 = it.__next__()
1140r2 = it.__next__()
1141try:
1142 it.__next__()
1143 r3 = False
1144except StopIteration:
1145 r3 = True
1146)")
1147 .isError());
1148 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "r0"), 'a'));
1149 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "r1"), 'b'));
1150 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "r2"), 'c'));
1151 EXPECT_EQ(mainModuleAt(runtime_, "r3"), Bool::trueObj());
1152}
1153
1154TEST_F(BytearrayBuiltinsTest,
1155 IteratorDunderNextStopsIterationWhenBytearrayIsShrunk) {
1156 ASSERT_FALSE(runFromCStr(runtime_, R"(
1157ba = bytearray(b'abc')
1158it = iter(ba)
1159)")
1160 .isError());
1161 HandleScope scope(thread_);
1162 Bytearray ba(&scope, mainModuleAt(runtime_, "ba"));
1163 BytearrayIterator it(&scope, mainModuleAt(runtime_, "it"));
1164 ba.setNumItems(0);
1165 EXPECT_TRUE(raised(thread_->invokeMethod1(it, ID(__next__)),
1166 LayoutId::kStopIteration));
1167}
1168
1169} // namespace testing
1170} // namespace py