this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <cstring>
3
4#include "Python.h"
5#include "gtest/gtest.h"
6
7#include "capi-fixture.h"
8#include "capi-testing.h"
9
10namespace py {
11namespace testing {
12
13using BytesExtensionApiTest = ExtensionApi;
14using BytesWriterExtensionApiTest = ExtensionApi;
15
16TEST_F(BytesExtensionApiTest,
17 AsStringFromNonBytesReturnsNullAndRaisesTypeError) {
18 PyObjectPtr num(PyLong_FromLong(0));
19 EXPECT_EQ(PyBytes_AsString(num), nullptr);
20 ASSERT_NE(PyErr_Occurred(), nullptr);
21 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
22}
23
24TEST_F(BytesExtensionApiTest, AsStringWithBytesReturnsByteString) {
25 const char* str = "foo";
26 PyObjectPtr bytes(PyBytes_FromString(str));
27 EXPECT_STREQ(PyBytes_AsString(bytes), str);
28}
29
30TEST_F(BytesExtensionApiTest, AsStringWithZeroByteReturnsByteString) {
31 const char* str = "foo \0 bar";
32 PyObjectPtr bytes(PyBytes_FromStringAndSize(str, 9));
33 char* result = PyBytes_AsString(bytes);
34 std::vector<char> expected(str, str + 9);
35 std::vector<char> actual(result, result + 9);
36 EXPECT_EQ(actual, expected);
37}
38
39TEST_F(BytesExtensionApiTest, AsStringReturnsSameBufferTwice) {
40 const char* str = "foo";
41 PyObjectPtr bytes(PyBytes_FromString(str));
42 char* buffer1 = PyBytes_AsString(bytes);
43 char* buffer2 = PyBytes_AsString(bytes);
44 EXPECT_EQ(buffer1, buffer2);
45}
46
47TEST_F(BytesExtensionApiTest, AsStringWithBytesSubclassReturnsString) {
48 PyRun_SimpleString(R"(
49class Foo(bytes): pass
50foo = Foo(b"foo")
51)");
52 PyObjectPtr foo(mainModuleGet("foo"));
53 EXPECT_STREQ(PyBytes_AsString(foo), "foo");
54}
55
56TEST_F(BytesExtensionApiTest,
57 AsStringAndSizeWithNullBufferReturnsNegativeAndRaisesSystemError) {
58 PyObjectPtr bytes(PyBytes_FromString(""));
59 Py_ssize_t length;
60 EXPECT_EQ(PyBytes_AsStringAndSize(bytes, nullptr, &length), -1);
61 ASSERT_NE(PyErr_Occurred(), nullptr);
62 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
63}
64
65TEST_F(BytesExtensionApiTest,
66 AsStringAndSizeWithNonBytesReturnsNegativeAndRaisesTypeError) {
67 PyObjectPtr num(PyLong_FromLong(0));
68 char* buffer;
69 EXPECT_EQ(PyBytes_AsStringAndSize(num, &buffer, nullptr), -1);
70 ASSERT_NE(PyErr_Occurred(), nullptr);
71 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
72}
73
74TEST_F(BytesExtensionApiTest, AsStringAndSizeWithBytesReturnsStringAndSize) {
75 const char* str = "foo";
76 PyObjectPtr bytes(PyBytes_FromString(str));
77 char* buffer;
78 Py_ssize_t length;
79 ASSERT_EQ(PyBytes_AsStringAndSize(bytes, &buffer, &length), 0);
80 EXPECT_STREQ(buffer, str);
81 EXPECT_EQ(length, 3);
82}
83
84TEST_F(BytesExtensionApiTest,
85 AsStringAndSizeWithBytesSubclassReturnsStringAndSize) {
86 PyRun_SimpleString(R"(
87class Foo(bytes): pass
88foo = Foo(b"foo")
89)");
90 PyObjectPtr foo(mainModuleGet("foo"));
91 char* buffer;
92 Py_ssize_t length;
93 ASSERT_EQ(PyBytes_AsStringAndSize(foo, &buffer, &length), 0);
94 EXPECT_STREQ(buffer, "foo");
95 EXPECT_EQ(length, 3);
96}
97
98TEST_F(BytesExtensionApiTest,
99 AsStringAndSizeWithBytesAndNullLengthReturnsString) {
100 const char* str = "foo";
101 PyObjectPtr bytes(PyBytes_FromString(str));
102 char* buffer;
103 ASSERT_EQ(PyBytes_AsStringAndSize(bytes, &buffer, nullptr), 0);
104 EXPECT_STREQ(buffer, str);
105}
106
107TEST_F(BytesExtensionApiTest,
108 AsStringAndSizeWithZeroByteAndNullLengthRaisesValueError) {
109 PyObjectPtr bytes(PyBytes_FromStringAndSize("foo \0 bar", 9));
110 char* buffer;
111 EXPECT_EQ(PyBytes_AsStringAndSize(bytes, &buffer, nullptr), -1);
112 ASSERT_NE(PyErr_Occurred(), nullptr);
113 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
114}
115
116TEST_F(BytesExtensionApiTest, AsStringAndSizeReturnsSameBufferTwice) {
117 const char* str = "foo";
118 PyObjectPtr bytes(PyBytes_FromString(str));
119 char* buffer1;
120 char* buffer2;
121 ASSERT_EQ(PyBytes_AsStringAndSize(bytes, &buffer1, nullptr), 0);
122 ASSERT_EQ(PyBytes_AsStringAndSize(bytes, &buffer2, nullptr), 0);
123 EXPECT_EQ(buffer1, buffer2);
124}
125
126TEST_F(BytesExtensionApiTest, ConcatWithPointerToNullIsNoop) {
127 PyObject* foo = nullptr;
128 PyObjectPtr bar(PyLong_FromLong(0));
129 PyBytes_Concat(&foo, bar);
130 ASSERT_EQ(PyErr_Occurred(), nullptr);
131}
132
133TEST_F(BytesExtensionApiTest, ConcatWithNullSetsFirstArgNull) {
134 PyObject* foo = PyBytes_FromString("foo");
135 PyBytes_Concat(&foo, nullptr);
136 ASSERT_EQ(PyErr_Occurred(), nullptr);
137 EXPECT_EQ(foo, nullptr);
138}
139
140TEST_F(BytesExtensionApiTest, ConcatWithNonBytesFirstArgSetsFirstArgNull) {
141 PyObject* foo = PyLong_FromLong(0);
142 PyObjectPtr bar(PyBytes_FromString("bar"));
143 PyBytes_Concat(&foo, bar);
144 ASSERT_NE(PyErr_Occurred(), nullptr);
145 EXPECT_EQ(foo, nullptr);
146}
147
148TEST_F(BytesExtensionApiTest, ConcatWithNonBytesFirstArgRaisesTypeError) {
149 PyObject* foo = PyLong_FromLong(0);
150 PyObjectPtr bar(PyBytes_FromString("bar"));
151 PyBytes_Concat(&foo, bar);
152 ASSERT_NE(PyErr_Occurred(), nullptr);
153 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
154}
155
156TEST_F(BytesExtensionApiTest, ConcatWithNonBytesSecondArgSetsFirstArgNull) {
157 PyObject* foo = PyBytes_FromString("foo");
158 PyObjectPtr bar(PyLong_FromLong(0));
159 PyBytes_Concat(&foo, bar);
160 ASSERT_NE(PyErr_Occurred(), nullptr);
161 EXPECT_EQ(foo, nullptr);
162}
163
164TEST_F(BytesExtensionApiTest, ConcatWithNonBytesSecondArgRaisesTypeError) {
165 PyObject* foo = PyBytes_FromString("foo");
166 PyObjectPtr bar(PyLong_FromLong(0));
167 PyBytes_Concat(&foo, bar);
168 ASSERT_NE(PyErr_Occurred(), nullptr);
169 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
170}
171
172TEST_F(BytesExtensionApiTest, ConcatWithBytesConcatenatesByteStrings) {
173 PyObject* foo = PyBytes_FromString("foo");
174 PyObjectPtr bar(PyBytes_FromString("bar"));
175 PyBytes_Concat(&foo, bar);
176 ASSERT_EQ(PyErr_Occurred(), nullptr);
177 EXPECT_EQ(PyBytes_Size(foo), 6);
178 Py_DECREF(foo);
179}
180
181TEST_F(BytesExtensionApiTest, ConcatWithBytesSubclassesReturnsBytes) {
182 PyRun_SimpleString(R"(
183class Foo(bytes): pass
184foo = Foo(b"foo")
185bar = Foo(b"bar")
186)");
187 PyObject* foo = mainModuleGet("foo");
188 PyObjectPtr bar(mainModuleGet("bar"));
189 PyBytes_Concat(&foo, bar);
190 ASSERT_EQ(PyErr_Occurred(), nullptr);
191 EXPECT_STREQ(PyBytes_AsString(foo), "foobar");
192 Py_DECREF(foo);
193}
194
195TEST_F(BytesExtensionApiTest, ConcatDoesNotDecrefSecondArg) {
196 PyObject* foo = PyBytes_FromString("foo");
197 PyObjectPtr bar(PyBytes_FromString("bar"));
198 long refcnt = Py_REFCNT(bar);
199 ASSERT_GE(refcnt, 1);
200 PyBytes_Concat(&foo, bar);
201 ASSERT_EQ(PyErr_Occurred(), nullptr);
202 EXPECT_EQ(Py_REFCNT(bar), refcnt);
203 Py_DECREF(foo);
204}
205
206TEST_F(BytesExtensionApiTest, ConcatAndDelDecrefsSecondArg) {
207 PyObject* foo = nullptr;
208 PyObject* bar = PyBytes_FromString("bar");
209 long refcnt = Py_REFCNT(bar);
210 ASSERT_GE(refcnt, 1);
211 Py_INCREF(bar); // prevent bar from being deallocated
212 PyBytes_ConcatAndDel(&foo, bar);
213 ASSERT_EQ(PyErr_Occurred(), nullptr);
214 EXPECT_EQ(Py_REFCNT(bar), refcnt);
215 Py_DECREF(bar);
216}
217
218TEST_F(BytesExtensionApiTest, DecodeEscapeReturnsString) {
219 PyObjectPtr bytes(
220 PyBytes_DecodeEscape("hello \\\nworld", 13, nullptr, 0, nullptr));
221 ASSERT_EQ(PyErr_Occurred(), nullptr);
222 EXPECT_STREQ(PyBytes_AsString(bytes), "hello world");
223}
224
225TEST_F(BytesExtensionApiTest, UnderDecodeEscapeSetsFirstInvalidEscapeToNull) {
226 const char* invalid = reinterpret_cast<const char*>(0x100);
227 PyObjectPtr result(
228 _PyBytes_DecodeEscape("hello", 5, nullptr, 0, nullptr, &invalid));
229 EXPECT_NE(result, nullptr);
230 EXPECT_EQ(PyErr_Occurred(), nullptr);
231 EXPECT_EQ(invalid, nullptr);
232}
233
234TEST_F(BytesExtensionApiTest, UnderDecodeEscapeReturnsFirstInvalid) {
235 const char* invalid;
236 PyObjectPtr bytes(_PyBytes_DecodeEscape("hello \\yworld", 13, nullptr, 0,
237 nullptr, &invalid));
238 ASSERT_EQ(PyErr_Occurred(), nullptr);
239 EXPECT_STREQ(PyBytes_AsString(bytes), "hello \\yworld");
240 EXPECT_EQ(*invalid, 'y');
241}
242
243TEST_F(BytesExtensionApiTest, FromFormatWithNoSpecifiersReturnsBytes) {
244 PyObjectPtr bytes(PyBytes_FromFormat("hello world"));
245 ASSERT_TRUE(PyBytes_Check(bytes));
246 EXPECT_STREQ(PyBytes_AsString(bytes), "hello world");
247}
248
249TEST_F(BytesExtensionApiTest, FromFormatWithManyArgsReturnsBytes) {
250 PyObjectPtr bytes(PyBytes_FromFormat("%%%ih%c%.3s", 2, 'e', "llo world"));
251 ASSERT_TRUE(PyBytes_Check(bytes));
252 EXPECT_STREQ(PyBytes_AsString(bytes), "%2hello");
253}
254
255TEST_F(BytesExtensionApiTest, FromFormatIgnoresWidth) {
256 PyObjectPtr bytes(PyBytes_FromFormat("%5d", 42));
257 ASSERT_TRUE(PyBytes_Check(bytes));
258 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
259}
260
261TEST_F(BytesExtensionApiTest, FromFormatIgnoresPrecisionForInt) {
262 PyObjectPtr bytes(PyBytes_FromFormat("%5d", 42));
263 ASSERT_TRUE(PyBytes_Check(bytes));
264 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
265}
266
267TEST_F(BytesExtensionApiTest, FromFormatUsesPrecisionForString) {
268 PyObjectPtr bytes(PyBytes_FromFormat("%.5s", "hello world"));
269 ASSERT_TRUE(PyBytes_Check(bytes));
270 EXPECT_STREQ(PyBytes_AsString(bytes), "hello");
271}
272
273TEST_F(BytesExtensionApiTest, FromFormatCParsesChar) {
274 PyObjectPtr bytes(PyBytes_FromFormat("%c", 42));
275 EXPECT_STREQ(PyBytes_AsString(bytes), "*");
276}
277
278TEST_F(BytesExtensionApiTest, FromFormatCWithNegativeRaisesOverflowError) {
279 ASSERT_EQ(PyBytes_FromFormat("%c", -1), nullptr);
280 ASSERT_NE(PyErr_Occurred(), nullptr);
281 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_OverflowError));
282}
283
284TEST_F(BytesExtensionApiTest, FromFormatCWithLargeRaisesOverflowError) {
285 ASSERT_EQ(PyBytes_FromFormat("%c", 256), nullptr);
286 ASSERT_NE(PyErr_Occurred(), nullptr);
287 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_OverflowError));
288}
289
290TEST_F(BytesExtensionApiTest, FromFormatLDParsesLongDecimal) {
291 PyObjectPtr bytes(PyBytes_FromFormat("%ld", 42l));
292 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
293}
294
295TEST_F(BytesExtensionApiTest, FromFormatZDParsesPySsizeT) {
296 PyObjectPtr bytes(PyBytes_FromFormat("%zd", Py_ssize_t{42}));
297 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
298}
299
300TEST_F(BytesExtensionApiTest, FromFormatDParsesDecimal) {
301 PyObjectPtr bytes(PyBytes_FromFormat("%d", 42));
302 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
303}
304
305TEST_F(BytesExtensionApiTest, FromFormatLUParsesNumberTypes) {
306 PyObjectPtr bytes(PyBytes_FromFormat("%lu", 42l));
307 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
308}
309
310TEST_F(BytesExtensionApiTest, FromFormatZUParsesSizeT) {
311 PyObjectPtr bytes(PyBytes_FromFormat("%zu", size_t{42}));
312 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
313}
314
315TEST_F(BytesExtensionApiTest, FromFormatUParsesUnsignedDecimal) {
316 PyObjectPtr bytes(PyBytes_FromFormat("%u", 42));
317 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
318}
319
320TEST_F(BytesExtensionApiTest, FromFormatIParsesInt) {
321 PyObjectPtr bytes(PyBytes_FromFormat("%i", 42));
322 EXPECT_STREQ(PyBytes_AsString(bytes), "42");
323}
324
325TEST_F(BytesExtensionApiTest, FromFormatXParsesHex) {
326 PyObjectPtr bytes(PyBytes_FromFormat("%x", 42));
327 EXPECT_STREQ(PyBytes_AsString(bytes), "2a");
328}
329
330TEST_F(BytesExtensionApiTest, FromFormatSParsesString) {
331 PyObjectPtr bytes(PyBytes_FromFormat("%s", "UTF-8"));
332 ASSERT_TRUE(PyBytes_Check(bytes));
333 EXPECT_EQ(PyBytes_Size(bytes), 5);
334 EXPECT_STREQ(PyBytes_AsString(bytes), "UTF-8");
335}
336
337TEST_F(BytesExtensionApiTest, FromFormatPParsesPointer) {
338 long value = 0;
339 void* test = &value;
340 char buff[18];
341 std::snprintf(buff, sizeof(buff), "%p", test);
342 Py_ssize_t pointer_len = static_cast<Py_ssize_t>(std::strlen(buff));
343 PyObjectPtr bytes(PyBytes_FromFormat("%p", test));
344 ASSERT_TRUE(PyBytes_Check(bytes));
345 if (buff[1] == 'x') {
346 EXPECT_EQ(PyBytes_Size(bytes), pointer_len);
347 EXPECT_STREQ(PyBytes_AsString(bytes), buff);
348 } else {
349 EXPECT_EQ(PyBytes_Size(bytes), pointer_len + 2);
350 const char* str = PyBytes_AsString(bytes);
351 EXPECT_EQ(str[0], '0');
352 EXPECT_EQ(str[1], 'x');
353 EXPECT_STREQ(str + 2, buff);
354 }
355}
356
357TEST_F(BytesExtensionApiTest, FromObjectWithBytesReturnsArgument) {
358 PyObjectPtr bytes(PyBytes_FromString("foo"));
359 PyObjectPtr copy(PyBytes_FromObject(bytes));
360 EXPECT_EQ(copy, bytes);
361}
362
363TEST_F(BytesExtensionApiTest, FromObjectWithListReturnsBytes) {
364 PyObjectPtr list(PyList_New(3));
365 PyList_SetItem(list, 0, PyLong_FromLong('a'));
366 PyList_SetItem(list, 1, PyLong_FromLong('b'));
367 PyList_SetItem(list, 2, PyLong_FromLong('c'));
368 PyObjectPtr bytes(PyBytes_FromObject(list));
369 EXPECT_STREQ(PyBytes_AsString(bytes), "abc");
370}
371
372TEST_F(BytesExtensionApiTest, FromObjectWithTupleReturnsBytes) {
373 PyObjectPtr tuple(PyTuple_New(3));
374 PyTuple_SetItem(tuple, 0, PyLong_FromLong('a'));
375 PyTuple_SetItem(tuple, 1, PyLong_FromLong('b'));
376 PyTuple_SetItem(tuple, 2, PyLong_FromLong('c'));
377 PyObjectPtr bytes(PyBytes_FromObject(tuple));
378 EXPECT_STREQ(PyBytes_AsString(bytes), "abc");
379}
380
381TEST_F(BytesExtensionApiTest, FromObjectWithNonIntTupleRaisesTypeError) {
382 PyObjectPtr tuple(PyTuple_New(1));
383 Py_INCREF(Py_None);
384 PyTuple_SetItem(tuple, 0, Py_None);
385 ASSERT_EQ(PyBytes_FromObject(tuple), nullptr);
386 ASSERT_NE(PyErr_Occurred(), nullptr);
387 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
388}
389
390TEST_F(BytesExtensionApiTest, FromObjectWithNonIntIndexTupleRaisesTypeError) {
391 PyRun_SimpleString(R"(
392class Foo:
393 def __index__(self): return ''
394obj = (Foo(),)
395)");
396 PyObjectPtr tuple(mainModuleGet("obj"));
397 ASSERT_EQ(PyBytes_FromObject(tuple), nullptr);
398 ASSERT_NE(PyErr_Occurred(), nullptr);
399 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
400}
401
402TEST_F(BytesExtensionApiTest, FromObjectWithNegativeIntTupleRaisesValueError) {
403 PyObjectPtr tuple(PyTuple_New(1));
404 PyTuple_SetItem(tuple, 0, PyLong_FromLong(-1));
405 ASSERT_EQ(PyBytes_FromObject(tuple), nullptr);
406 ASSERT_NE(PyErr_Occurred(), nullptr);
407 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
408}
409
410TEST_F(BytesExtensionApiTest, FromObjectWithOverflowTupleRaisesValueError) {
411 PyObjectPtr tuple(PyTuple_New(1));
412 PyTuple_SetItem(tuple, 0, PyLong_FromLong(256));
413 ASSERT_EQ(PyBytes_FromObject(tuple), nullptr);
414 ASSERT_NE(PyErr_Occurred(), nullptr);
415 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
416}
417
418TEST_F(BytesExtensionApiTest, FromObjectWithStringRaisesTypeError) {
419 PyObjectPtr str(PyUnicode_FromString("hello"));
420 ASSERT_EQ(PyBytes_FromObject(str), nullptr);
421 ASSERT_NE(PyErr_Occurred(), nullptr);
422 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
423}
424
425TEST_F(BytesExtensionApiTest, FromObjectWithNonIterableRaisesTypeError) {
426 PyObjectPtr num(PyLong_FromLong(1));
427 ASSERT_EQ(PyBytes_FromObject(num), nullptr);
428 ASSERT_NE(PyErr_Occurred(), nullptr);
429 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
430}
431
432TEST_F(BytesExtensionApiTest, FromObjectWithBadIteratorRaisesTypeError) {
433 PyRun_SimpleString(R"(
434class NotIterator: pass
435class HasIter:
436 def __iter__(self): return NotIterator()
437obj = HasIter()
438)");
439 PyObjectPtr obj(mainModuleGet("obj"));
440 ASSERT_EQ(PyBytes_FromObject(obj), nullptr);
441 ASSERT_NE(PyErr_Occurred(), nullptr);
442 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
443}
444
445TEST_F(BytesExtensionApiTest, FromObjectWithSetReturnsBytes) {
446 PyObjectPtr set(PySet_New(nullptr));
447 PyObjectPtr obj(PyLong_FromLong('a'));
448 PySet_Add(set, obj);
449 PyObjectPtr bytes(PyBytes_FromObject(set));
450 EXPECT_STREQ(PyBytes_AsString(bytes), "a");
451}
452
453TEST_F(BytesExtensionApiTest, FromStringAndSizeIncrementsRefCount) {
454 PyObject* bytes = PyBytes_FromStringAndSize("foo", 3);
455 ASSERT_NE(bytes, nullptr);
456 EXPECT_GE(Py_REFCNT(bytes), 1);
457 Py_DECREF(bytes);
458 EXPECT_EQ(PyErr_Occurred(), nullptr);
459}
460
461TEST_F(BytesExtensionApiTest, FromStringAndSizeReturnsBytes) {
462 PyObjectPtr bytes(PyBytes_FromStringAndSize("foo", 3));
463 EXPECT_TRUE(PyBytes_CheckExact(bytes));
464 EXPECT_EQ(PyBytes_Size(bytes), 3);
465}
466
467TEST_F(BytesExtensionApiTest,
468 FromStringAndSizeWithEmptyStringReturnsEmptyBytes) {
469 PyObjectPtr bytes(PyBytes_FromStringAndSize("", 0));
470 EXPECT_TRUE(PyBytes_CheckExact(bytes));
471 EXPECT_EQ(PyBytes_Size(bytes), 0);
472}
473
474TEST_F(BytesExtensionApiTest, FromStringAndSizeWithZeroSizeReturnsEmptyBytes) {
475 PyObjectPtr bytes(PyBytes_FromStringAndSize(nullptr, 0));
476 EXPECT_TRUE(PyBytes_CheckExact(bytes));
477 EXPECT_EQ(PyBytes_Size(bytes), 0);
478}
479
480TEST_F(BytesExtensionApiTest, FromStringAndSizeWithNegativeSizeReturnsNull) {
481 EXPECT_EQ(PyBytes_FromStringAndSize("foo", -1), nullptr);
482 ASSERT_NE(PyErr_Occurred(), nullptr);
483 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
484}
485
486TEST_F(BytesExtensionApiTest, FromStringAndSizeWithShorterSize) {
487 PyObjectPtr bytes(PyBytes_FromStringAndSize("foo bar", 5));
488 EXPECT_TRUE(PyBytes_CheckExact(bytes));
489 EXPECT_EQ(PyBytes_Size(bytes), 5);
490}
491
492TEST_F(BytesExtensionApiTest, FromStringAndSizeWithSizeZero) {
493 PyObjectPtr bytes(PyBytes_FromStringAndSize("foo bar", 0));
494 EXPECT_TRUE(PyBytes_CheckExact(bytes));
495 EXPECT_EQ(PyBytes_Size(bytes), 0);
496}
497
498TEST_F(BytesExtensionApiTest, FromStringIncrementsRefCount) {
499 PyObject* bytes = PyBytes_FromString("foo");
500 ASSERT_NE(bytes, nullptr);
501 EXPECT_GE(Py_REFCNT(bytes), 1);
502 Py_DECREF(bytes);
503 EXPECT_EQ(PyErr_Occurred(), nullptr);
504}
505
506TEST_F(BytesExtensionApiTest, FromStringReturnsBytes) {
507 PyObjectPtr bytes(PyBytes_FromString("foo"));
508 EXPECT_TRUE(PyBytes_CheckExact(bytes));
509 EXPECT_EQ(PyBytes_Size(bytes), 3);
510}
511
512TEST_F(BytesExtensionApiTest, FromStringWithEmptyStringReturnsEmptyBytes) {
513 PyObjectPtr bytes(PyBytes_FromString(""));
514 EXPECT_TRUE(PyBytes_CheckExact(bytes));
515 EXPECT_EQ(PyBytes_Size(bytes), 0);
516}
517
518TEST_F(BytesExtensionApiTest, JoinWithEmptyIteratorReturnsBytes) {
519 PyObjectPtr sep(PyBytes_FromString("foo"));
520 PyObjectPtr iter(PyTuple_New(0));
521 PyObjectPtr join(_PyBytes_Join(sep, iter));
522 EXPECT_TRUE(PyBytes_CheckExact(join));
523 EXPECT_STREQ(PyBytes_AsString(join), "");
524}
525
526TEST_F(BytesExtensionApiTest, JoinWithOneElementIteratorReturnsBytes) {
527 PyObjectPtr sep(PyBytes_FromString("foo"));
528 PyObjectPtr iter(PyTuple_New(1));
529 ASSERT_EQ(PyTuple_SetItem(iter, 0, PyBytes_FromString("bar")), 0);
530 PyObjectPtr join(_PyBytes_Join(sep, iter));
531 EXPECT_TRUE(PyBytes_CheckExact(join));
532 EXPECT_STREQ(PyBytes_AsString(join), "bar");
533}
534
535TEST_F(BytesExtensionApiTest, JoinWithEmptySeparatorReturnsBytes) {
536 PyObjectPtr sep(PyBytes_FromString(""));
537 PyObjectPtr iter(PyList_New(3));
538 ASSERT_EQ(PyList_SetItem(iter, 0, PyBytes_FromString("ab")), 0);
539 ASSERT_EQ(PyList_SetItem(iter, 1, PyBytes_FromString("cde")), 0);
540 ASSERT_EQ(PyList_SetItem(iter, 2, PyBytes_FromString("f")), 0);
541 PyObjectPtr join(_PyBytes_Join(sep, iter));
542 EXPECT_TRUE(PyBytes_CheckExact(join));
543 EXPECT_STREQ(PyBytes_AsString(join), "abcdef");
544}
545
546TEST_F(BytesExtensionApiTest, JoinWithNonEmptySeparatorReturnsBytes) {
547 PyObjectPtr sep(PyBytes_FromString(" "));
548 PyObjectPtr iter(PyList_New(3));
549 ASSERT_EQ(PyList_SetItem(iter, 0, PyBytes_FromString("ab")), 0);
550 ASSERT_EQ(PyList_SetItem(iter, 1, PyBytes_FromString("cde")), 0);
551 ASSERT_EQ(PyList_SetItem(iter, 2, PyBytes_FromString("f")), 0);
552 PyObjectPtr join(_PyBytes_Join(sep, iter));
553 EXPECT_TRUE(PyBytes_CheckExact(join));
554 EXPECT_STREQ(PyBytes_AsString(join), "ab cde f");
555}
556
557TEST_F(BytesExtensionApiTest, JoinWithBytesSubclassReturnsBytes) {
558 PyRun_SimpleString(R"(
559class Foo(bytes):
560 def join(self, iterable):
561 # we expect to call bytes.join(), not this method
562 return 0
563sep = Foo(b"-")
564first = Foo(b"ab")
565second = Foo(b"")
566third = Foo(b"123456789")
567 )");
568 PyObjectPtr sep(mainModuleGet("sep"));
569 PyObjectPtr iter(PyList_New(3));
570 ASSERT_EQ(PyList_SetItem(iter, 0, mainModuleGet("first")), 0);
571 ASSERT_EQ(PyList_SetItem(iter, 1, mainModuleGet("second")), 0);
572 ASSERT_EQ(PyList_SetItem(iter, 2, mainModuleGet("third")), 0);
573 PyObjectPtr join(_PyBytes_Join(sep, iter));
574 EXPECT_TRUE(PyBytes_CheckExact(join));
575 EXPECT_STREQ(PyBytes_AsString(join), "ab--123456789");
576}
577
578TEST_F(BytesExtensionApiTest, JoinWithMistypedIteratorRaisesTypeError) {
579 PyObjectPtr sep(PyBytes_FromString(" "));
580 PyObjectPtr iter(PyTuple_New(1));
581 ASSERT_EQ(PyTuple_SetItem(iter, 0, PyLong_FromLong(0)), 0);
582 ASSERT_EQ(_PyBytes_Join(sep, iter), nullptr);
583 ASSERT_NE(PyErr_Occurred(), nullptr);
584 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
585}
586
587TEST_F(BytesExtensionApiTest, ReprWithNonBytesRaisesTypeErrorPyro) {
588 PyObjectPtr array(PyByteArray_FromStringAndSize("", 0));
589 ASSERT_EQ(PyBytes_Repr(array, true), nullptr);
590 ASSERT_NE(PyErr_Occurred(), nullptr);
591 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
592}
593
594TEST_F(BytesExtensionApiTest, ReprWithEmptyBytesReturnsEmptyRepr) {
595 PyObjectPtr bytes(PyBytes_FromString(""));
596 PyObjectPtr repr(PyBytes_Repr(bytes, true));
597 ASSERT_TRUE(PyUnicode_Check(repr));
598 EXPECT_TRUE(isUnicodeEqualsCStr(repr, "b''"));
599}
600
601TEST_F(BytesExtensionApiTest, ReprWithSimpleBytesReturnsRepr) {
602 PyObjectPtr bytes(PyBytes_FromString("Hello world!"));
603 PyObjectPtr repr(PyBytes_Repr(bytes, true));
604 EXPECT_TRUE(isUnicodeEqualsCStr(repr, "b'Hello world!'"));
605}
606
607TEST_F(BytesExtensionApiTest, ReprWithBytesSubclassReturnsString) {
608 PyRun_SimpleString(R"(
609class Foo(bytes): pass
610self = Foo(b"Hello world!")
611)");
612 PyObjectPtr self(mainModuleGet("self"));
613 PyObjectPtr repr(PyBytes_Repr(self, true));
614 EXPECT_TRUE(isUnicodeEqualsCStr(repr, "b'Hello world!'"));
615}
616
617TEST_F(BytesExtensionApiTest, ReprWithDoubleQuoteUsesSingleQuoteDelimiters) {
618 PyObjectPtr bytes(PyBytes_FromString(R"(_"_)"));
619 PyObjectPtr repr(PyBytes_Repr(bytes, true));
620 EXPECT_TRUE(isUnicodeEqualsCStr(repr, R"(b'_"_')"));
621}
622
623TEST_F(BytesExtensionApiTest, ReprWithSingleQuoteUsesDoubleQuoteDelimiters) {
624 PyObjectPtr bytes(PyBytes_FromString("_'_"));
625 PyObjectPtr repr(PyBytes_Repr(bytes, true));
626 EXPECT_TRUE(isUnicodeEqualsCStr(repr, R"(b"_'_")"));
627}
628
629TEST_F(BytesExtensionApiTest,
630 ReprWithSingleQuoteWithoutSmartquotesUsesSingleQuoteDelimiters) {
631 PyObjectPtr bytes(PyBytes_FromString("_'_"));
632 PyObjectPtr repr(PyBytes_Repr(bytes, false));
633 EXPECT_TRUE(isUnicodeEqualsCStr(repr, R"(b'_\'_')"));
634}
635
636TEST_F(BytesExtensionApiTest, ReprWithBothQuotesUsesSingleQuoteDelimiters) {
637 PyObjectPtr bytes(PyBytes_FromString(R"(_"_'_)"));
638 PyObjectPtr repr(PyBytes_Repr(bytes, true));
639 EXPECT_TRUE(isUnicodeEqualsCStr(repr, R"(b'_"_\'_')"));
640}
641
642TEST_F(BytesExtensionApiTest, ReprWithSpeciaBytesUsesEscapeSequences) {
643 PyObjectPtr bytes(PyBytes_FromString("\\\t\n\r"));
644 PyObjectPtr repr(PyBytes_Repr(bytes, true));
645 EXPECT_TRUE(isUnicodeEqualsCStr(repr, R"(b'\\\t\n\r')"));
646}
647
648TEST_F(BytesExtensionApiTest, ReprWithSmallAndLargeBytesUsesHex) {
649 char str[4] = {0, 0x1f, static_cast<char>(0x80), static_cast<char>(0xff)};
650 Py_ssize_t size = static_cast<Py_ssize_t>(sizeof(str));
651 PyObjectPtr bytes(PyBytes_FromStringAndSize(str, size));
652 PyObjectPtr repr(PyBytes_Repr(bytes, true));
653 EXPECT_TRUE(isUnicodeEqualsCStr(repr, R"(b'\x00\x1f\x80\xff')"));
654}
655
656TEST_F(BytesExtensionApiTest, ResizeWithNonBytesRaisesSystemError) {
657 PyObject* num = PyLong_FromLong(0);
658 ASSERT_EQ(_PyBytes_Resize(&num, 1), -1);
659 ASSERT_EQ(num, nullptr);
660 ASSERT_NE(PyErr_Occurred(), nullptr);
661 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
662}
663
664TEST_F(BytesExtensionApiTest, ResizeWithNegativeNewSizeRaisesSystemError) {
665 PyObject* bytes = PyBytes_FromString("hello");
666 ASSERT_EQ(_PyBytes_Resize(&bytes, -1), -1);
667 ASSERT_EQ(bytes, nullptr);
668 ASSERT_NE(PyErr_Occurred(), nullptr);
669 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
670}
671
672TEST_F(BytesExtensionApiTest, ResizeWithSameSizeKeepsBytes) {
673 PyObject* bytes = PyBytes_FromString("hello");
674 PyObject** arg = &bytes;
675 ASSERT_EQ(_PyBytes_Resize(&bytes, 5), 0);
676 ASSERT_EQ(PyErr_Occurred(), nullptr);
677 EXPECT_EQ(&bytes, arg);
678 Py_DECREF(bytes);
679}
680
681TEST_F(BytesExtensionApiTest, ResizeWithLargerSizeAllocatesLargerBytes) {
682 PyObject* bytes = PyBytes_FromString("hello");
683 ASSERT_EQ(_PyBytes_Resize(&bytes, 10), 0);
684 ASSERT_EQ(PyErr_Occurred(), nullptr);
685 EXPECT_EQ(PyBytes_Size(bytes), 10);
686 EXPECT_STREQ(PyBytes_AsString(bytes), "hello"); // sixth byte is 0
687 Py_DECREF(bytes);
688}
689
690TEST_F(BytesExtensionApiTest, ResizeWithSmallerSizeAllocatesSmallerBytes) {
691 PyObject* bytes = PyBytes_FromString("hello");
692 ASSERT_EQ(_PyBytes_Resize(&bytes, 2), 0);
693 ASSERT_EQ(PyErr_Occurred(), nullptr);
694 EXPECT_EQ(PyBytes_Size(bytes), 2);
695 EXPECT_STREQ(PyBytes_AsString(bytes), "he");
696 Py_DECREF(bytes);
697}
698
699TEST_F(BytesExtensionApiTest,
700 ResizeWithNonEmptyBytesAndZeroNewsizeReturnsEmpty) {
701 PyObject* bytes = PyBytes_FromString("hello");
702 ASSERT_EQ(_PyBytes_Resize(&bytes, 0), 0);
703 ASSERT_EQ(PyErr_Occurred(), nullptr);
704 EXPECT_EQ(PyBytes_Size(bytes), 0);
705 EXPECT_STREQ(PyBytes_AsString(bytes), "");
706 Py_DECREF(bytes);
707}
708
709TEST_F(BytesExtensionApiTest, SizeWithNonBytesReturnsNegative) {
710 PyObjectPtr dict(PyDict_New());
711
712 EXPECT_EQ(PyBytes_Size(dict), -1);
713 ASSERT_NE(PyErr_Occurred(), nullptr);
714 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
715}
716
717TEST_F(BytesExtensionApiTest, SizeWithBytesSubclassesReturnsLength) {
718 PyRun_SimpleString(R"(
719class Foo(bytes): pass
720empty = Foo()
721foo = Foo(b"foo")
722)");
723 PyObjectPtr empty(mainModuleGet("empty"));
724 PyObjectPtr foo(mainModuleGet("foo"));
725 EXPECT_EQ(PyBytes_Size(empty), 0);
726 EXPECT_EQ(PyBytes_Size(foo), 3);
727}
728
729// _PyBytesWriter API
730
731TEST_F(BytesWriterExtensionApiTest, AllocSetsUpBuffer) {
732 Py_ssize_t size = 10;
733 _PyBytesWriter writer;
734 _PyBytesWriter_Init(&writer);
735 EXPECT_NE(_PyBytesWriter_Alloc(&writer, size), nullptr);
736 EXPECT_GE(writer.allocated, size);
737 EXPECT_EQ(writer.min_size, size);
738 _PyBytesWriter_Dealloc(&writer);
739}
740
741TEST_F(BytesWriterExtensionApiTest,
742 FinishWithHeapBufferAndNoSizeDeallocsBuffer) {
743 // at least big enough for heap buffer
744 Py_ssize_t size = 50000;
745 _PyBytesWriter writer;
746 _PyBytesWriter_Init(&writer);
747 void* buffer = _PyBytesWriter_Alloc(&writer, size);
748 EXPECT_NE(buffer, nullptr);
749 EXPECT_EQ(writer.allocated, size);
750 EXPECT_EQ(writer.min_size, size);
751 PyObjectPtr result(_PyBytesWriter_Finish(&writer, buffer));
752 EXPECT_NE(result, nullptr);
753 EXPECT_TRUE(PyBytes_CheckExact(result));
754}
755
756TEST_F(BytesWriterExtensionApiTest, DeallocFreesHeapBuffer) {
757 _PyBytesWriter writer;
758 _PyBytesWriter_Init(&writer);
759 void* str = _PyBytesWriter_Alloc(&writer, 0);
760 EXPECT_NE(str, nullptr);
761 str = _PyBytesWriter_Resize(&writer, str, 5000);
762 EXPECT_NE(str, nullptr);
763 const char* to_write = "Hello world!";
764 Py_ssize_t len = std::strlen(to_write);
765 str = _PyBytesWriter_WriteBytes(&writer, str, to_write, len);
766 ASSERT_NE(str, nullptr);
767 EXPECT_EQ(writer.min_size, len);
768 PyObjectPtr result(_PyBytesWriter_Finish(&writer, str));
769 ASSERT_TRUE(PyBytes_CheckExact(result));
770 _PyBytesWriter_Dealloc(&writer);
771}
772
773TEST_F(BytesWriterExtensionApiTest, FinishWithEmptyWriterReturnsEmptyBytes) {
774 _PyBytesWriter writer;
775 _PyBytesWriter_Init(&writer);
776 void* str = _PyBytesWriter_Alloc(&writer, 0);
777 ASSERT_NE(str, nullptr);
778 PyObjectPtr result(_PyBytesWriter_Finish(&writer, str));
779 _PyBytesWriter_Dealloc(&writer);
780 EXPECT_TRUE(PyBytes_CheckExact(result));
781 EXPECT_EQ(PyBytes_Size(result), 0);
782}
783
784TEST_F(BytesWriterExtensionApiTest,
785 FinishWithEmptyWriterUseByteArrayReturnsEmptyByteArray) {
786 _PyBytesWriter writer;
787 _PyBytesWriter_Init(&writer);
788 void* str = _PyBytesWriter_Alloc(&writer, 0);
789 ASSERT_NE(str, nullptr);
790 writer.use_bytearray = true;
791 PyObjectPtr result(_PyBytesWriter_Finish(&writer, str));
792 _PyBytesWriter_Dealloc(&writer);
793 EXPECT_TRUE(PyByteArray_CheckExact(result));
794 EXPECT_EQ(PyByteArray_Size(result), 0);
795}
796
797TEST_F(BytesWriterExtensionApiTest, FinishReturnsBytes) {
798 Py_ssize_t size = 10;
799 _PyBytesWriter writer;
800 _PyBytesWriter_Init(&writer);
801 char* str = reinterpret_cast<char*>(_PyBytesWriter_Alloc(&writer, 0));
802 ASSERT_NE(str, nullptr);
803 for (char c = 'a'; c < 'a' + size; c++) {
804 *str++ = c;
805 }
806 PyObjectPtr result(_PyBytesWriter_Finish(&writer, str));
807 _PyBytesWriter_Dealloc(&writer);
808 EXPECT_TRUE(PyBytes_CheckExact(result));
809 EXPECT_EQ(PyBytes_Size(result), size);
810 EXPECT_STREQ(PyBytes_AsString(result), "abcdefghij");
811}
812
813TEST_F(BytesWriterExtensionApiTest, FinishUseByteArrayReturnsByteArray) {
814 Py_ssize_t size = 10;
815 _PyBytesWriter writer;
816 _PyBytesWriter_Init(&writer);
817 char* str = reinterpret_cast<char*>(_PyBytesWriter_Alloc(&writer, 0));
818 ASSERT_NE(str, nullptr);
819 for (char c = 'a'; c < 'a' + size; c++) {
820 *str++ = c;
821 }
822 writer.use_bytearray = true;
823 PyObjectPtr result(_PyBytesWriter_Finish(&writer, str));
824 _PyBytesWriter_Dealloc(&writer);
825 EXPECT_TRUE(PyByteArray_CheckExact(result));
826 EXPECT_EQ(PyByteArray_Size(result), size);
827 EXPECT_STREQ(PyByteArray_AsString(result), "abcdefghij");
828}
829
830TEST_F(BytesWriterExtensionApiTest, InitSetsFieldsToZero) {
831 _PyBytesWriter writer;
832 _PyBytesWriter_Init(&writer);
833 EXPECT_EQ(writer.allocated, 0);
834 EXPECT_EQ(writer.min_size, 0);
835 EXPECT_FALSE(writer.overallocate);
836 EXPECT_FALSE(writer.use_bytearray);
837}
838
839TEST_F(BytesWriterExtensionApiTest, PrepareWithZeroReturnsSamePointer) {
840 Py_ssize_t initial_size = 10;
841 _PyBytesWriter writer;
842 _PyBytesWriter_Init(&writer);
843 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
844 ASSERT_NE(str, nullptr);
845 ASSERT_EQ(writer.min_size, initial_size);
846 EXPECT_EQ(_PyBytesWriter_Prepare(&writer, str, 0), str);
847 EXPECT_EQ(writer.min_size, initial_size);
848}
849
850TEST_F(BytesWriterExtensionApiTest, PrepareWithNonZeroIncreasesMinSize) {
851 Py_ssize_t initial_size = 10;
852 Py_ssize_t growth = 20;
853 _PyBytesWriter writer;
854 _PyBytesWriter_Init(&writer);
855 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
856 ASSERT_NE(str, nullptr);
857 ASSERT_EQ(writer.min_size, initial_size);
858 EXPECT_NE(_PyBytesWriter_Prepare(&writer, str, growth), nullptr);
859 EXPECT_EQ(writer.min_size, initial_size + growth);
860}
861
862TEST_F(BytesWriterExtensionApiTest, PrepareWithLargeIntRaisesMemoryError) {
863 Py_ssize_t initial_size = 10;
864 _PyBytesWriter writer;
865 _PyBytesWriter_Init(&writer);
866 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
867 ASSERT_NE(str, nullptr);
868 EXPECT_EQ(_PyBytesWriter_Prepare(&writer, str, PY_SSIZE_T_MAX), nullptr);
869 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_MemoryError));
870}
871
872TEST_F(BytesWriterExtensionApiTest, ResizeAllocatesNewBuffer) {
873 Py_ssize_t initial_size = 10;
874 Py_ssize_t new_size = 1000;
875 _PyBytesWriter writer;
876 _PyBytesWriter_Init(&writer);
877 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
878 ASSERT_NE(str, nullptr);
879 ASSERT_LT(writer.allocated, new_size);
880 void* new_str = _PyBytesWriter_Resize(&writer, str, new_size);
881 EXPECT_NE(new_str, nullptr);
882 EXPECT_NE(new_str, str); // buffer has been reallocated
883 EXPECT_EQ(writer.allocated, new_size);
884 _PyBytesWriter_Dealloc(&writer);
885}
886
887TEST_F(BytesWriterExtensionApiTest, ResizeWithOverallocateAllocatesOversized) {
888 Py_ssize_t initial_size = 10;
889 Py_ssize_t new_size = 1000;
890 _PyBytesWriter writer;
891 _PyBytesWriter_Init(&writer);
892 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
893 ASSERT_NE(str, nullptr);
894 ASSERT_LT(writer.allocated, new_size);
895 writer.overallocate = true;
896 void* new_str = _PyBytesWriter_Resize(&writer, str, new_size);
897 EXPECT_NE(new_str, nullptr);
898 EXPECT_NE(new_str, str); // buffer has been reallocated
899 EXPECT_GT(writer.allocated, new_size);
900 _PyBytesWriter_Dealloc(&writer);
901}
902
903TEST_F(BytesWriterExtensionApiTest,
904 ResizeWithUseByteArrayAllocatesOversizedPyro) {
905 Py_ssize_t initial_size = 10;
906 Py_ssize_t new_size = 1000;
907 _PyBytesWriter writer;
908 _PyBytesWriter_Init(&writer);
909 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
910 ASSERT_NE(str, nullptr);
911 ASSERT_LT(writer.allocated, new_size);
912 writer.use_bytearray = true;
913 void* new_str = _PyBytesWriter_Resize(&writer, str, new_size);
914 EXPECT_NE(new_str, nullptr);
915 EXPECT_NE(new_str, str); // buffer has been reallocated
916 EXPECT_GT(writer.allocated, new_size);
917 _PyBytesWriter_Dealloc(&writer);
918}
919
920TEST_F(BytesWriterExtensionApiTest, WriteBytesGrowsAndWrites) {
921 Py_ssize_t initial_size = 10;
922 Py_ssize_t growth = 5;
923 _PyBytesWriter writer;
924 _PyBytesWriter_Init(&writer);
925 void* str = _PyBytesWriter_Alloc(&writer, initial_size);
926 ASSERT_NE(str, nullptr);
927 ASSERT_EQ(writer.min_size, initial_size);
928 str = _PyBytesWriter_WriteBytes(&writer, str, "Hello world!", growth);
929 ASSERT_NE(str, nullptr);
930 EXPECT_EQ(writer.min_size, initial_size + growth);
931 PyObjectPtr result(_PyBytesWriter_Finish(&writer, str));
932 _PyBytesWriter_Dealloc(&writer);
933 ASSERT_TRUE(PyBytes_CheckExact(result));
934 EXPECT_EQ(PyBytes_Size(result), 5);
935 EXPECT_STREQ(PyBytes_AsString(result), "Hello");
936}
937
938} // namespace testing
939} // namespace py