this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "bytes-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 BytesBuiltinsTest = RuntimeFixture;
13using BytesIteratorBuiltinsTest = RuntimeFixture;
14
15TEST_F(BytesBuiltinsTest, BuiltinBaseIsBytes) {
16 HandleScope scope(thread_);
17 Type bytes_type(&scope, runtime_->typeAt(LayoutId::kBytes));
18 EXPECT_EQ(bytes_type.builtinBase(), LayoutId::kBytes);
19}
20
21TEST_F(BytesBuiltinsTest, BytesIsValidUTF8ReturnsTrue) {
22 EXPECT_TRUE(bytesIsValidUTF8(Bytes::empty()));
23
24 HandleScope scope(thread_);
25 const byte zeros_bytes[] = {0, 0, 0};
26 Bytes zeros(&scope, runtime_->newBytesWithAll(zeros_bytes));
27 EXPECT_TRUE(bytesIsValidUTF8(*zeros));
28
29 const byte test0[] = {'S', ':', 'a'};
30 EXPECT_TRUE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test0))));
31 const byte test1[] = {'S', ':', 0xC3, 0xA4};
32 EXPECT_TRUE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test1))));
33 const byte test2[] = {'S', ':', 0xE2, 0x88, 0x91};
34 EXPECT_TRUE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test2))));
35 const byte test3[] = {'S', ':', 0xF0, 0x9F, 0x90, 0x8D};
36 EXPECT_TRUE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test3))));
37
38 const byte test_misc[] = {0xEC, 0x95, 0x88, 0xEB, 0x85, 0x95, ' ',
39 0xEC, 0x84, 0xB8, 0xEC, 0x83, 0x81, 0};
40 EXPECT_TRUE(
41 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test_misc))));
42
43 const byte max_unicode[] = {0xF4, 0x8F, 0xBF, 0xBF};
44 EXPECT_TRUE(
45 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(max_unicode))));
46
47 const byte min_surrogate_minus_one[] = {0xED, 0x9F, 0xBF};
48 EXPECT_TRUE(bytesIsValidUTF8(
49 Bytes::cast(runtime_->newBytesWithAll(min_surrogate_minus_one))));
50 const byte max_surrogate_plus_one[] = {0xEE, 0x80, 0x80};
51 EXPECT_TRUE(bytesIsValidUTF8(
52 Bytes::cast(runtime_->newBytesWithAll(max_surrogate_plus_one))));
53}
54
55TEST_F(BytesBuiltinsTest,
56 BytesIsValidUTF8WithContinuationAfterValidCharReturnsFalse) {
57 const byte test0[] = {0x80};
58 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test0))));
59 const byte test1[] = {'a', 0xB3};
60 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test1))));
61 const byte test2[] = {0xC3, 0xA4, 0xB3};
62 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test2))));
63 const byte test3[] = {0xE2, 0x88, 0x91, 0xB3};
64 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test3))));
65 const byte test4[] = {0xF0, 0x9F, 0x90, 0x8D, 0xB3};
66 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test4))));
67}
68
69TEST_F(BytesBuiltinsTest, BytesIsValidUTF8WithMissingContinuationReturnsFalse) {
70 const byte test0[] = {0xC3};
71 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test0))));
72 const byte test1[] = {0xC3, 0};
73 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test1))));
74
75 const byte test2[] = {0xE2};
76 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test2))));
77 const byte test3[] = {0xE2, 0};
78 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test3))));
79 const byte test5[] = {0xE2, 0x88};
80 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test5))));
81 const byte test4[] = {0xE2, 0, 0};
82 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test4))));
83 const byte test6[] = {0xE2, 0x88, 0};
84 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test6))));
85
86 const byte test7[] = {0xF0};
87 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test7))));
88 const byte test8[] = {0xF0, 0};
89 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test8))));
90 const byte test9[] = {0xF0, 0x9F};
91 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test9))));
92 const byte test10[] = {0xF0, 0, 0};
93 EXPECT_FALSE(
94 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test10))));
95 const byte test11[] = {0xF0, 0x9F, 0};
96 EXPECT_FALSE(
97 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test11))));
98 const byte test12[] = {0xF0, 0x9F, 0x90};
99 EXPECT_FALSE(
100 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test12))));
101 const byte test13[] = {0xF0, 0, 0, 0};
102 EXPECT_FALSE(
103 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test13))));
104 const byte test14[] = {0xF0, 0x9F, 0x90, 0};
105 EXPECT_FALSE(
106 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test14))));
107}
108
109TEST_F(BytesBuiltinsTest,
110 BytesIsValidUTF8WithValueTooSmallForEncodingReturnsFalse) {
111 const byte test0[] = {0xC0, 0x84};
112 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test0))));
113 const byte test1[] = {0xE0, 0x80, 0x80};
114 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test1))));
115 const byte test2[] = {0xE0, 0x9F, 0xBF};
116 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test2))));
117 const byte test3[] = {0xF0, 0x80, 0x80, 0x80};
118 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test3))));
119 const byte test4[] = {0xF0, 0x80, 0x9F, 0xBF};
120 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test4))));
121 const byte test5[] = {0xF4, 0x90, 0x80, 0x80};
122 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test5))));
123 const byte test6[] = {0xF7, 0xBF, 0xBF, 0xBF};
124 EXPECT_FALSE(bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(test6))));
125}
126
127TEST_F(BytesBuiltinsTest, BytesIsValidUTF8WithSurrogateReturnsFalse) {
128 const byte min_surrogate[] = {0xED, 0xA0, 0x80};
129 EXPECT_FALSE(
130 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(min_surrogate))));
131 const byte max_surrogate[] = {0xED, 0xBF, 0xBF};
132 EXPECT_FALSE(
133 bytesIsValidUTF8(Bytes::cast(runtime_->newBytesWithAll(max_surrogate))));
134}
135
136TEST_F(BytesBuiltinsTest, BytesIsValidStrWithSurrogateReturnsTrue) {
137 const byte min_surrogate[] = {0xED, 0xA0, 0x80};
138 EXPECT_TRUE(
139 bytesIsValidStr(Bytes::cast(runtime_->newBytesWithAll(min_surrogate))));
140 const byte max_surrogate[] = {0xED, 0xBF, 0xBF};
141 EXPECT_TRUE(
142 bytesIsValidStr(Bytes::cast(runtime_->newBytesWithAll(max_surrogate))));
143}
144
145TEST_F(BytesBuiltinsTest, BytesSubseqReturnsBytes) {
146 HandleScope scope(thread_);
147
148 View<byte> hello(reinterpret_cast<const byte*>("Hello world!"), 12);
149 Bytes bytes(&scope, runtime_->newBytesWithAll(hello));
150 ASSERT_EQ(bytes.length(), 12);
151
152 Bytes copy(&scope, bytesSubseq(thread_, bytes, 6, 5));
153 EXPECT_TRUE(isBytesEqualsCStr(copy, "world"));
154}
155
156TEST_F(BytesBuiltinsTest, FindWithSameBytesReturnsZero) {
157 HandleScope scope(thread_);
158 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
159 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
160 word start = 0;
161 word end = haystack.length();
162 word result = bytesFind(haystack, haystack.length(), haystack,
163 haystack.length(), start, end);
164 EXPECT_EQ(result, 0);
165}
166
167TEST_F(BytesBuiltinsTest, FindWithWideBoundsReturnsIndex) {
168 HandleScope scope(thread_);
169 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
170 const byte needle_bytes[] = {100, 74};
171 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
172 Bytes needle(&scope, runtime_->newBytesWithAll(needle_bytes));
173 word start = -1000;
174 word end = 123;
175 word result = bytesFind(haystack, haystack.length(), needle, needle.length(),
176 start, end);
177 EXPECT_EQ(result, 2);
178}
179
180TEST_F(BytesBuiltinsTest, FindWithNegativeBoundsReturnsIndex) {
181 HandleScope scope(thread_);
182 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
183 const byte needle_bytes[] = {100, 74};
184 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
185 Bytes needle(&scope, runtime_->newBytesWithAll(needle_bytes));
186 word start = -5;
187 word end = -2;
188 word result = bytesFind(haystack, haystack.length(), needle, needle.length(),
189 start, end);
190 EXPECT_EQ(result, 2);
191}
192
193TEST_F(BytesBuiltinsTest, FindWithEmptyReturnsAdjustedStart) {
194 HandleScope scope(thread_);
195 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
196 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
197 Bytes needle(&scope, Bytes::empty());
198 word start = -3;
199 word end = -1;
200 word result = bytesFind(haystack, haystack.length(), needle, needle.length(),
201 start, end);
202 EXPECT_EQ(result, 3);
203}
204
205TEST_F(BytesBuiltinsTest, FindWithEndLessThanStartReturnsNegativeOne) {
206 HandleScope scope(thread_);
207 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
208 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
209 Bytes needle(&scope, Bytes::empty());
210 word start = 3;
211 word end = 2;
212 word result = bytesFind(haystack, haystack.length(), needle, needle.length(),
213 start, end);
214 EXPECT_EQ(result, -1);
215}
216
217TEST_F(BytesBuiltinsTest, FindWithSingleCharReturnsFirstIndexInRange) {
218 HandleScope scope(thread_);
219 const byte haystack_bytes[] = {100, 55, 100, 74, 100, 118};
220 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
221 Bytes needle(&scope, runtime_->newBytes(1, 100));
222 word start = 1;
223 word end = haystack.length();
224 word result = bytesFind(haystack, haystack.length(), needle, needle.length(),
225 start, end);
226 EXPECT_EQ(result, 2);
227}
228
229TEST_F(BytesBuiltinsTest, RFindWithSameBytesReturnsZero) {
230 HandleScope scope(thread_);
231 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
232 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
233 word start = 0;
234 word end = haystack.length();
235 word result = bytesRFind(haystack, haystack.length(), haystack,
236 haystack.length(), start, end);
237 EXPECT_EQ(result, 0);
238}
239
240TEST_F(BytesBuiltinsTest, RFindWithWideBoundsReturnsIndex) {
241 HandleScope scope(thread_);
242 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
243 const byte needle_bytes[] = {100, 74};
244 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
245 Bytes needle(&scope, runtime_->newBytesWithAll(needle_bytes));
246 word start = -1000;
247 word end = 123;
248 word result = bytesRFind(haystack, haystack.length(), needle, needle.length(),
249 start, end);
250 EXPECT_EQ(result, 2);
251}
252
253TEST_F(BytesBuiltinsTest, RFindWithNegativeBoundsReturnsIndex) {
254 HandleScope scope(thread_);
255 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
256 const byte needle_bytes[] = {100, 74};
257 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
258 Bytes needle(&scope, runtime_->newBytesWithAll(needle_bytes));
259 word start = -5;
260 word end = -2;
261 word result = bytesRFind(haystack, haystack.length(), needle, needle.length(),
262 start, end);
263 EXPECT_EQ(result, 2);
264}
265
266TEST_F(BytesBuiltinsTest, RFindWithEmptyReturnsAdjustedEnd) {
267 HandleScope scope(thread_);
268 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
269 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
270 Bytes needle(&scope, Bytes::empty());
271 word start = -3;
272 word end = -1;
273 word result = bytesRFind(haystack, haystack.length(), needle, needle.length(),
274 start, end);
275 EXPECT_EQ(result, 5);
276}
277
278TEST_F(BytesBuiltinsTest, RFindWithEndLessThanStartReturnsNegativeOne) {
279 HandleScope scope(thread_);
280 const byte haystack_bytes[] = {102, 55, 100, 74, 91, 118};
281 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
282 Bytes needle(&scope, Bytes::empty());
283 word start = 3;
284 word end = 2;
285 word result = bytesRFind(haystack, haystack.length(), needle, needle.length(),
286 start, end);
287 EXPECT_EQ(result, -1);
288}
289
290TEST_F(BytesBuiltinsTest, RFindWithSingleCharReturnsLastIndexInRange) {
291 HandleScope scope(thread_);
292 const byte haystack_bytes[] = {100, 55, 100, 74, 100, 118};
293 Bytes haystack(&scope, runtime_->newBytesWithAll(haystack_bytes));
294 Bytes needle(&scope, runtime_->newBytes(1, 100));
295 word start = 0;
296 word end = 4;
297 word result = bytesRFind(haystack, haystack.length(), needle, needle.length(),
298 start, end);
299 EXPECT_EQ(result, 2);
300}
301
302TEST_F(BytesBuiltinsTest, DunderAddWithTooFewArgsRaisesTypeError) {
303 EXPECT_TRUE(raisedWithStr(
304 runFromCStr(runtime_, "bytes.__add__(b'')"), LayoutId::kTypeError,
305 "'bytes.__add__' takes min 2 positional arguments but 1 given"));
306}
307
308TEST_F(BytesBuiltinsTest, DunderAddWithTooManyArgsRaisesTypeError) {
309 EXPECT_TRUE(raisedWithStr(
310 runFromCStr(runtime_, "bytes.__add__(b'', b'', b'')"),
311 LayoutId::kTypeError,
312 "'bytes.__add__' takes max 2 positional arguments but 3 given"));
313}
314
315TEST_F(BytesBuiltinsTest, DunderAddWithNonBytesSelfRaisesTypeError) {
316 HandleScope scope(thread_);
317 Object self(&scope, SmallInt::fromWord(0));
318 Object other(&scope, runtime_->newBytes(1, '1'));
319 Object sum(&scope, runBuiltin(METH(bytes, __add__), self, other));
320 EXPECT_TRUE(raised(*sum, LayoutId::kTypeError));
321}
322
323TEST_F(BytesBuiltinsTest, DunderAddWithNonBytesOtherRaisesTypeError) {
324 HandleScope scope(thread_);
325 Object self(&scope, runtime_->newBytes(1, '1'));
326 Object other(&scope, SmallInt::fromWord(2));
327 Object sum(&scope, runBuiltin(METH(bytes, __add__), self, other));
328 EXPECT_TRUE(raised(*sum, LayoutId::kTypeError));
329}
330
331TEST_F(BytesBuiltinsTest, DunderAddWithBytesLikeOtherReturnsBytes) {
332 Thread* thread = Thread::current();
333 HandleScope scope(thread);
334 Object self(&scope, runtime_->newBytes(1, '1'));
335 Bytearray other(&scope, runtime_->newBytearray());
336 const byte buf[] = {'2', '3'};
337 runtime_->bytearrayExtend(thread, other, buf);
338 Object sum(&scope, runBuiltin(METH(bytes, __add__), self, other));
339 EXPECT_TRUE(isBytesEqualsCStr(sum, "123"));
340}
341
342TEST_F(BytesBuiltinsTest, DunderAddWithBytesSubclassReturnsBytes) {
343 ASSERT_FALSE(runFromCStr(runtime_, R"(
344class Foo(bytes): pass
345self = Foo(b'abc')
346other = Foo(b'123')
347)")
348 .isError());
349 HandleScope scope(thread_);
350 Object self(&scope, mainModuleAt(runtime_, "self"));
351 Object other(&scope, mainModuleAt(runtime_, "other"));
352 Object sum(&scope, runBuiltin(METH(bytes, __add__), self, other));
353 EXPECT_TRUE(isBytesEqualsCStr(sum, "abc123"));
354}
355
356TEST_F(BytesBuiltinsTest, DunderAddWithTwoBytesReturnsConcatenatedBytes) {
357 HandleScope scope(thread_);
358 Object self(&scope, runtime_->newBytes(1, '1'));
359 Object other(&scope, runtime_->newBytes(2, '2'));
360 Object sum(&scope, runBuiltin(METH(bytes, __add__), self, other));
361 EXPECT_TRUE(isBytesEqualsCStr(sum, "122"));
362}
363
364TEST_F(BytesBuiltinsTest, DunderEqWithTooFewArgsRaisesTypeError) {
365 EXPECT_TRUE(raisedWithStr(
366 runFromCStr(runtime_, "bytes.__eq__(b'')"), LayoutId::kTypeError,
367 "'bytes.__eq__' takes min 2 positional arguments but 1 given"));
368}
369
370TEST_F(BytesBuiltinsTest, DunderEqWithTooManyArgsRaisesTypeError) {
371 EXPECT_TRUE(raisedWithStr(
372 runFromCStr(runtime_, "bytes.__eq__(b'', b'', b'')"),
373 LayoutId::kTypeError,
374 "'bytes.__eq__' takes max 2 positional arguments but 3 given"));
375}
376
377TEST_F(BytesBuiltinsTest, DunderEqWithNonBytesSelfRaisesTypeError) {
378 HandleScope scope(thread_);
379 Object self(&scope, SmallInt::fromWord(0));
380 Object other(&scope, runtime_->newBytes(1, 'a'));
381 Object eq(&scope, runBuiltin(METH(bytes, __eq__), self, other));
382 EXPECT_TRUE(raised(*eq, LayoutId::kTypeError));
383}
384
385TEST_F(BytesBuiltinsTest, DunderEqWithNonBytesOtherReturnsNotImplemented) {
386 HandleScope scope(thread_);
387 Object self(&scope, runtime_->newBytes(1, 'a'));
388 Object other(&scope, SmallInt::fromWord(0));
389 Object eq(&scope, runBuiltin(METH(bytes, __eq__), self, other));
390 EXPECT_TRUE(eq.isNotImplementedType());
391}
392
393TEST_F(BytesBuiltinsTest, DunderEqWithBytesSubclassComparesBytes) {
394 ASSERT_FALSE(runFromCStr(runtime_, R"(
395class Foo(bytes): pass
396self = Foo(b'123')
397other = Foo(b'123')
398)")
399 .isError());
400 HandleScope scope(thread_);
401 Object self(&scope, mainModuleAt(runtime_, "self"));
402 Object other(&scope, mainModuleAt(runtime_, "other"));
403 Object eq(&scope, runBuiltin(METH(bytes, __eq__), self, other));
404 EXPECT_EQ(eq, Bool::trueObj());
405}
406
407TEST_F(BytesBuiltinsTest, DunderEqWithEqualBytesReturnsTrue) {
408 HandleScope scope(thread_);
409 Object self(&scope, runtime_->newBytes(5, 'a'));
410 Object other(&scope, runtime_->newBytes(5, 'a'));
411 Object eq(&scope, runBuiltin(METH(bytes, __eq__), self, other));
412 ASSERT_TRUE(eq.isBool());
413 EXPECT_TRUE(Bool::cast(*eq).value());
414}
415
416TEST_F(BytesBuiltinsTest, DunderEqWithDifferentLengthsReturnsFalse) {
417 HandleScope scope(thread_);
418 Object self(&scope, runtime_->newBytes(1, 'a'));
419 Object other(&scope, runtime_->newBytes(4, 'a'));
420 Object eq(&scope, runBuiltin(METH(bytes, __eq__), self, other));
421 ASSERT_TRUE(eq.isBool());
422 EXPECT_FALSE(Bool::cast(*eq).value());
423}
424
425TEST_F(BytesBuiltinsTest, DunderEqWithDifferentContentsReturnsFalse) {
426 HandleScope scope(thread_);
427 Object self(&scope, runtime_->newBytes(3, 'a'));
428 Object other(&scope, runtime_->newBytes(3, 'b'));
429 Object eq(&scope, runBuiltin(METH(bytes, __eq__), self, other));
430 ASSERT_TRUE(eq.isBool());
431 EXPECT_FALSE(Bool::cast(*eq).value());
432}
433
434TEST_F(BytesBuiltinsTest, DunderGeWithTooFewArgsRaisesTypeError) {
435 EXPECT_TRUE(raisedWithStr(
436 runFromCStr(runtime_, "bytes.__ge__(b'')"), LayoutId::kTypeError,
437 "'bytes.__ge__' takes min 2 positional arguments but 1 given"));
438}
439
440TEST_F(BytesBuiltinsTest, DunderGeWithTooManyArgsRaisesTypeError) {
441 EXPECT_TRUE(raisedWithStr(
442 runFromCStr(runtime_, "bytes.__ge__(b'', b'', b'')"),
443 LayoutId::kTypeError,
444 "'bytes.__ge__' takes max 2 positional arguments but 3 given"));
445}
446
447TEST_F(BytesBuiltinsTest, DunderGeWithNonBytesSelfRaisesTypeError) {
448 HandleScope scope(thread_);
449 Object self(&scope, SmallInt::fromWord(0));
450 Object other(&scope, runtime_->newBytes(1, 'a'));
451 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
452 EXPECT_TRUE(raised(*ge, LayoutId::kTypeError));
453}
454
455TEST_F(BytesBuiltinsTest, DunderGeWithNonBytesOtherReturnsNotImplemented) {
456 HandleScope scope(thread_);
457 Object self(&scope, runtime_->newBytes(1, 'a'));
458 Object other(&scope, SmallInt::fromWord(0));
459 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
460 ASSERT_TRUE(ge.isNotImplementedType());
461}
462
463TEST_F(BytesBuiltinsTest, DunderGeWithBytesSubclassComparesBytes) {
464 ASSERT_FALSE(runFromCStr(runtime_, R"(
465class Foo(bytes): pass
466self = Foo(b'123')
467other = Foo(b'123')
468)")
469 .isError());
470 HandleScope scope(thread_);
471 Object self(&scope, mainModuleAt(runtime_, "self"));
472 Object other(&scope, mainModuleAt(runtime_, "other"));
473 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
474 EXPECT_EQ(ge, Bool::trueObj());
475}
476
477TEST_F(BytesBuiltinsTest, DunderGeWithEqualBytesReturnsTrue) {
478 HandleScope scope(thread_);
479 Object self(&scope, runtime_->newBytes(5, 'a'));
480 Object other(&scope, runtime_->newBytes(5, 'a'));
481 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
482 ASSERT_TRUE(ge.isBool());
483 EXPECT_TRUE(Bool::cast(*ge).value());
484}
485
486TEST_F(BytesBuiltinsTest, DunderGeWithShorterOtherReturnsTrue) {
487 HandleScope scope(thread_);
488 Object self(&scope, runtime_->newBytes(3, 'a'));
489 Object other(&scope, runtime_->newBytes(2, 'a'));
490 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
491 ASSERT_TRUE(ge.isBool());
492 EXPECT_TRUE(Bool::cast(*ge).value());
493}
494
495TEST_F(BytesBuiltinsTest, DunderGeWithLongerOtherReturnsFalse) {
496 HandleScope scope(thread_);
497 Object self(&scope, runtime_->newBytes(3, 'a'));
498 Object other(&scope, runtime_->newBytes(4, 'a'));
499 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
500 ASSERT_TRUE(ge.isBool());
501 EXPECT_FALSE(Bool::cast(*ge).value());
502}
503
504TEST_F(BytesBuiltinsTest,
505 DunderGeWithLexicographicallyEarlierOtherReturnsTrue) {
506 HandleScope scope(thread_);
507 Object self(&scope, runtime_->newBytes(3, 'b'));
508 Object other(&scope, runtime_->newBytes(3, 'a'));
509 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
510 ASSERT_TRUE(ge.isBool());
511 EXPECT_TRUE(Bool::cast(*ge).value());
512}
513
514TEST_F(BytesBuiltinsTest, DunderGeWithLexicographicallyLaterOtherReturnsFalse) {
515 HandleScope scope(thread_);
516 Object self(&scope, runtime_->newBytes(3, 'a'));
517 Object other(&scope, runtime_->newBytes(3, 'b'));
518 Object ge(&scope, runBuiltin(METH(bytes, __ge__), self, other));
519 ASSERT_TRUE(ge.isBool());
520 EXPECT_FALSE(Bool::cast(*ge).value());
521}
522
523TEST_F(BytesBuiltinsTest, DunderGetitemWithTooFewArgsRaisesTypeError) {
524 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes.__getitem__(b'')"),
525 LayoutId::kTypeError,
526 "'bytes.__getitem__' takes min 2 positional "
527 "arguments but 1 given"));
528}
529
530TEST_F(BytesBuiltinsTest, DunderGetitemWithTooManyArgsRaisesTypeError) {
531 EXPECT_TRUE(
532 raisedWithStr(runFromCStr(runtime_, "bytes.__getitem__(b'', b'', b'')"),
533 LayoutId::kTypeError,
534 "'bytes.__getitem__' takes max 2 positional "
535 "arguments but 3 given"));
536}
537
538TEST_F(BytesBuiltinsTest, DunderGetitemWithLargeIntRaisesIndexError) {
539 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b''[2**64]"),
540 LayoutId::kIndexError,
541 "cannot fit 'int' into an index-sized integer"));
542}
543
544TEST_F(BytesBuiltinsTest,
545 DunderGetitemWithIntGreaterOrEqualLenRaisesIndexError) {
546 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b'abc'[3]"),
547 LayoutId::kIndexError, "index out of range"));
548}
549
550TEST_F(BytesBuiltinsTest,
551 DunderGetitemWithNegativeIntGreaterThanLenRaisesIndexError) {
552 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b'abc'[-4]"),
553 LayoutId::kIndexError, "index out of range"));
554}
555
556TEST_F(BytesBuiltinsTest, DunderGetitemWithNegativeIntIndexesFromEnd) {
557 HandleScope scope(thread_);
558 ASSERT_FALSE(runFromCStr(runtime_, "result = b'hello'[-5]").isError());
559 Object result(&scope, mainModuleAt(runtime_, "result"));
560 EXPECT_TRUE(isIntEqualsWord(*result, 'h'));
561}
562
563TEST_F(BytesBuiltinsTest, DunderGetitemIndexesFromBeginning) {
564 HandleScope scope(thread_);
565 ASSERT_FALSE(runFromCStr(runtime_, "result = b'hello'[0]").isError());
566 Object result(&scope, mainModuleAt(runtime_, "result"));
567 EXPECT_TRUE(isIntEqualsWord(*result, 'h'));
568}
569
570TEST_F(BytesBuiltinsTest, DunderGetitemWithSliceReturnsBytes) {
571 HandleScope scope(thread_);
572 ASSERT_FALSE(runFromCStr(runtime_, "result = b'hello world'[:3]").isError());
573 Object result(&scope, mainModuleAt(runtime_, "result"));
574 EXPECT_TRUE(isBytesEqualsCStr(result, "hel"));
575}
576
577TEST_F(BytesBuiltinsTest, DunderGetitemWithSliceStepReturnsBytes) {
578 HandleScope scope(thread_);
579 ASSERT_FALSE(
580 runFromCStr(runtime_, "result = b'hello world'[1:6:2]").isError());
581 Object result(&scope, mainModuleAt(runtime_, "result"));
582 EXPECT_TRUE(isBytesEqualsCStr(result, "el "));
583}
584
585TEST_F(BytesBuiltinsTest, DunderGetitemWithNonIndexOtherRaisesTypeError) {
586 EXPECT_TRUE(
587 raisedWithStr(runFromCStr(runtime_, "b''[1.5]"), LayoutId::kTypeError,
588 "byte indices must be integers or slice, not float"));
589}
590
591TEST_F(BytesBuiltinsTest, DunderGtWithTooFewArgsRaisesTypeError) {
592 EXPECT_TRUE(raisedWithStr(
593 runFromCStr(runtime_, "bytes.__gt__(b'')"), LayoutId::kTypeError,
594 "'bytes.__gt__' takes min 2 positional arguments but 1 given"));
595}
596
597TEST_F(BytesBuiltinsTest, DunderGtWithTooManyArgsRaisesTypeError) {
598 EXPECT_TRUE(raisedWithStr(
599 runFromCStr(runtime_, "bytes.__gt__(b'', b'', b'')"),
600 LayoutId::kTypeError,
601 "'bytes.__gt__' takes max 2 positional arguments but 3 given"));
602}
603
604TEST_F(BytesBuiltinsTest, DunderGtWithNonBytesSelfRaisesTypeError) {
605 HandleScope scope(thread_);
606 Object self(&scope, SmallInt::fromWord(0));
607 Object other(&scope, runtime_->newBytes(1, 'a'));
608 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
609 EXPECT_TRUE(raised(*gt, LayoutId::kTypeError));
610}
611
612TEST_F(BytesBuiltinsTest, DunderGtWithNonBytesOtherReturnsNotImplemented) {
613 HandleScope scope(thread_);
614 Object self(&scope, runtime_->newBytes(1, 'a'));
615 Object other(&scope, SmallInt::fromWord(0));
616 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
617 ASSERT_TRUE(gt.isNotImplementedType());
618}
619
620TEST_F(BytesBuiltinsTest, DunderGtWithBytesSubclassComparesBytes) {
621 ASSERT_FALSE(runFromCStr(runtime_, R"(
622class Foo(bytes): pass
623self = Foo(b'123')
624other = Foo(b'123')
625)")
626 .isError());
627 HandleScope scope(thread_);
628 Object self(&scope, mainModuleAt(runtime_, "self"));
629 Object other(&scope, mainModuleAt(runtime_, "other"));
630 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
631 EXPECT_EQ(gt, Bool::falseObj());
632}
633
634TEST_F(BytesBuiltinsTest, DunderGtWithEqualBytesReturnsFalse) {
635 HandleScope scope(thread_);
636 Object self(&scope, runtime_->newBytes(5, 'a'));
637 Object other(&scope, runtime_->newBytes(5, 'a'));
638 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
639 ASSERT_TRUE(gt.isBool());
640 EXPECT_FALSE(Bool::cast(*gt).value());
641}
642
643TEST_F(BytesBuiltinsTest, DunderGtWithShorterOtherReturnsTrue) {
644 HandleScope scope(thread_);
645 Object self(&scope, runtime_->newBytes(3, 'a'));
646 Object other(&scope, runtime_->newBytes(2, 'a'));
647 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
648 ASSERT_TRUE(gt.isBool());
649 EXPECT_TRUE(Bool::cast(*gt).value());
650}
651
652TEST_F(BytesBuiltinsTest, DunderGtWithLongerOtherReturnsFalse) {
653 HandleScope scope(thread_);
654 Object self(&scope, runtime_->newBytes(3, 'a'));
655 Object other(&scope, runtime_->newBytes(4, 'a'));
656 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
657 ASSERT_TRUE(gt.isBool());
658 EXPECT_FALSE(Bool::cast(*gt).value());
659}
660
661TEST_F(BytesBuiltinsTest,
662 DunderGtWithLexicographicallyEarlierOtherReturnsTrue) {
663 HandleScope scope(thread_);
664 Object self(&scope, runtime_->newBytes(3, 'b'));
665 Object other(&scope, runtime_->newBytes(3, 'a'));
666 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
667 ASSERT_TRUE(gt.isBool());
668 EXPECT_TRUE(Bool::cast(*gt).value());
669}
670
671TEST_F(BytesBuiltinsTest, DunderGtWithLexicographicallyLaterOtherReturnsFalse) {
672 HandleScope scope(thread_);
673 Object self(&scope, runtime_->newBytes(3, 'a'));
674 Object other(&scope, runtime_->newBytes(3, 'b'));
675 Object gt(&scope, runBuiltin(METH(bytes, __gt__), self, other));
676 ASSERT_TRUE(gt.isBool());
677 EXPECT_FALSE(Bool::cast(*gt).value());
678}
679
680TEST_F(BytesBuiltinsTest, DunderHashReturnsSmallInt) {
681 Thread* thread = Thread::current();
682 HandleScope scope(thread);
683 const byte bytes[] = {'h', 'e', 'l', 'l', 'o', '\0'};
684 Bytes bytes_obj(&scope, runtime_->newBytesWithAll(bytes));
685 EXPECT_TRUE(runBuiltin(METH(bytes, __hash__), bytes_obj).isSmallInt());
686}
687
688TEST_F(BytesBuiltinsTest, DunderHashSmallBytesReturnsSmallInt) {
689 Thread* thread = Thread::current();
690 HandleScope scope(thread);
691 const byte bytes[] = {'h'};
692 Bytes bytes_obj(&scope, runtime_->newBytesWithAll(bytes));
693 EXPECT_TRUE(runBuiltin(METH(bytes, __hash__), bytes_obj).isSmallInt());
694}
695
696TEST_F(BytesBuiltinsTest, DunderHashWithEquivalentBytesReturnsSameHash) {
697 Thread* thread = Thread::current();
698 HandleScope scope(thread);
699 const byte bytes[] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '\0'};
700 Bytes bytes_obj1(&scope, runtime_->newBytesWithAll(bytes));
701 Bytes bytes_obj2(&scope, runtime_->newBytesWithAll(bytes));
702 EXPECT_NE(*bytes_obj1, *bytes_obj2);
703 Object result1(&scope, runBuiltin(METH(bytes, __hash__), bytes_obj1));
704 Object result2(&scope, runBuiltin(METH(bytes, __hash__), bytes_obj2));
705 EXPECT_TRUE(result1.isSmallInt());
706 EXPECT_TRUE(result2.isSmallInt());
707 EXPECT_EQ(*result1, *result2);
708}
709
710TEST_F(BytesBuiltinsTest, DunderHashWithBytesSubclassReturnsSameHash) {
711 HandleScope scope(thread_);
712 ASSERT_FALSE(runFromCStr(runtime_, R"(
713class C(bytes): pass
714i0 = C(b"abc")
715i1 = b"abc"
716)")
717 .isError());
718 Object i0(&scope, mainModuleAt(runtime_, "i0"));
719 Object i1(&scope, mainModuleAt(runtime_, "i1"));
720
721 Object result0(&scope, runBuiltin(METH(bytes, __hash__), i0));
722 Object result1(&scope, runBuiltin(METH(bytes, __hash__), i1));
723 EXPECT_TRUE(result0.isSmallInt());
724 EXPECT_TRUE(result1.isSmallInt());
725 EXPECT_EQ(result0, result1);
726}
727
728TEST_F(BytesBuiltinsTest, DunderIterReturnsBytesIterator) {
729 HandleScope scope(thread_);
730 Object self(&scope, Bytes::empty());
731 Object result(&scope, runBuiltin(METH(bytes, __iter__), self));
732 EXPECT_TRUE(result.isBytesIterator());
733}
734
735TEST_F(BytesBuiltinsTest, DunderLeWithTooFewArgsRaisesTypeError) {
736 EXPECT_TRUE(raisedWithStr(
737 runFromCStr(runtime_, "bytes.__le__(b'')"), LayoutId::kTypeError,
738 "'bytes.__le__' takes min 2 positional arguments but 1 given"));
739}
740
741TEST_F(BytesBuiltinsTest, DunderLeWithTooManyArgsRaisesTypeError) {
742 EXPECT_TRUE(raisedWithStr(
743 runFromCStr(runtime_, "bytes.__le__(b'', b'', b'')"),
744 LayoutId::kTypeError,
745 "'bytes.__le__' takes max 2 positional arguments but 3 given"));
746}
747
748TEST_F(BytesBuiltinsTest, DunderLeWithNonBytesSelfRaisesTypeError) {
749 HandleScope scope(thread_);
750 Object self(&scope, SmallInt::fromWord(0));
751 Object other(&scope, runtime_->newBytes(1, 'a'));
752 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
753 EXPECT_TRUE(raised(*le, LayoutId::kTypeError));
754}
755
756TEST_F(BytesBuiltinsTest, DunderLeWithNonBytesOtherReturnsNotImplemented) {
757 HandleScope scope(thread_);
758 Object self(&scope, runtime_->newBytes(1, 'a'));
759 Object other(&scope, SmallInt::fromWord(0));
760 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
761 ASSERT_TRUE(le.isNotImplementedType());
762}
763
764TEST_F(BytesBuiltinsTest, DunderLeWithBytesSubclassComparesBytes) {
765 ASSERT_FALSE(runFromCStr(runtime_, R"(
766class Foo(bytes): pass
767self = Foo(b'123')
768other = Foo(b'123')
769)")
770 .isError());
771 HandleScope scope(thread_);
772 Object self(&scope, mainModuleAt(runtime_, "self"));
773 Object other(&scope, mainModuleAt(runtime_, "other"));
774 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
775 EXPECT_EQ(le, Bool::trueObj());
776}
777
778TEST_F(BytesBuiltinsTest, DunderLeWithEqualBytesReturnsTrue) {
779 HandleScope scope(thread_);
780 Object self(&scope, runtime_->newBytes(5, 'a'));
781 Object other(&scope, runtime_->newBytes(5, 'a'));
782 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
783 ASSERT_TRUE(le.isBool());
784 EXPECT_TRUE(Bool::cast(*le).value());
785}
786
787TEST_F(BytesBuiltinsTest, DunderLeWithShorterOtherReturnsFalse) {
788 HandleScope scope(thread_);
789 Object self(&scope, runtime_->newBytes(3, 'a'));
790 Object other(&scope, runtime_->newBytes(2, 'a'));
791 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
792 ASSERT_TRUE(le.isBool());
793 EXPECT_FALSE(Bool::cast(*le).value());
794}
795
796TEST_F(BytesBuiltinsTest, DunderLeWithLongerOtherReturnsTrue) {
797 HandleScope scope(thread_);
798 Object self(&scope, runtime_->newBytes(3, 'a'));
799 Object other(&scope, runtime_->newBytes(4, 'a'));
800 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
801 ASSERT_TRUE(le.isBool());
802 EXPECT_TRUE(Bool::cast(*le).value());
803}
804
805TEST_F(BytesBuiltinsTest,
806 DunderLeWithLexicographicallyEarlierOtherReturnsFalse) {
807 HandleScope scope(thread_);
808 Object self(&scope, runtime_->newBytes(3, 'b'));
809 Object other(&scope, runtime_->newBytes(3, 'a'));
810 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
811 ASSERT_TRUE(le.isBool());
812 EXPECT_FALSE(Bool::cast(*le).value());
813}
814
815TEST_F(BytesBuiltinsTest, DunderLeWithLexicographicallyLaterOtherReturnsTrue) {
816 HandleScope scope(thread_);
817 Object self(&scope, runtime_->newBytes(3, 'a'));
818 Object other(&scope, runtime_->newBytes(3, 'b'));
819 Object le(&scope, runBuiltin(METH(bytes, __le__), self, other));
820 ASSERT_TRUE(le.isBool());
821 EXPECT_TRUE(Bool::cast(*le).value());
822}
823
824TEST_F(BytesBuiltinsTest, DunderLenWithTooFewArgsRaisesTypeError) {
825 EXPECT_TRUE(raisedWithStr(
826 runFromCStr(runtime_, "bytes.__len__()"), LayoutId::kTypeError,
827 "'bytes.__len__' takes min 1 positional arguments but 0 given"));
828}
829
830TEST_F(BytesBuiltinsTest, DunderLenWithTooManyArgsRaisesTypeError) {
831 EXPECT_TRUE(raisedWithStr(
832 runFromCStr(runtime_, "bytes.__len__(b'', b'')"), LayoutId::kTypeError,
833 "'bytes.__len__' takes max 1 positional arguments but 2 given"));
834}
835
836TEST_F(BytesBuiltinsTest, DunderLenWithNonBytesSelfRaisesTypeError) {
837 HandleScope scope(thread_);
838 Object self(&scope, SmallInt::fromWord(0));
839 Object len(&scope, runBuiltin(METH(bytes, __len__), self));
840 EXPECT_TRUE(raised(*len, LayoutId::kTypeError));
841}
842
843TEST_F(BytesBuiltinsTest, DunderLenWithEmptyBytesReturnsZero) {
844 HandleScope scope(thread_);
845 Object self(&scope, runtime_->newBytesWithAll(View<byte>(nullptr, 0)));
846 Object len(&scope, runBuiltin(METH(bytes, __len__), self));
847 EXPECT_EQ(len, SmallInt::fromWord(0));
848}
849
850TEST_F(BytesBuiltinsTest, DunderLenWithNonEmptyBytesReturnsLength) {
851 HandleScope scope(thread_);
852 Object self(&scope, runtime_->newBytes(4, 'a'));
853 Object len(&scope, runBuiltin(METH(bytes, __len__), self));
854 EXPECT_EQ(len, SmallInt::fromWord(4));
855}
856
857TEST_F(BytesBuiltinsTest, DunderLenWithBytesSubclassReturnsLength) {
858 ASSERT_FALSE(runFromCStr(runtime_, R"(
859class Foo(bytes): pass
860self = Foo(b"1234567890")
861 )")
862 .isError());
863 HandleScope scope(thread_);
864 Object self(&scope, mainModuleAt(runtime_, "self"));
865 Object len(&scope, runBuiltin(METH(bytes, __len__), self));
866 EXPECT_EQ(len, SmallInt::fromWord(10));
867}
868
869TEST_F(BytesBuiltinsTest, DunderLtWithTooFewArgsRaisesTypeError) {
870 EXPECT_TRUE(raisedWithStr(
871 runFromCStr(runtime_, "bytes.__lt__(b'')"), LayoutId::kTypeError,
872 "'bytes.__lt__' takes min 2 positional arguments but 1 given"));
873}
874
875TEST_F(BytesBuiltinsTest, DunderLtWithTooManyArgsRaisesTypeError) {
876 EXPECT_TRUE(raisedWithStr(
877 runFromCStr(runtime_, "bytes.__lt__(b'', b'', b'')"),
878 LayoutId::kTypeError,
879 "'bytes.__lt__' takes max 2 positional arguments but 3 given"));
880}
881
882TEST_F(BytesBuiltinsTest, DunderLtWithNonBytesSelfRaisesTypeError) {
883 HandleScope scope(thread_);
884 Object self(&scope, SmallInt::fromWord(0));
885 Object other(&scope, runtime_->newBytes(1, 'a'));
886 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
887 EXPECT_TRUE(raised(*lt, LayoutId::kTypeError));
888}
889
890TEST_F(BytesBuiltinsTest, DunderLtWithNonBytesOtherReturnsNotImplemented) {
891 HandleScope scope(thread_);
892 Object self(&scope, runtime_->newBytes(1, 'a'));
893 Object other(&scope, SmallInt::fromWord(0));
894 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
895 ASSERT_TRUE(lt.isNotImplementedType());
896}
897
898TEST_F(BytesBuiltinsTest, DunderLtWithBytesSubclassComparesBytes) {
899 ASSERT_FALSE(runFromCStr(runtime_, R"(
900class Foo(bytes): pass
901self = Foo(b'123')
902other = Foo(b'123')
903)")
904 .isError());
905 HandleScope scope(thread_);
906 Object self(&scope, mainModuleAt(runtime_, "self"));
907 Object other(&scope, mainModuleAt(runtime_, "other"));
908 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
909 EXPECT_EQ(lt, Bool::falseObj());
910}
911
912TEST_F(BytesBuiltinsTest, DunderLtWithEqualBytesReturnsFalse) {
913 HandleScope scope(thread_);
914 Object self(&scope, runtime_->newBytes(5, 'a'));
915 Object other(&scope, runtime_->newBytes(5, 'a'));
916 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
917 ASSERT_TRUE(lt.isBool());
918 EXPECT_FALSE(Bool::cast(*lt).value());
919}
920
921TEST_F(BytesBuiltinsTest, DunderLtWithShorterOtherReturnsFalse) {
922 HandleScope scope(thread_);
923 Object self(&scope, runtime_->newBytes(3, 'a'));
924 Object other(&scope, runtime_->newBytes(2, 'a'));
925 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
926 ASSERT_TRUE(lt.isBool());
927 EXPECT_FALSE(Bool::cast(*lt).value());
928}
929
930TEST_F(BytesBuiltinsTest, DunderLtWithLongerOtherReturnsTrue) {
931 HandleScope scope(thread_);
932 Object self(&scope, runtime_->newBytes(3, 'a'));
933 Object other(&scope, runtime_->newBytes(4, 'a'));
934 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
935 ASSERT_TRUE(lt.isBool());
936 EXPECT_TRUE(Bool::cast(*lt).value());
937}
938
939TEST_F(BytesBuiltinsTest,
940 DunderLtWithLexicographicallyEarlierOtherReturnsFalse) {
941 HandleScope scope(thread_);
942 Object self(&scope, runtime_->newBytes(3, 'b'));
943 Object other(&scope, runtime_->newBytes(3, 'a'));
944 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
945 ASSERT_TRUE(lt.isBool());
946 EXPECT_FALSE(Bool::cast(*lt).value());
947}
948
949TEST_F(BytesBuiltinsTest, DunderLtWithLexicographicallyLaterOtherReturnsTrue) {
950 HandleScope scope(thread_);
951 Object self(&scope, runtime_->newBytes(3, 'a'));
952 Object other(&scope, runtime_->newBytes(3, 'b'));
953 Object lt(&scope, runBuiltin(METH(bytes, __lt__), self, other));
954 ASSERT_TRUE(lt.isBool());
955 EXPECT_TRUE(Bool::cast(*lt).value());
956}
957
958TEST_F(BytesBuiltinsTest, DunderMulWithNonIntRaisesTypeError) {
959 HandleScope scope(thread_);
960 Object self(&scope, Bytes::empty());
961 Object count(&scope, runtime_->newList());
962 EXPECT_TRUE(raisedWithStr(
963 runBuiltin(METH(bytes, __mul__), self, count), LayoutId::kTypeError,
964 "'list' object cannot be interpreted as an integer"));
965}
966
967TEST_F(BytesBuiltinsTest, DunderMulWithIntSubclassReturnsRepeatedBytes) {
968 HandleScope scope(thread_);
969 const byte view[] = {'a', 'b', 'c'};
970 Object self(&scope, runtime_->newBytesWithAll(view));
971 ASSERT_FALSE(runFromCStr(runtime_, R"(
972class C(int): pass
973count = C(4)
974)")
975 .isError());
976 Object count(&scope, mainModuleAt(runtime_, "count"));
977 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
978 EXPECT_TRUE(isBytesEqualsCStr(result, "abcabcabcabc"));
979}
980
981TEST_F(BytesBuiltinsTest, DunderMulWithDunderIndexReturnsRepeatedBytes) {
982 HandleScope scope(thread_);
983 Object self(&scope, runtime_->newBytes(1, 'a'));
984 ASSERT_FALSE(runFromCStr(runtime_, R"(
985class C:
986 def __index__(self):
987 return 2
988count = C()
989)")
990 .isError());
991 Object count(&scope, mainModuleAt(runtime_, "count"));
992 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
993 EXPECT_TRUE(isBytesEqualsCStr(result, "aa"));
994}
995
996TEST_F(BytesBuiltinsTest, DunderMulWithBadDunderIndexRaisesTypeError) {
997 HandleScope scope(thread_);
998 Object self(&scope, runtime_->newBytes(1, 'a'));
999 ASSERT_FALSE(runFromCStr(runtime_, R"(
1000class C:
1001 def __index__(self):
1002 return "foo"
1003count = C()
1004)")
1005 .isError());
1006 Object count(&scope, mainModuleAt(runtime_, "count"));
1007 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytes, __mul__), self, count),
1008 LayoutId::kTypeError,
1009 "__index__ returned non-int (type str)"));
1010}
1011
1012TEST_F(BytesBuiltinsTest, DunderMulPropagatesDunderIndexError) {
1013 HandleScope scope(thread_);
1014 Object self(&scope, runtime_->newBytes(1, 'a'));
1015 ASSERT_FALSE(runFromCStr(runtime_, R"(
1016class C:
1017 def __index__(self):
1018 raise ArithmeticError("called __index__")
1019count = C()
1020)")
1021 .isError());
1022 Object count(&scope, mainModuleAt(runtime_, "count"));
1023 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytes, __mul__), self, count),
1024 LayoutId::kArithmeticError, "called __index__"));
1025}
1026
1027TEST_F(BytesBuiltinsTest, DunderMulWithLargeIntRaisesOverflowError) {
1028 HandleScope scope(thread_);
1029 Object self(&scope, Bytes::empty());
1030 const uword digits[] = {1, 1};
1031 Object count(&scope, runtime_->newLargeIntWithDigits(digits));
1032 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytes, __mul__), self, count),
1033 LayoutId::kOverflowError,
1034 "cannot fit 'int' into an index-sized integer"));
1035}
1036
1037TEST_F(BytesBuiltinsTest, DunderMulWithOverflowRaisesOverflowError) {
1038 HandleScope scope(thread_);
1039 Object self(&scope, runtime_->newBytes(3, 'a'));
1040 Object count(&scope, SmallInt::fromWord(SmallInt::kMaxValue / 2));
1041 EXPECT_TRUE(raisedWithStr(runBuiltin(METH(bytes, __mul__), self, count),
1042 LayoutId::kOverflowError,
1043 "repeated bytes are too long"));
1044}
1045
1046TEST_F(BytesBuiltinsTest, DunderMulWithEmptyBytesReturnsEmptyBytes) {
1047 HandleScope scope(thread_);
1048 Object self(&scope, Bytes::empty());
1049 Object count(&scope, runtime_->newInt(10));
1050 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
1051 EXPECT_TRUE(isBytesEqualsCStr(result, ""));
1052}
1053
1054TEST_F(BytesBuiltinsTest, DunderMulWithNegativeReturnsEmptyBytes) {
1055 HandleScope scope(thread_);
1056 Object self(&scope, runtime_->newBytes(4, 'a'));
1057 Object count(&scope, SmallInt::fromWord(-5));
1058 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
1059 EXPECT_TRUE(isBytesEqualsCStr(result, ""));
1060}
1061
1062TEST_F(BytesBuiltinsTest, DunderMulWithZeroReturnsEmptyBytes) {
1063 HandleScope scope(thread_);
1064 Object self(&scope, runtime_->newBytes(4, 'a'));
1065 Object count(&scope, SmallInt::fromWord(0));
1066 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
1067 EXPECT_TRUE(isBytesEqualsCStr(result, ""));
1068}
1069
1070TEST_F(BytesBuiltinsTest, DunderMulWithOneReturnsSameBytes) {
1071 HandleScope scope(thread_);
1072 const byte bytes_array[] = {'a', 'b'};
1073 Object self(&scope, runtime_->newBytesWithAll(bytes_array));
1074 Object count(&scope, SmallInt::fromWord(1));
1075 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
1076 EXPECT_TRUE(isBytesEqualsCStr(result, "ab"));
1077}
1078
1079TEST_F(BytesBuiltinsTest, DunderMulReturnsRepeatedBytes) {
1080 HandleScope scope(thread_);
1081 const byte bytes_array[] = {'a', 'b'};
1082 Object self(&scope, runtime_->newBytesWithAll(bytes_array));
1083 Object count(&scope, SmallInt::fromWord(3));
1084 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
1085 EXPECT_TRUE(isBytesEqualsCStr(result, "ababab"));
1086}
1087
1088TEST_F(BytesBuiltinsTest, DunderMulWithBytesSubclassReturnsRepeatedBytes) {
1089 ASSERT_FALSE(runFromCStr(runtime_, R"(
1090class Foo(bytes): pass
1091self = Foo(b"ab")
1092)")
1093 .isError());
1094 HandleScope scope(thread_);
1095 Object self(&scope, mainModuleAt(runtime_, "self"));
1096 Object count(&scope, SmallInt::fromWord(3));
1097 Object result(&scope, runBuiltin(METH(bytes, __mul__), self, count));
1098 EXPECT_TRUE(isBytesEqualsCStr(result, "ababab"));
1099}
1100
1101TEST_F(BytesBuiltinsTest, DunderNeWithTooFewArgsRaisesTypeError) {
1102 EXPECT_TRUE(raisedWithStr(
1103 runFromCStr(runtime_, "bytes.__ne__(b'')"), LayoutId::kTypeError,
1104 "'bytes.__ne__' takes min 2 positional arguments but 1 given"));
1105}
1106
1107TEST_F(BytesBuiltinsTest, DunderNeWithTooManyArgsRaisesTypeError) {
1108 EXPECT_TRUE(raisedWithStr(
1109 runFromCStr(runtime_, "bytes.__ne__(b'', b'', b'')"),
1110 LayoutId::kTypeError,
1111 "'bytes.__ne__' takes max 2 positional arguments but 3 given"));
1112}
1113
1114TEST_F(BytesBuiltinsTest, DunderNeWithNonBytesSelfRaisesTypeError) {
1115 HandleScope scope(thread_);
1116 Object self(&scope, SmallInt::fromWord(0));
1117 Object other(&scope, runtime_->newBytes(1, 'a'));
1118 Object ne(&scope, runBuiltin(METH(bytes, __ne__), self, other));
1119 EXPECT_TRUE(raised(*ne, LayoutId::kTypeError));
1120}
1121
1122TEST_F(BytesBuiltinsTest, DunderNeWithNonBytesOtherReturnsNotImplemented) {
1123 HandleScope scope(thread_);
1124 Object self(&scope, runtime_->newBytes(1, 'a'));
1125 Object other(&scope, SmallInt::fromWord(0));
1126 Object ne(&scope, runBuiltin(METH(bytes, __ne__), self, other));
1127 EXPECT_TRUE(ne.isNotImplementedType());
1128}
1129
1130TEST_F(BytesBuiltinsTest, DunderNeWithBytesSubclassComparesBytes) {
1131 ASSERT_FALSE(runFromCStr(runtime_, R"(
1132class Foo(bytes): pass
1133self = Foo(b'123')
1134other = Foo(b'123')
1135)")
1136 .isError());
1137 HandleScope scope(thread_);
1138 Object self(&scope, mainModuleAt(runtime_, "self"));
1139 Object other(&scope, mainModuleAt(runtime_, "other"));
1140 Object ne(&scope, runBuiltin(METH(bytes, __ne__), self, other));
1141 EXPECT_EQ(ne, Bool::falseObj());
1142}
1143
1144TEST_F(BytesBuiltinsTest, DunderNeWithEqualBytesReturnsFalse) {
1145 HandleScope scope(thread_);
1146 Object self(&scope, runtime_->newBytes(5, 'a'));
1147 Object other(&scope, runtime_->newBytes(5, 'a'));
1148 Object ne(&scope, runBuiltin(METH(bytes, __ne__), self, other));
1149 ASSERT_TRUE(ne.isBool());
1150 EXPECT_FALSE(Bool::cast(*ne).value());
1151}
1152
1153TEST_F(BytesBuiltinsTest, DunderNeWithDifferentLengthsReturnsTrue) {
1154 HandleScope scope(thread_);
1155 Object self(&scope, runtime_->newBytes(1, 'a'));
1156 Object other(&scope, runtime_->newBytes(4, 'a'));
1157 Object ne(&scope, runBuiltin(METH(bytes, __ne__), self, other));
1158 ASSERT_TRUE(ne.isBool());
1159 EXPECT_TRUE(Bool::cast(*ne).value());
1160}
1161
1162TEST_F(BytesBuiltinsTest, DunderNeWithDifferentContentsReturnsTrue) {
1163 HandleScope scope(thread_);
1164 Object self(&scope, runtime_->newBytes(3, 'a'));
1165 Object other(&scope, runtime_->newBytes(3, 'b'));
1166 Object ne(&scope, runBuiltin(METH(bytes, __ne__), self, other));
1167 ASSERT_TRUE(ne.isBool());
1168 EXPECT_TRUE(Bool::cast(*ne).value());
1169}
1170
1171TEST_F(BytesBuiltinsTest, DunderNewWithoutSourceWithEncodingRaisesTypeError) {
1172 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes(encoding='ascii')"),
1173 LayoutId::kTypeError,
1174 "encoding or errors without sequence argument"));
1175}
1176
1177TEST_F(BytesBuiltinsTest, DunderNewWithoutSourceWithErrorsRaisesTypeError) {
1178 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes(errors='strict')"),
1179 LayoutId::kTypeError,
1180 "encoding or errors without sequence argument"));
1181}
1182
1183TEST_F(BytesBuiltinsTest, DunderNewWithoutArgsReturnsEmptyBytes) {
1184 HandleScope scope(thread_);
1185 ASSERT_FALSE(runFromCStr(runtime_, "obj = bytes()").isError());
1186 Object obj(&scope, mainModuleAt(runtime_, "obj"));
1187 EXPECT_TRUE(isBytesEqualsCStr(obj, ""));
1188}
1189
1190TEST_F(BytesBuiltinsTest,
1191 DunderNewWithNonStringSourceWithEncodingRaisesTypeError) {
1192 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes(1, 'ascii')"),
1193 LayoutId::kTypeError,
1194 "encoding without a string argument"));
1195}
1196
1197TEST_F(BytesBuiltinsTest,
1198 DunderNewWithoutEncodingWithErrorsAndStringSourceRaisesTypeError) {
1199 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes('', errors='strict')"),
1200 LayoutId::kTypeError,
1201 "string argument without an encoding"));
1202}
1203
1204TEST_F(BytesBuiltinsTest,
1205 DunderNewWithoutEncodingWithErrorsAndNonStringSourceRaisesTypeError) {
1206 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes(1, errors='strict')"),
1207 LayoutId::kTypeError,
1208 "errors without a string argument"));
1209}
1210
1211TEST_F(BytesBuiltinsTest, DunderNewWithMistypedDunderBytesRaisesTypeError) {
1212 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1213class Foo:
1214 def __bytes__(self): return 1
1215bytes(Foo())
1216)"),
1217 LayoutId::kTypeError,
1218 "__bytes__ returned non-bytes (type int)"));
1219}
1220
1221TEST_F(BytesBuiltinsTest, DunderNewPropagatesDunderBytesError) {
1222 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"(
1223class Foo:
1224 def __bytes__(self): raise SystemError("foo")
1225bytes(Foo())
1226)"),
1227 LayoutId::kSystemError, "foo"));
1228}
1229
1230TEST_F(BytesBuiltinsTest, DunderNewWithDunderBytesReturnsBytes) {
1231 HandleScope scope(thread_);
1232 ASSERT_FALSE(runFromCStr(runtime_, R"(
1233class Foo:
1234 def __bytes__(self): return b'foo'
1235result = bytes(Foo())
1236)")
1237 .isError());
1238 Object result(&scope, mainModuleAt(runtime_, "result"));
1239 EXPECT_TRUE(isBytesEqualsCStr(result, "foo"));
1240}
1241
1242TEST_F(BytesBuiltinsTest, DunderNewWithNegativeIntegerSourceRaisesValueError) {
1243 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "result = bytes(-1)"),
1244 LayoutId::kValueError, "negative count"));
1245}
1246
1247TEST_F(BytesBuiltinsTest, DunderNewWithLargeIntegerSourceRaisesOverflowError) {
1248 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "result = bytes(2**63)"),
1249 LayoutId::kOverflowError,
1250 "cannot fit 'int' into an index-sized integer"));
1251}
1252
1253TEST_F(BytesBuiltinsTest, DunderNewWithIntegerSourceReturnsZeroFilledBytes) {
1254 HandleScope scope(thread_);
1255 ASSERT_FALSE(runFromCStr(runtime_, "result = bytes(10)").isError());
1256 Object result(&scope, mainModuleAt(runtime_, "result"));
1257 const byte bytes[10] = {};
1258 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
1259}
1260
1261TEST_F(BytesBuiltinsTest, DunderNewWithBytesReturnsSameBytes) {
1262 HandleScope scope(thread_);
1263 ASSERT_FALSE(runFromCStr(runtime_, "result = bytes(b'123')").isError());
1264 Object result(&scope, mainModuleAt(runtime_, "result"));
1265 const byte bytes[] = {'1', '2', '3'};
1266 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
1267}
1268
1269TEST_F(BytesBuiltinsTest, DunderNewWithBytearrayReturnsBytesCopy) {
1270 HandleScope scope(thread_);
1271 ASSERT_FALSE(
1272 runFromCStr(runtime_, "result = bytes(bytearray(b'123'))").isError());
1273 Object result(&scope, mainModuleAt(runtime_, "result"));
1274 const byte bytes[] = {'1', '2', '3'};
1275 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
1276}
1277
1278TEST_F(BytesBuiltinsTest, DunderNewWithListReturnsNewBytes) {
1279 HandleScope scope(thread_);
1280 ASSERT_FALSE(runFromCStr(runtime_, "result = bytes([6, 28])").isError());
1281 Object result(&scope, mainModuleAt(runtime_, "result"));
1282 const byte bytes[] = {6, 28};
1283 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
1284}
1285
1286TEST_F(BytesBuiltinsTest, DunderNewWithTupleReturnsNewBytes) {
1287 HandleScope scope(thread_);
1288 ASSERT_FALSE(runFromCStr(runtime_, "result = bytes((6, 28))").isError());
1289 Object result(&scope, mainModuleAt(runtime_, "result"));
1290 const byte bytes[] = {6, 28};
1291 EXPECT_TRUE(isBytesEqualsBytes(result, bytes));
1292}
1293
1294TEST_F(BytesBuiltinsTest, DunderNewWithNegativeRaisesValueError) {
1295 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "result = bytes([-1])"),
1296 LayoutId::kValueError,
1297 "bytes must be in range(0, 256)"));
1298}
1299
1300TEST_F(BytesBuiltinsTest, DunderNewWithGreaterThanByteRaisesValueError) {
1301 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "result = bytes([256])"),
1302 LayoutId::kValueError,
1303 "bytes must be in range(0, 256)"));
1304}
1305
1306TEST_F(BytesBuiltinsTest, DunderNewWithIterableReturnsNewBytes) {
1307 HandleScope scope(thread_);
1308 ASSERT_FALSE(runFromCStr(runtime_, R"(
1309class Foo:
1310 def __iter__(self):
1311 return [1, 2, 3].__iter__()
1312result = bytes(Foo())
1313)")
1314 .isError());
1315 Object result(&scope, mainModuleAt(runtime_, "result"));
1316 const byte expected[] = {1, 2, 3};
1317 EXPECT_TRUE(isBytesEqualsBytes(result, expected));
1318}
1319
1320TEST_F(BytesBuiltinsTest, DunderReprWithEmptyBytesReturnsEmptyRepr) {
1321 HandleScope scope(thread_);
1322 Object self(&scope, Bytes::empty());
1323 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1324 EXPECT_TRUE(isStrEqualsCStr(*repr, "b''"));
1325}
1326
1327TEST_F(BytesBuiltinsTest, DunderReprWithSimpleBytesReturnsRepr) {
1328 HandleScope scope(thread_);
1329 Object self(&scope, runtime_->newBytes(10, '*'));
1330 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1331 EXPECT_TRUE(isStrEqualsCStr(*repr, "b'**********'"));
1332}
1333
1334TEST_F(BytesBuiltinsTest, DunderReprWithBytesSubclassReturnsStr) {
1335 ASSERT_FALSE(runFromCStr(runtime_, R"(
1336class Foo(bytes): pass
1337self = Foo(b"*****")
1338)")
1339 .isError());
1340 HandleScope scope(thread_);
1341 Object self(&scope, mainModuleAt(runtime_, "self"));
1342 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1343 EXPECT_TRUE(isStrEqualsCStr(*repr, "b'*****'"));
1344}
1345
1346TEST_F(BytesBuiltinsTest, DunderReprWithDoubleQuoteUsesSingleQuoteDelimiters) {
1347 HandleScope scope(thread_);
1348 const byte view[] = {'_', '"', '_'};
1349 Object self(&scope, runtime_->newBytesWithAll(view));
1350 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1351 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(b'_"_')"));
1352}
1353
1354TEST_F(BytesBuiltinsTest, DunderReprWithSingleQuoteUsesDoubleQuoteDelimiters) {
1355 HandleScope scope(thread_);
1356 const byte view[] = {'_', '\'', '_'};
1357 Object self(&scope, runtime_->newBytesWithAll(view));
1358 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1359 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(b"_'_")"));
1360}
1361
1362TEST_F(BytesBuiltinsTest, DunderReprWithBothQuotesUsesSingleQuoteDelimiters) {
1363 HandleScope scope(thread_);
1364 const byte view[] = {'_', '"', '_', '\'', '_'};
1365 Object self(&scope, runtime_->newBytesWithAll(view));
1366 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1367 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(b'_"_\'_')"));
1368}
1369
1370TEST_F(BytesBuiltinsTest, DunderReprWithSpeciaBytesUsesEscapeSequences) {
1371 HandleScope scope(thread_);
1372 const byte view[] = {'\\', '\t', '\n', '\r'};
1373 Object self(&scope, runtime_->newBytesWithAll(view));
1374 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1375 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(b'\\\t\n\r')"));
1376}
1377
1378TEST_F(BytesBuiltinsTest, DunderReprWithSmallAndLargeBytesUsesHex) {
1379 HandleScope scope(thread_);
1380 const byte view[] = {0, 0x1f, 0x80, 0xff};
1381 Object self(&scope, runtime_->newBytesWithAll(view));
1382 Object repr(&scope, runBuiltin(METH(bytes, __repr__), self));
1383 EXPECT_TRUE(isStrEqualsCStr(*repr, R"(b'\x00\x1f\x80\xff')"));
1384}
1385
1386TEST_F(BytesBuiltinsTest, DunderRmulCallsDunderMul) {
1387 HandleScope scope(thread_);
1388 ASSERT_FALSE(runFromCStr(runtime_, "result = 3 * b'1'").isError());
1389 Object result(&scope, mainModuleAt(runtime_, "result"));
1390 EXPECT_TRUE(isBytesEqualsCStr(result, "111"));
1391}
1392
1393TEST_F(BytesBuiltinsTest, DecodeWithASCIIReturnsString) {
1394 HandleScope scope(thread_);
1395 ASSERT_FALSE(
1396 runFromCStr(runtime_, "result = b'hello'.decode('ascii')").isError());
1397 Object result(&scope, mainModuleAt(runtime_, "result"));
1398 EXPECT_TRUE(isStrEqualsCStr(*result, "hello"));
1399}
1400
1401TEST_F(BytesBuiltinsTest, JoinWithBytesReturnsBytes) {
1402 HandleScope scope(thread_);
1403 Bytes sep(&scope, newBytesFromCStr(thread_, ","));
1404 Bytes obj1(&scope, newBytesFromCStr(thread_, "hello"));
1405 Bytes obj2(&scope, newBytesFromCStr(thread_, "world"));
1406 Tuple src(&scope, runtime_->newTupleWith2(obj1, obj2));
1407 Bytes result(&scope,
1408 bytesJoin(thread_, sep, sep.length(), src, src.length()));
1409 EXPECT_TRUE(isBytesEqualsCStr(result, "hello,world"));
1410}
1411
1412TEST_F(BytesBuiltinsTest, JoinWithBytearrayReturnsBytes) {
1413 HandleScope scope(thread_);
1414 Bytes sep(&scope, newBytesFromCStr(thread_, ","));
1415 Bytearray obj1(&scope, newBytearrayFromCStr(thread_, "hello"));
1416 Bytearray obj2(&scope, newBytearrayFromCStr(thread_, "world"));
1417 Tuple src(&scope, runtime_->newTupleWith2(obj1, obj2));
1418 Bytes result(&scope,
1419 bytesJoin(thread_, sep, sep.length(), src, src.length()));
1420 EXPECT_TRUE(isBytesEqualsCStr(result, "hello,world"));
1421}
1422
1423TEST_F(BytesBuiltinsTest, JoinWithMemoryviewReturnsBytes) {
1424 HandleScope scope(thread_);
1425 Bytes sep(&scope, newBytesFromCStr(thread_, ","));
1426 Bytes src1(&scope, newBytesFromCStr(thread_, "hello"));
1427 MemoryView obj1(&scope,
1428 runtime_->newMemoryView(thread_, src1, src1, src1.length(),
1429 ReadOnly::ReadOnly));
1430 Bytes src2(&scope, newBytesFromCStr(thread_, "world"));
1431 MemoryView obj2(&scope,
1432 runtime_->newMemoryView(thread_, src2, src2, src2.length(),
1433 ReadOnly::ReadOnly));
1434 Tuple src(&scope, runtime_->newTupleWith2(obj1, obj2));
1435 Bytes result(&scope,
1436 bytesJoin(thread_, sep, sep.length(), src, src.length()));
1437 EXPECT_TRUE(isBytesEqualsCStr(result, "hello,world"));
1438}
1439
1440TEST_F(BytesBuiltinsTest, HexWithEmptyBytesReturnsEmptyString) {
1441 HandleScope scope(thread_);
1442 Bytes self(&scope, Bytes::empty());
1443 Object result(&scope, runBuiltin(METH(bytes, hex), self));
1444 EXPECT_TRUE(isStrEqualsCStr(*result, ""));
1445}
1446
1447TEST_F(BytesBuiltinsTest, HexWithNonEmptyBytesReturnsString) {
1448 HandleScope scope(thread_);
1449 const byte bytes_array[] = {0x12, 0x34, 0xfe, 0x5b};
1450 Bytes self(&scope, runtime_->newBytesWithAll(bytes_array));
1451 Object result(&scope, runBuiltin(METH(bytes, hex), self));
1452 EXPECT_TRUE(isStrEqualsCStr(*result, "1234fe5b"));
1453}
1454
1455TEST_F(BytesBuiltinsTest, HexWithBytesSubclassReturnsStr) {
1456 ASSERT_FALSE(runFromCStr(runtime_, R"(
1457class Foo(bytes): pass
1458self = Foo(b"*\x01a\x92")
1459)")
1460 .isError());
1461 HandleScope scope(thread_);
1462 Object self(&scope, mainModuleAt(runtime_, "self"));
1463 Object repr(&scope, runBuiltin(METH(bytes, hex), self));
1464 EXPECT_TRUE(isStrEqualsCStr(*repr, "2a016192"));
1465}
1466
1467TEST_F(BytesBuiltinsTest, IsalnumWithEmptyBytesReturnsFalse) {
1468 HandleScope scope(thread_);
1469 Bytes self(&scope, Bytes::empty());
1470 Object result(&scope, runBuiltin(METH(bytes, isalnum), self));
1471 EXPECT_EQ(result, Bool::falseObj());
1472}
1473
1474TEST_F(BytesBuiltinsTest, IsalnumWithAllAlnumReturnsTrue) {
1475 HandleScope scope(thread_);
1476 const byte view[] = {'A', '1', 'a', '2', 'B'};
1477 Bytes self(&scope, runtime_->newBytesWithAll(view));
1478 Object result(&scope, runBuiltin(METH(bytes, isalnum), self));
1479 EXPECT_EQ(result, Bool::trueObj());
1480}
1481
1482TEST_F(BytesBuiltinsTest, IsalnumWithOneNonAlnumReturnsFalse) {
1483 HandleScope scope(thread_);
1484 const byte view[] = {'A', '1', ' ', '2', 'b'};
1485 Bytes self(&scope, runtime_->newBytesWithAll(view));
1486 Object result(&scope, runBuiltin(METH(bytes, isalnum), self));
1487 EXPECT_EQ(result, Bool::falseObj());
1488}
1489
1490TEST_F(BytesBuiltinsTest, IsalphaWithEmptyBytesReturnsFalse) {
1491 HandleScope scope(thread_);
1492 Bytes self(&scope, Bytes::empty());
1493 Object result(&scope, runBuiltin(METH(bytes, isalpha), self));
1494 EXPECT_EQ(result, Bool::falseObj());
1495}
1496
1497TEST_F(BytesBuiltinsTest, IsalphaWithAllAlphaReturnsTrue) {
1498 HandleScope scope(thread_);
1499 const byte view[] = {'A', 'a', 'Z', 'z'};
1500 Bytes self(&scope, runtime_->newBytesWithAll(view));
1501 Object result(&scope, runBuiltin(METH(bytes, isalpha), self));
1502 EXPECT_EQ(result, Bool::trueObj());
1503}
1504
1505TEST_F(BytesBuiltinsTest, IsAlphaWithOneDigitReturnsFalse) {
1506 HandleScope scope(thread_);
1507 const byte view[] = {'A', 'a', '1'};
1508 Bytes self(&scope, runtime_->newBytesWithAll(view));
1509 Object result(&scope, runBuiltin(METH(bytes, isalpha), self));
1510 EXPECT_EQ(result, Bool::falseObj());
1511}
1512
1513TEST_F(BytesBuiltinsTest, IsdigitWithEmptyBytesReturnsFalse) {
1514 HandleScope scope(thread_);
1515 Bytes self(&scope, Bytes::empty());
1516 Object result(&scope, runBuiltin(METH(bytes, isdigit), self));
1517 EXPECT_EQ(result, Bool::falseObj());
1518}
1519
1520TEST_F(BytesBuiltinsTest, IsdigitAllDigitsReturnsTrue) {
1521 HandleScope scope(thread_);
1522 const byte view[] = {'2', '0', '2', '0'};
1523 Bytes self(&scope, runtime_->newBytesWithAll(view));
1524 Object result(&scope, runBuiltin(METH(bytes, isdigit), self));
1525 EXPECT_EQ(result, Bool::trueObj());
1526}
1527
1528TEST_F(BytesBuiltinsTest, IsdigitOneAlphaReturnsFalse) {
1529 HandleScope scope(thread_);
1530 const byte view[] = {'4', '0', '1', 'k'};
1531 Bytes self(&scope, runtime_->newBytesWithAll(view));
1532 Object result(&scope, runBuiltin(METH(bytes, isdigit), self));
1533 EXPECT_EQ(result, Bool::falseObj());
1534}
1535
1536TEST_F(BytesBuiltinsTest, IsLowerWithEmptyBytesReturnsFalse) {
1537 HandleScope scope(thread_);
1538 Bytes self(&scope, Bytes::empty());
1539 Object result(&scope, runBuiltin(METH(bytes, islower), self));
1540 EXPECT_EQ(result, Bool::falseObj());
1541}
1542
1543TEST_F(BytesBuiltinsTest, IslowerWithAllLowercaseReturnsTrue) {
1544 HandleScope scope(thread_);
1545 const byte view[] = {'a', 'b', 'c'};
1546 Bytes self(&scope, runtime_->newBytesWithAll(view));
1547 Object result(&scope, runBuiltin(METH(bytes, islower), self));
1548 EXPECT_EQ(result, Bool::trueObj());
1549}
1550
1551TEST_F(BytesBuiltinsTest, IslowerWithOneUppercaseReturnsFalse) {
1552 HandleScope scope(thread_);
1553 const byte view[] = {'F', 'o', 'o'};
1554 Bytes self(&scope, runtime_->newBytesWithAll(view));
1555 Object result(&scope, runBuiltin(METH(bytes, islower), self));
1556 EXPECT_EQ(result, Bool::falseObj());
1557}
1558
1559TEST_F(BytesBuiltinsTest, IslowerWithOneDigitReturnsFalse) {
1560 HandleScope scope(thread_);
1561 const byte view[] = {'f', '8'};
1562 Bytes self(&scope, runtime_->newBytesWithAll(view));
1563 Object result(&scope, runBuiltin(METH(bytes, islower), self));
1564 EXPECT_EQ(result, Bool::falseObj());
1565}
1566
1567TEST_F(BytesBuiltinsTest, IsspaceWithEmptyBytesReturnsFalse) {
1568 HandleScope scope(thread_);
1569 Bytes self(&scope, Bytes::empty());
1570 Object result(&scope, runBuiltin(METH(bytes, isspace), self));
1571 EXPECT_EQ(result, Bool::falseObj());
1572}
1573
1574TEST_F(BytesBuiltinsTest, IsspaceWithAllWhitespaceReturnsTrue) {
1575 HandleScope scope(thread_);
1576 const byte view[] = {' ', '\n', '\t', '\r'};
1577 Bytes self(&scope, runtime_->newBytesWithAll(view));
1578 Object result(&scope, runBuiltin(METH(bytes, isspace), self));
1579 EXPECT_EQ(result, Bool::trueObj());
1580}
1581
1582TEST_F(BytesBuiltinsTest, IsspaceWithNonSpaceReturnsFalse) {
1583 HandleScope scope(thread_);
1584 const byte view[] = {'\t', '.', ' ', '\n'};
1585 Bytes self(&scope, runtime_->newBytesWithAll(view));
1586 Object result(&scope, runBuiltin(METH(bytes, isspace), self));
1587 EXPECT_EQ(result, Bool::falseObj());
1588}
1589
1590TEST_F(BytesBuiltinsTest, IstitleWithEmptyBytesReturnsFalse) {
1591 HandleScope scope(thread_);
1592 Bytes self(&scope, Bytes::empty());
1593 Object result(&scope, runBuiltin(METH(bytes, istitle), self));
1594 EXPECT_EQ(result, Bool::falseObj());
1595}
1596
1597TEST_F(BytesBuiltinsTest, IstitleWithTitlecaseWordsReturnsTrue) {
1598 HandleScope scope(thread_);
1599 const byte view[] = {'H', 'e', 'l', 'l', 'o', ' ',
1600 'W', 'o', 'r', 'l', 'd', '!'};
1601 Bytes self(&scope, runtime_->newBytesWithAll(view));
1602 Object result(&scope, runBuiltin(METH(bytes, istitle), self));
1603 EXPECT_EQ(result, Bool::trueObj());
1604}
1605
1606TEST_F(BytesBuiltinsTest, IstitleWithLowercaseWordStartReturnsFalse) {
1607 HandleScope scope(thread_);
1608 const byte view[] = {'F', 'o', 'o', '1', 'b', 'a', 'r'};
1609 Bytes self(&scope, runtime_->newBytesWithAll(view));
1610 Object result(&scope, runBuiltin(METH(bytes, istitle), self));
1611 EXPECT_EQ(result, Bool::falseObj());
1612}
1613
1614TEST_F(BytesBuiltinsTest, IstitleWithUppercaseMiddleReturnsFalse) {
1615 HandleScope scope(thread_);
1616 const byte view[] = {'F', 'o', 'O'};
1617 Bytes self(&scope, runtime_->newBytesWithAll(view));
1618 Object result(&scope, runBuiltin(METH(bytes, istitle), self));
1619 EXPECT_EQ(result, Bool::falseObj());
1620}
1621
1622TEST_F(BytesBuiltinsTest, IsupperWithEmptyBytesReturnsFalse) {
1623 HandleScope scope(thread_);
1624 Bytes self(&scope, Bytes::empty());
1625 Object result(&scope, runBuiltin(METH(bytes, isupper), self));
1626 EXPECT_EQ(result, Bool::falseObj());
1627}
1628
1629TEST_F(BytesBuiltinsTest, IsupperWithAllUppercaseReturnsTrue) {
1630 HandleScope scope(thread_);
1631 const byte view[] = {'F', 'O', 'O', 'B', 'A', 'R'};
1632 Bytes self(&scope, runtime_->newBytesWithAll(view));
1633 Object result(&scope, runBuiltin(METH(bytes, isupper), self));
1634 EXPECT_EQ(result, Bool::trueObj());
1635}
1636
1637TEST_F(BytesBuiltinsTest, IsupperWithOneLowercaseReturnsFalse) {
1638 HandleScope scope(thread_);
1639 const byte view[] = {'F', 'O', 'O', 'B', 'a', 'R'};
1640 Bytes self(&scope, runtime_->newBytesWithAll(view));
1641 Object result(&scope, runBuiltin(METH(bytes, isupper), self));
1642 EXPECT_EQ(result, Bool::falseObj());
1643}
1644
1645TEST_F(BytesBuiltinsTest, IsupperWithOneDigitReturnsFalse) {
1646 HandleScope scope(thread_);
1647 const byte view[] = {'F', '8'};
1648 Bytes self(&scope, runtime_->newBytesWithAll(view));
1649 Object result(&scope, runBuiltin(METH(bytes, isupper), self));
1650 EXPECT_EQ(result, Bool::falseObj());
1651}
1652
1653TEST_F(BytesBuiltinsTest, JoinWithNonIterableRaisesTypeError) {
1654 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b''.join(0)"),
1655 LayoutId::kTypeError,
1656 "'int' object is not iterable"));
1657}
1658
1659TEST_F(BytesBuiltinsTest, JoinWithMistypedIterableRaisesTypeError) {
1660 EXPECT_TRUE(raisedWithStr(
1661 runFromCStr(runtime_, "b' '.join([1])"), LayoutId::kTypeError,
1662 "sequence item 0: expected a bytes-like object, 'int' found"));
1663}
1664
1665TEST_F(BytesBuiltinsTest, JoinWithIterableReturnsBytes) {
1666 ASSERT_FALSE(runFromCStr(runtime_, R"(
1667class Foo:
1668 def __iter__(self):
1669 return [b'ab', b'c', b'def'].__iter__()
1670result = b' '.join(Foo())
1671)")
1672 .isError());
1673 Thread* thread = Thread::current();
1674 HandleScope scope(thread);
1675 Object result(&scope, mainModuleAt(runtime_, "result"));
1676 EXPECT_TRUE(isBytesEqualsCStr(result, "ab c def"));
1677}
1678
1679TEST_F(BytesBuiltinsTest, MaketransWithNonBytesLikeFromRaisesTypeError) {
1680 EXPECT_TRUE(raisedWithStr(
1681 runFromCStr(runtime_, "bytes.maketrans([1,2], b'ab')"),
1682 LayoutId::kTypeError, "a bytes-like object is required, not 'list'"));
1683}
1684
1685TEST_F(BytesBuiltinsTest, MaketransWithNonBytesLikeToRaisesTypeError) {
1686 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "bytes.maketrans(b'1', 2)"),
1687 LayoutId::kTypeError,
1688 "a bytes-like object is required, not 'int'"));
1689}
1690
1691TEST_F(BytesBuiltinsTest, MaketransWithDifferentLengthsRaisesValueError) {
1692 EXPECT_TRUE(raisedWithStr(
1693 runFromCStr(runtime_, "bytes.maketrans(b'12', bytearray())"),
1694 LayoutId::kValueError, "maketrans arguments must have same length"));
1695}
1696
1697TEST_F(BytesBuiltinsTest, MaketransWithEmptyReturnsDefaultBytes) {
1698 HandleScope scope(thread_);
1699 ASSERT_FALSE(
1700 runFromCStr(runtime_, "result = bytes.maketrans(bytearray(), b'')")
1701 .isError());
1702 Object result(&scope, mainModuleAt(runtime_, "result"));
1703 byte expected[256];
1704 for (word i = 0; i < 256; i++) {
1705 expected[i] = i;
1706 }
1707 EXPECT_TRUE(isBytesEqualsBytes(result, expected));
1708}
1709
1710TEST_F(BytesBuiltinsTest, MaketransWithNonEmptyReturnsBytes) {
1711 HandleScope scope(thread_);
1712 ASSERT_FALSE(
1713 runFromCStr(runtime_,
1714 "result = bytes.maketrans(bytearray(b'abc'), b'123')")
1715 .isError());
1716 Object result(&scope, mainModuleAt(runtime_, "result"));
1717 ASSERT_TRUE(result.isBytes());
1718 LargeBytes actual(&scope, *result);
1719 EXPECT_EQ(actual.byteAt('a'), '1');
1720 EXPECT_EQ(actual.byteAt('b'), '2');
1721 EXPECT_EQ(actual.byteAt('c'), '3');
1722}
1723
1724TEST_F(BytesBuiltinsTest, TranslateWithNonBytesLikeTableRaisesTypeError) {
1725 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b''.translate(42)"),
1726 LayoutId::kTypeError,
1727 "a bytes-like object is required, not 'int'"));
1728}
1729
1730TEST_F(BytesBuiltinsTest, TranslateWithNonBytesLikeDeleteRaisesTypeError) {
1731 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b''.translate(None, 42)"),
1732 LayoutId::kTypeError,
1733 "a bytes-like object is required, not 'int'"));
1734}
1735
1736TEST_F(BytesBuiltinsTest, TranslateWithShortTableRaisesValueError) {
1737 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "b''.translate(b'')"),
1738 LayoutId::kValueError,
1739 "translation table must be 256 characters long"));
1740}
1741
1742TEST_F(BytesBuiltinsTest, TranslateWithEmptyBytesReturnsEmptyBytes) {
1743 HandleScope scope(thread_);
1744 Object self(&scope, Bytes::empty());
1745 Object table(&scope, NoneType::object());
1746 Object del(&scope, runtime_->newBytearray());
1747 Object result(&scope, runBuiltin(METH(bytes, translate), self, table, del));
1748 EXPECT_EQ(result, Bytes::empty());
1749}
1750
1751TEST_F(BytesBuiltinsTest, TranslateWithNonEmptySecondArgDeletesBytes) {
1752 HandleScope scope(thread_);
1753 const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'};
1754 const byte abc[] = {'a', 'b', 'c'};
1755 Object self(&scope, runtime_->newBytesWithAll(alabama));
1756 Object table(&scope, NoneType::object());
1757 Object del(&scope, runtime_->newBytesWithAll(abc));
1758 Object result(&scope, runBuiltin(METH(bytes, translate), self, table, del));
1759 EXPECT_TRUE(isBytesEqualsCStr(result, "Alm"));
1760}
1761
1762TEST_F(BytesBuiltinsTest, TranslateWithTableTranslatesBytes) {
1763 HandleScope scope(thread_);
1764 ASSERT_FALSE(
1765 runFromCStr(runtime_, "table = bytes.maketrans(b'Aa', b'12')").isError());
1766 const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'};
1767 Object self(&scope, runtime_->newBytesWithAll(alabama));
1768 Object table(&scope, mainModuleAt(runtime_, "table"));
1769 Object del(&scope, Bytes::empty());
1770 Object result(&scope, runBuiltin(METH(bytes, translate), self, table, del));
1771 EXPECT_TRUE(isBytesEqualsCStr(result, "1l2b2m2"));
1772}
1773
1774TEST_F(BytesBuiltinsTest,
1775 TranslateWithTableAndDeleteTranslatesAndDeletesBytes) {
1776 HandleScope scope(thread_);
1777 ASSERT_FALSE(
1778 runFromCStr(runtime_, "table = bytes.maketrans(b'Aa', b'12')").isError());
1779 const byte alabama[] = {'A', 'l', 'a', 'b', 'a', 'm', 'a'};
1780 const byte abc[] = {'a', 'b', 'c'};
1781 Object self(&scope, runtime_->newBytesWithAll(alabama));
1782 Object table(&scope, mainModuleAt(runtime_, "table"));
1783 Object del(&scope, runtime_->newBytesWithAll(abc));
1784 Object result(&scope, runBuiltin(METH(bytes, translate), self, table, del));
1785 EXPECT_TRUE(isBytesEqualsCStr(result, "1lm"));
1786}
1787
1788TEST_F(BytesBuiltinsTest, TranslateDeletesAllBytes) {
1789 HandleScope scope(thread_);
1790 const byte alabama[] = {'b', 'a', 'c', 'a', 'a', 'c', 'a'};
1791 const byte abc[] = {'a', 'b', 'c'};
1792 Object self(&scope, runtime_->newBytesWithAll(alabama));
1793 Object table(&scope, NoneType::object());
1794 Object del(&scope, runtime_->newBytesWithAll(abc));
1795 Object result(&scope, runBuiltin(METH(bytes, translate), self, table, del));
1796 EXPECT_EQ(result, Bytes::empty());
1797}
1798
1799TEST_F(BytesIteratorBuiltinsTest, DunderLengthHintReturnsRemainingCount) {
1800 HandleScope scope(thread_);
1801 const byte data[] = {100, 0, 37};
1802 Bytes bytes(&scope, SmallBytes::fromBytes(data));
1803 Object iter(&scope, runtime_->newBytesIterator(thread_, bytes));
1804 Object result(&scope,
1805 runBuiltin(METH(bytes_iterator, __length_hint__), iter));
1806 EXPECT_TRUE(isIntEqualsWord(*result, 3));
1807 ASSERT_TRUE(!runBuiltin(METH(bytes_iterator, __next__), iter).isError());
1808 result = runBuiltin(METH(bytes_iterator, __length_hint__), iter);
1809 EXPECT_TRUE(isIntEqualsWord(*result, 2));
1810 ASSERT_TRUE(!runBuiltin(METH(bytes_iterator, __next__), iter).isError());
1811 result = runBuiltin(METH(bytes_iterator, __length_hint__), iter);
1812 EXPECT_TRUE(isIntEqualsWord(*result, 1));
1813 ASSERT_TRUE(!runBuiltin(METH(bytes_iterator, __next__), iter).isError());
1814 result = runBuiltin(METH(bytes_iterator, __length_hint__), iter);
1815 EXPECT_TRUE(isIntEqualsWord(*result, 0));
1816 EXPECT_TRUE(raised(runBuiltin(METH(bytes_iterator, __next__), iter),
1817 LayoutId::kStopIteration));
1818}
1819
1820TEST_F(BytesIteratorBuiltinsTest, DunderIterReturnsSelf) {
1821 HandleScope scope(thread_);
1822 const byte data[] = {100, 0, 37};
1823 Bytes bytes(&scope, SmallBytes::fromBytes(data));
1824 Object iter(&scope, runtime_->newBytesIterator(thread_, bytes));
1825 Object result(&scope, runBuiltin(METH(bytes_iterator, __iter__), iter));
1826 EXPECT_EQ(result, iter);
1827}
1828
1829TEST_F(BytesIteratorBuiltinsTest, DunderNextReturnsNextElement) {
1830 HandleScope scope(thread_);
1831 const byte data[] = {100, 0, 37};
1832 Bytes bytes(&scope, SmallBytes::fromBytes(data));
1833 Object iter(&scope, runtime_->newBytesIterator(thread_, bytes));
1834 Object result(&scope, runBuiltin(METH(bytes_iterator, __next__), iter));
1835 EXPECT_TRUE(isIntEqualsWord(*result, 100));
1836 result = runBuiltin(METH(bytes_iterator, __next__), iter);
1837 EXPECT_TRUE(isIntEqualsWord(*result, 0));
1838 result = runBuiltin(METH(bytes_iterator, __next__), iter);
1839 EXPECT_TRUE(isIntEqualsWord(*result, 37));
1840 EXPECT_TRUE(raised(runBuiltin(METH(bytes_iterator, __next__), iter),
1841 LayoutId::kStopIteration));
1842}
1843
1844} // namespace testing
1845} // namespace py