this repo has no description
at trunk 939 lines 32 kB view raw
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