this repo has no description
at trunk 1525 lines 45 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "Python.h" 3#include "gtest/gtest.h" 4 5#include "capi-fixture.h" 6#include "capi-testing.h" 7 8namespace py { 9namespace testing { 10 11using ObjectExtensionApiTest = ExtensionApi; 12 13TEST_F(ObjectExtensionApiTest, PyNoneIdentityIsEqual) { 14 // Test Identitiy 15 PyObject* none1 = Py_None; 16 PyObject* none2 = Py_None; 17 EXPECT_EQ(none1, none2); 18} 19 20TEST_F(ObjectExtensionApiTest, PyNotImplementedIdentityIsEqual) { 21 // Test Identitiy 22 PyObject* not_impl1 = Py_NotImplemented; 23 PyObject* not_impl2 = Py_NotImplemented; 24 EXPECT_EQ(not_impl1, not_impl2); 25} 26 27TEST_F(ObjectExtensionApiTest, BytesWithNullReturnsBytes) { 28 PyObjectPtr result(PyObject_Bytes(nullptr)); 29 ASSERT_EQ(PyErr_Occurred(), nullptr); 30 EXPECT_STREQ(PyBytes_AsString(result), "<NULL>"); 31} 32 33TEST_F(ObjectExtensionApiTest, BytesWithBytesReturnsSameObject) { 34 PyObjectPtr bytes(PyBytes_FromString("hello")); 35 PyObjectPtr result(PyObject_Bytes(bytes)); 36 ASSERT_EQ(PyErr_Occurred(), nullptr); 37 EXPECT_EQ(result, bytes); 38} 39 40TEST_F(ObjectExtensionApiTest, BytesWithBadDunderBytesRaisesTypeError) { 41 PyRun_SimpleString(R"( 42class Foo: 43 def __bytes__(self): 44 return 1 45obj = Foo() 46)"); 47 PyObjectPtr obj(mainModuleGet("obj")); 48 ASSERT_EQ(PyObject_Bytes(obj), nullptr); 49 ASSERT_NE(PyErr_Occurred(), nullptr); 50 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 51} 52 53TEST_F(ObjectExtensionApiTest, BytesWithDunderBytesReturnsBytes) { 54 PyRun_SimpleString(R"( 55class Foo: 56 def __bytes__(self): 57 return b'123' 58obj = Foo() 59)"); 60 PyObjectPtr obj(mainModuleGet("obj")); 61 PyObjectPtr result(PyObject_Bytes(obj)); 62 ASSERT_EQ(PyErr_Occurred(), nullptr); 63 EXPECT_STREQ(PyBytes_AsString(result), "123"); 64} 65 66TEST_F(ObjectExtensionApiTest, BytesWithDunderBytesErrorRaisesValueError) { 67 PyRun_SimpleString(R"( 68class Foo: 69 def __bytes__(self): 70 raise ValueError 71obj = Foo() 72)"); 73 PyObjectPtr obj(mainModuleGet("obj")); 74 ASSERT_EQ(PyObject_Bytes(obj), nullptr); 75 ASSERT_NE(PyErr_Occurred(), nullptr); 76 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError)); 77} 78 79TEST_F(ObjectExtensionApiTest, BytesWithListOfByteReturnsBytes) { 80 PyObjectPtr list(PyList_New(2)); 81 ASSERT_EQ(PyList_SetItem(list, 0, PyLong_FromLong('h')), 0); 82 ASSERT_EQ(PyList_SetItem(list, 1, PyLong_FromLong('i')), 0); 83 PyObjectPtr result(PyObject_Bytes(list)); 84 ASSERT_EQ(PyErr_Occurred(), nullptr); 85 EXPECT_STREQ(PyBytes_AsString(result), "hi"); 86} 87 88TEST_F(ObjectExtensionApiTest, BytesWithTupleOfByteReturnsBytes) { 89 PyObjectPtr tuple(PyTuple_New(2)); 90 ASSERT_EQ(PyTuple_SetItem(tuple, 0, PyLong_FromLong('h')), 0); 91 ASSERT_EQ(PyTuple_SetItem(tuple, 1, PyLong_FromLong('i')), 0); 92 PyObjectPtr result(PyObject_Bytes(tuple)); 93 ASSERT_EQ(PyErr_Occurred(), nullptr); 94 EXPECT_STREQ(PyBytes_AsString(result), "hi"); 95} 96 97TEST_F(ObjectExtensionApiTest, BytesWithStringRaisesTypeError) { 98 PyObjectPtr str(PyUnicode_FromString("hello")); 99 EXPECT_EQ(PyObject_Bytes(str), nullptr); 100 ASSERT_NE(PyErr_Occurred(), nullptr); 101 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 102} 103 104TEST_F(ObjectExtensionApiTest, CallableCheckWithNullReturnsZero) { 105 EXPECT_EQ(PyCallable_Check(nullptr), 0); 106 EXPECT_EQ(PyErr_Occurred(), nullptr); 107} 108 109TEST_F(ObjectExtensionApiTest, CallableCheckWithNoneDunderCallReturnsOne) { 110 PyRun_SimpleString(R"( 111class C: 112 __call__ = None 113c = C() 114)"); 115 PyObjectPtr c(mainModuleGet("c")); 116 EXPECT_EQ(PyCallable_Check(c), 1); 117 EXPECT_EQ(PyErr_Occurred(), nullptr); 118} 119 120TEST_F(ObjectExtensionApiTest, 121 CallableCheckWithNonCallableDunderCallReturnsOne) { 122 PyRun_SimpleString(R"( 123class C: 124 __call__ = 5 125c = C() 126)"); 127 PyObjectPtr c(mainModuleGet("c")); 128 EXPECT_EQ(PyCallable_Check(c), 1); 129 EXPECT_EQ(PyErr_Occurred(), nullptr); 130} 131 132TEST_F(ObjectExtensionApiTest, DelAttrStringRemovesAttribute) { 133 PyRun_SimpleString(R"( 134class C: 135 pass 136obj = C() 137obj.a = 42 138obj.b = 13 139)"); 140 PyObjectPtr obj(mainModuleGet("obj")); 141 ASSERT_TRUE(PyObject_HasAttrString(obj, "a")); 142 ASSERT_TRUE(PyObject_HasAttrString(obj, "b")); 143 EXPECT_EQ(PyObject_DelAttrString(obj, "a"), 0); 144 EXPECT_FALSE(PyObject_HasAttrString(obj, "a")); 145 EXPECT_TRUE(PyObject_HasAttrString(obj, "b")); 146} 147 148TEST_F(ObjectExtensionApiTest, DelAttrRemovesAttribute) { 149 PyRun_SimpleString(R"( 150class C: 151 pass 152obj = C() 153obj.a = 42 154obj.b = 13 155)"); 156 PyObjectPtr obj(mainModuleGet("obj")); 157 ASSERT_TRUE(PyObject_HasAttrString(obj, "a")); 158 ASSERT_TRUE(PyObject_HasAttrString(obj, "b")); 159 PyObjectPtr name(PyUnicode_FromString("a")); 160 EXPECT_EQ(PyObject_DelAttr(obj, name), 0); 161 EXPECT_FALSE(PyObject_HasAttrString(obj, "a")); 162 EXPECT_TRUE(PyObject_HasAttrString(obj, "b")); 163} 164 165TEST_F(ObjectExtensionApiTest, DelAttrRaisesAttributeError) { 166 PyObjectPtr obj(borrow(Py_None)); 167 EXPECT_EQ(PyObject_DelAttrString(obj, "does_not_exist"), -1); 168 EXPECT_NE(PyErr_Occurred(), nullptr); 169 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError)); 170} 171 172TEST_F(ObjectExtensionApiTest, LookupAttrWithNonStrNameRaisesTypeError) { 173 PyObjectPtr obj(borrow(Py_None)); 174 PyObjectPtr name(borrow(Py_None)); 175 PyObject* result = name.get(); // some non-NULL value 176 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), -1); 177 ASSERT_NE(PyErr_Occurred(), nullptr); 178 EXPECT_EQ(result, nullptr); 179 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 180} 181 182TEST_F(ObjectExtensionApiTest, LookupAttrWithExtantAttrReturnsOne) { 183 PyRun_SimpleString(R"( 184class C: 185 pass 186obj = C() 187obj.a = 42 188)"); 189 PyObjectPtr obj(mainModuleGet("obj")); 190 PyObjectPtr name(PyUnicode_FromString("a")); 191 ASSERT_TRUE(PyObject_HasAttr(obj, name)); 192 PyObject* result = nullptr; 193 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 1); 194 EXPECT_EQ(PyErr_Occurred(), nullptr); 195 ASSERT_NE(result, nullptr); 196 EXPECT_EQ(PyLong_AsLong(result), 42); 197 Py_DECREF(result); 198} 199 200TEST_F(ObjectExtensionApiTest, LookupAttrWithNonexistentAttrReturnsZero) { 201 PyObjectPtr obj(borrow(Py_None)); 202 PyObjectPtr name(PyUnicode_FromString("a")); 203 ASSERT_FALSE(PyObject_HasAttr(obj, name)); 204 PyObject* result = name.get(); // some non-NULL value 205 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 0); 206 EXPECT_EQ(PyErr_Occurred(), nullptr); 207 EXPECT_EQ(result, nullptr); 208} 209 210TEST_F(ObjectExtensionApiTest, 211 LookupAttrWithSuccessfulDunderGetAttributeReturnsOne) { 212 PyRun_SimpleString(R"( 213class C: 214 def __getattribute__(self, key): 215 return 42 216obj = C() 217)"); 218 PyObjectPtr obj(mainModuleGet("obj")); 219 PyObjectPtr name(PyUnicode_FromString("a")); 220 PyObject* result = nullptr; 221 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 1); 222 EXPECT_EQ(PyErr_Occurred(), nullptr); 223 ASSERT_NE(result, nullptr); 224 EXPECT_EQ(PyLong_AsLong(result), 42); 225 Py_DECREF(result); 226} 227 228TEST_F(ObjectExtensionApiTest, 229 LookupAttrWithRaisingDunderGetAttributeReturnsNegativeOne) { 230 PyRun_SimpleString(R"( 231class C: 232 def __getattribute__(self, key): 233 raise TypeError("foo") 234obj = C() 235)"); 236 PyObjectPtr obj(mainModuleGet("obj")); 237 PyObjectPtr name(PyUnicode_FromString("a")); 238 PyObject* result = name.get(); // some non-NULL value 239 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), -1); 240 ASSERT_NE(PyErr_Occurred(), nullptr); 241 EXPECT_EQ(result, nullptr); 242 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 243} 244 245TEST_F(ObjectExtensionApiTest, 246 LookupAttrWithAttributeErrorRaisingDunderGetAttributeReturnsZero) { 247 PyRun_SimpleString(R"( 248class C: 249 def __getattribute__(self, key): 250 raise AttributeError("foo") 251obj = C() 252)"); 253 PyObjectPtr obj(mainModuleGet("obj")); 254 PyObjectPtr name(PyUnicode_FromString("a")); 255 PyObject* result = name.get(); // some non-NULL value 256 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 0); 257 EXPECT_EQ(PyErr_Occurred(), nullptr); 258 EXPECT_EQ(result, nullptr); 259} 260 261TEST_F(ObjectExtensionApiTest, 262 LookupAttrWithSuccessfulDunderGetAttrReturnsOne) { 263 PyRun_SimpleString(R"( 264class C: 265 def __getattr__(self, key): 266 return 42 267obj = C() 268)"); 269 PyObjectPtr obj(mainModuleGet("obj")); 270 PyObjectPtr name(PyUnicode_FromString("a")); 271 PyObject* result = nullptr; 272 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 1); 273 EXPECT_EQ(PyErr_Occurred(), nullptr); 274 ASSERT_NE(result, nullptr); 275 EXPECT_EQ(PyLong_AsLong(result), 42); 276 Py_DECREF(result); 277} 278 279TEST_F(ObjectExtensionApiTest, 280 LookupAttrWithRaisingDunderGetAttrReturnsNegativeOne) { 281 PyRun_SimpleString(R"( 282class C: 283 def __getattr__(self, key): 284 raise TypeError("foo") 285obj = C() 286)"); 287 PyObjectPtr obj(mainModuleGet("obj")); 288 PyObjectPtr name(PyUnicode_FromString("a")); 289 PyObject* result = name.get(); // some non-NULL value 290 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), -1); 291 ASSERT_NE(PyErr_Occurred(), nullptr); 292 EXPECT_EQ(result, nullptr); 293 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 294} 295 296TEST_F(ObjectExtensionApiTest, 297 LookupAttrWithAttributeErrorRaisingDunderGetAttrReturnsZero) { 298 PyRun_SimpleString(R"( 299class C: 300 def __getattr__(self, key): 301 raise AttributeError("foo") 302obj = C() 303)"); 304 PyObjectPtr obj(mainModuleGet("obj")); 305 PyObjectPtr name(PyUnicode_FromString("a")); 306 PyObject* result = name.get(); // some non-NULL value 307 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 0); 308 EXPECT_EQ(PyErr_Occurred(), nullptr); 309 EXPECT_EQ(result, nullptr); 310} 311 312TEST_F( 313 ObjectExtensionApiTest, 314 LookupAttrWithDunderGetAttributeAndDunderGetAttrCallsDunderGetAttribute) { 315 PyRun_SimpleString(R"( 316class C: 317 def __getattr__(self, key): 318 return 5 319 def __getattribute__(self, key): 320 return 10 321obj = C() 322)"); 323 PyObjectPtr obj(mainModuleGet("obj")); 324 PyObjectPtr name(PyUnicode_FromString("a")); 325 PyObject* result = nullptr; 326 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 1); 327 EXPECT_EQ(PyErr_Occurred(), nullptr); 328 ASSERT_NE(result, nullptr); 329 EXPECT_EQ(PyLong_AsLong(result), 10); 330 Py_DECREF(result); 331} 332 333TEST_F( 334 ObjectExtensionApiTest, 335 LookupAttrWithRaisingDunderGetAttributeAndDunderGetAttrCallsDunderGetAttr) { 336 PyRun_SimpleString(R"( 337class C: 338 def __getattr__(self, key): 339 return 5 340 def __getattribute__(self, key): 341 raise AttributeError("foo") 342obj = C() 343)"); 344 PyObjectPtr obj(mainModuleGet("obj")); 345 PyObjectPtr name(PyUnicode_FromString("a")); 346 PyObject* result = nullptr; 347 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), 1); 348 EXPECT_EQ(PyErr_Occurred(), nullptr); 349 ASSERT_NE(result, nullptr); 350 EXPECT_EQ(PyLong_AsLong(result), 5); 351 Py_DECREF(result); 352} 353 354TEST_F(ObjectExtensionApiTest, 355 LookupAttrWithRaisingDescrAttrReturnsNegativeOne) { 356 PyRun_SimpleString(R"( 357class Desc: 358 def __get__(self, instance, owner): 359 raise TypeError("foo") 360 361class C: 362 a = Desc() 363 364obj = C() 365)"); 366 PyObjectPtr obj(mainModuleGet("obj")); 367 PyObjectPtr name(PyUnicode_FromString("a")); 368 PyObject* result = name.get(); // some non-NULL value 369 EXPECT_EQ(_PyObject_LookupAttr(obj, name, &result), -1); 370 ASSERT_NE(PyErr_Occurred(), nullptr); 371 EXPECT_EQ(result, nullptr); 372 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 373} 374 375TEST_F(ObjectExtensionApiTest, PySizeReturnsLvalue) { 376 PyType_Slot slots[] = { 377 {0, nullptr}, 378 }; 379 static PyType_Spec spec; 380 spec = { 381 "foo.Bar", sizeof(PyObject) + 10, 5, Py_TPFLAGS_DEFAULT, slots, 382 }; 383 PyObjectPtr type(PyType_FromSpec(&spec)); 384 ASSERT_NE(type, nullptr); 385 ASSERT_TRUE(PyType_CheckExact(type)); 386 387 PyObjectPtr result( 388 PyType_GenericAlloc(reinterpret_cast<PyTypeObject*>(type.get()), 5)); 389 EXPECT_EQ(Py_SIZE(result.get()), 5); 390 391 Py_SIZE(result.get()) = 4; 392 EXPECT_EQ(Py_SIZE(result.get()), 4); 393} 394 395TEST_F(ObjectExtensionApiTest, SetAttrWithInvalidTypeReturnsNegative) { 396 PyObjectPtr key(PyUnicode_FromString("a_key")); 397 PyObjectPtr value(PyLong_FromLong(5)); 398 EXPECT_EQ(PyObject_SetAttr(Py_None, key, value), -1); 399} 400 401TEST_F(ObjectExtensionApiTest, SetAttrWithInvalidKeyReturnsNegative) { 402 static PyModuleDef def; 403 def = { 404 PyModuleDef_HEAD_INIT, 405 "test", 406 }; 407 PyObjectPtr module(PyModule_Create(&def)); 408 PyObjectPtr value(PyLong_FromLong(5)); 409 EXPECT_EQ(PyObject_SetAttr(module, Py_None, value), -1); 410} 411 412TEST_F(ObjectExtensionApiTest, SetAttrReturnsZero) { 413 static PyModuleDef def; 414 def = { 415 PyModuleDef_HEAD_INIT, 416 "test", 417 }; 418 PyObjectPtr module(PyModule_Create(&def)); 419 PyObjectPtr key(PyUnicode_FromString("a_key")); 420 PyObjectPtr value(PyLong_FromLong(5)); 421 EXPECT_EQ(PyObject_SetAttr(module, key, value), 0); 422} 423 424TEST_F(ObjectExtensionApiTest, SetAttrStringWithNullRemovesAttribute) { 425 PyRun_SimpleString(R"( 426class C: 427 pass 428obj = C() 429obj.a = 42 430obj.b = 13 431)"); 432 PyObjectPtr obj(mainModuleGet("obj")); 433 ASSERT_TRUE(PyObject_HasAttrString(obj, "a")); 434 ASSERT_TRUE(PyObject_HasAttrString(obj, "b")); 435 EXPECT_EQ(PyObject_SetAttrString(obj, "a", nullptr), 0); 436 EXPECT_FALSE(PyObject_HasAttrString(obj, "a")); 437 EXPECT_TRUE(PyObject_HasAttrString(obj, "b")); 438} 439 440TEST_F(ObjectExtensionApiTest, SetAttrWithNullRemovesAttribute) { 441 PyRun_SimpleString(R"( 442class C: 443 pass 444obj = C() 445obj.a = 42 446obj.b = 13 447)"); 448 PyObjectPtr obj(mainModuleGet("obj")); 449 ASSERT_TRUE(PyObject_HasAttrString(obj, "a")); 450 ASSERT_TRUE(PyObject_HasAttrString(obj, "b")); 451 PyObjectPtr name(PyUnicode_FromString("a")); 452 EXPECT_EQ(PyObject_SetAttr(obj, name, nullptr), 0); 453 EXPECT_FALSE(PyObject_HasAttrString(obj, "a")); 454 EXPECT_TRUE(PyObject_HasAttrString(obj, "b")); 455} 456 457TEST_F(ObjectExtensionApiTest, GetAttrWithNoneExistingKeyReturnsNull) { 458 static PyModuleDef def; 459 def = { 460 PyModuleDef_HEAD_INIT, 461 "test", 462 }; 463 PyObjectPtr module(PyModule_Create(&def)); 464 465 PyObjectPtr key(PyUnicode_FromString("a_key")); 466 EXPECT_EQ(PyObject_GetAttr(module, key), nullptr); 467} 468 469TEST_F(ObjectExtensionApiTest, GetAttrWithInvalidTypeReturnsNull) { 470 static PyModuleDef def; 471 def = { 472 PyModuleDef_HEAD_INIT, 473 "test", 474 }; 475 int expected_int = 5; 476 PyObjectPtr module(PyModule_Create(&def)); 477 PyObjectPtr key(PyUnicode_FromString("a_key")); 478 PyObjectPtr value(PyLong_FromLong(expected_int)); 479 ASSERT_EQ(PyObject_SetAttr(module, key, value), 0); 480 481 EXPECT_EQ(PyObject_GetAttr(Py_None, key), nullptr); 482} 483 484TEST_F(ObjectExtensionApiTest, GetAttrWithInvalidKeyReturnsNull) { 485 static PyModuleDef def; 486 def = { 487 PyModuleDef_HEAD_INIT, 488 "test", 489 }; 490 int expected_int = 5; 491 PyObjectPtr module(PyModule_Create(&def)); 492 PyObjectPtr key(PyUnicode_FromString("a_key")); 493 PyObjectPtr value(PyLong_FromLong(expected_int)); 494 ASSERT_EQ(PyObject_SetAttr(module, key, value), 0); 495 496 EXPECT_EQ(PyObject_GetAttr(module, Py_None), nullptr); 497} 498 499TEST_F(ObjectExtensionApiTest, GetAttrReturnsCorrectValue) { 500 static PyModuleDef def; 501 def = { 502 PyModuleDef_HEAD_INIT, 503 "test", 504 }; 505 int expected_int = 5; 506 PyObjectPtr module(PyModule_Create(&def)); 507 PyObjectPtr key(PyUnicode_FromString("a_key")); 508 PyObjectPtr value(PyLong_FromLong(expected_int)); 509 ASSERT_EQ(PyObject_SetAttr(module, key, value), 0); 510 511 PyObjectPtr dict_result(PyObject_GetAttr(module, key)); 512 ASSERT_NE(dict_result, nullptr); 513 EXPECT_EQ(PyLong_AsLong(dict_result), expected_int); 514} 515 516TEST_F(ObjectExtensionApiTest, GetAttrStringReturnsCorrectValue) { 517 static PyModuleDef def; 518 def = { 519 PyModuleDef_HEAD_INIT, 520 "test", 521 }; 522 const char* key = "a_key"; 523 int expected_int = 5; 524 PyObjectPtr module(PyModule_Create(&def)); 525 PyObjectPtr value(PyLong_FromLong(expected_int)); 526 ASSERT_EQ(PyObject_SetAttrString(module, key, value), 0); 527 528 PyObjectPtr dict_result(PyObject_GetAttrString(module, key)); 529 ASSERT_NE(dict_result, nullptr); 530 EXPECT_EQ(PyLong_AsLong(dict_result), expected_int); 531} 532 533TEST_F(ObjectExtensionApiTest, HasAttrWithImmediateWithAttributeReturnsTrue) { 534 PyObjectPtr num(PyLong_FromLong(6)); 535 PyObjectPtr name(PyUnicode_FromString("__int__")); 536 EXPECT_TRUE(PyObject_HasAttr(num, name)); 537} 538 539TEST_F(ObjectExtensionApiTest, 540 HasAttrStringWithImmediateWithoutAttributeReturnsFalse) { 541 PyObjectPtr str(PyUnicode_FromString("")); 542 EXPECT_FALSE(PyObject_HasAttrString(str, "foo")); 543} 544 545TEST_F(ObjectExtensionApiTest, HasAttrWithNonStringAttrReturnsFalse) { 546 PyObjectPtr set(PySet_New(nullptr)); 547 PyObjectPtr num(PyLong_FromLong(1)); 548 EXPECT_FALSE(PyObject_HasAttr(set, num)); 549 ASSERT_EQ(PyErr_Occurred(), nullptr); 550} 551 552TEST_F(ObjectExtensionApiTest, HasAttrWithoutAttrReturnsFalse) { 553 static PyModuleDef def; 554 def = { 555 PyModuleDef_HEAD_INIT, 556 "test", 557 }; 558 PyObjectPtr module(PyModule_Create(&def)); 559 PyObjectPtr name(PyUnicode_FromString("foo")); 560 EXPECT_FALSE(PyObject_HasAttr(module, name)); 561} 562 563TEST_F(ObjectExtensionApiTest, HasAttrStringWithoutAttrReturnsFalse) { 564 static PyModuleDef def; 565 def = { 566 PyModuleDef_HEAD_INIT, 567 "test", 568 }; 569 PyObjectPtr module(PyModule_Create(&def)); 570 EXPECT_FALSE(PyObject_HasAttrString(module, "foo")); 571} 572 573TEST_F(ObjectExtensionApiTest, HasAttrWithAttrReturnsTrue) { 574 static PyModuleDef def; 575 def = { 576 PyModuleDef_HEAD_INIT, 577 "test", 578 }; 579 PyObjectPtr module(PyModule_Create(&def)); 580 PyObjectPtr name(PyUnicode_FromString("foo")); 581 PyObjectPtr val(PyLong_FromLong(2)); 582 ASSERT_EQ(PyObject_SetAttr(module, name, val), 0); 583 EXPECT_TRUE(PyObject_HasAttr(module, name)); 584} 585 586TEST_F(ObjectExtensionApiTest, HasAttrStringWithAttrReturnsTrue) { 587 static PyModuleDef def; 588 def = { 589 PyModuleDef_HEAD_INIT, 590 "test", 591 }; 592 PyObjectPtr module(PyModule_Create(&def)); 593 PyObjectPtr name(PyUnicode_FromString("foo")); 594 PyObjectPtr val(PyLong_FromLong(2)); 595 ASSERT_EQ(PyObject_SetAttr(module, name, val), 0); 596 EXPECT_TRUE(PyObject_HasAttrString(module, "foo")); 597} 598 599TEST_F(ObjectExtensionApiTest, PrintWithNullObjPrintsNil) { 600 CaptureStdStreams streams; 601 int result = PyObject_Print(nullptr, stdout, 0); 602 EXPECT_EQ(result, 0); 603 EXPECT_EQ(streams.out(), "<nil>"); 604} 605 606TEST_F(ObjectExtensionApiTest, PrintWithZeroFlagsCallsDunderRepr) { 607 ASSERT_EQ(PyRun_SimpleString(R"( 608class C: 609 def __repr__(self): 610 return "foo" 611 def __str__(self): 612 return "bar" 613obj = C() 614 )"), 615 0); 616 CaptureStdStreams streams; 617 PyObjectPtr obj(mainModuleGet("obj")); 618 int result = PyObject_Print(obj, stdout, 0); 619 EXPECT_EQ(result, 0); 620 EXPECT_EQ(streams.out(), "foo"); 621} 622 623TEST_F(ObjectExtensionApiTest, PrintWithRawFlagsCallsDunderStr) { 624 ASSERT_EQ(PyRun_SimpleString(R"( 625class C: 626 def __repr__(self): 627 return "foo" 628 def __str__(self): 629 return "bar" 630obj = C() 631 )"), 632 0); 633 CaptureStdStreams streams; 634 PyObjectPtr obj(mainModuleGet("obj")); 635 int result = PyObject_Print(obj, stdout, Py_PRINT_RAW); 636 EXPECT_EQ(result, 0); 637 EXPECT_EQ(streams.out(), "bar"); 638} 639 640TEST_F(ObjectExtensionApiTest, PrintReplacesBackslashes) { 641 ASSERT_EQ(PyRun_SimpleString(R"( 642class C: 643 def __repr__(self): 644 return r"foo\bar" 645obj = C() 646 )"), 647 0); 648 CaptureStdStreams streams; 649 PyObjectPtr obj(mainModuleGet("obj")); 650 int result = PyObject_Print(obj, stdout, 0); 651 EXPECT_EQ(result, 0); 652 EXPECT_EQ(streams.out(), "foo\\bar"); 653} 654 655TEST_F(ObjectExtensionApiTest, RefCountDecreaseDeallocsHandle) { 656 long value = 10; 657 PyObject* o = PyLong_FromLong(value); 658 Py_DECREF(o); 659} 660 661TEST_F(ObjectExtensionApiTest, IncrementDecrementRefCount) { 662 PyObject* o = PyTuple_New(1); 663 long refcnt = Py_REFCNT(o); 664 EXPECT_GE(Py_REFCNT(o), 1); 665 Py_INCREF(o); 666 EXPECT_EQ(Py_REFCNT(o), refcnt + 1); 667 Py_DECREF(o); 668 EXPECT_EQ(Py_REFCNT(o), refcnt); 669 Py_DECREF(o); 670} 671 672TEST_F(ObjectExtensionApiTest, IncrementDecrementRefCountWithPyObjectPtr) { 673 PyObject* o = PyTuple_New(1); 674 long refcnt = Py_REFCNT(o); 675 { 676 Py_INCREF(o); 677 EXPECT_EQ(Py_REFCNT(o), refcnt + 1); 678 testing::PyObjectPtr h(o); 679 static_cast<void>(h); 680 } 681 EXPECT_EQ(Py_REFCNT(o), refcnt); 682 { 683 Py_INCREF(o); 684 EXPECT_EQ(Py_REFCNT(o), refcnt + 1); 685 testing::PyObjectPtr h(o); 686 h = nullptr; 687 static_cast<void>(h); 688 EXPECT_EQ(Py_REFCNT(o), refcnt); 689 } 690 Py_DECREF(o); 691} 692 693TEST_F(ObjectExtensionApiTest, CallFinalizerFromDeallocWithNonZeroRefcntDies) { 694 PyObject* obj = Py_None; 695 Py_INCREF(obj); // definitely has a non-zero refcount 696 EXPECT_DEATH(PyObject_CallFinalizerFromDealloc(obj), 697 "PyObject_CallFinalizerFromDealloc called on object with a " 698 "non-zero refcount"); 699} 700 701TEST_F(ObjectExtensionApiTest, 702 CallFinalizerFromDeallocWithoutTpFinalizeFlagCallsTpFinalize) { 703 static bool dealloc_called; 704 static bool finalizer_called; 705 dealloc_called = false; 706 finalizer_called = false; 707 destructor dealloc_func = [](PyObject* self) { 708 dealloc_called = true; 709 if (PyObject_CallFinalizerFromDealloc(self) < 0) return; 710 PyTypeObject* type = Py_TYPE(self); 711 PyObject_Del(self); 712 Py_DECREF(type); 713 }; 714 destructor finalizer_func = [](PyObject*) { finalizer_called = true; }; 715 PyType_Slot slots[] = { 716 {Py_tp_dealloc, reinterpret_cast<void*>(dealloc_func)}, 717 {Py_tp_finalize, reinterpret_cast<void*>(finalizer_func)}, 718 {0, nullptr}, 719 }; 720 static PyType_Spec spec; 721 spec = { 722 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots, 723 }; 724 PyObjectPtr type(PyType_FromSpec(&spec)); 725 ASSERT_NE(type, nullptr); 726 allocfunc func = reinterpret_cast<allocfunc>( 727 PyType_GetSlot(type.asTypeObject(), Py_tp_alloc)); 728 ASSERT_NE(func, nullptr); 729 PyObject* obj = (*func)(type.asTypeObject(), 0); 730 ASSERT_NE(obj, nullptr); 731 EXPECT_GE(Py_REFCNT(obj), 1); 732 Py_DECREF(obj); // Drop the reference to it 733 // Trigger a GC. PyObject_CallFinalizerFromDealloc is called during GC in 734 // Pyro and immmediately in the decref in CPython. 735 collectGarbage(); 736 EXPECT_TRUE(dealloc_called); 737 EXPECT_TRUE(finalizer_called); 738} 739 740TEST_F(ObjectExtensionApiTest, 741 CallFinalizerFromDeallocWithTpFinalizeFlagCallsTpFinalize) { 742 static bool dealloc_called; 743 static bool finalizer_called; 744 dealloc_called = false; 745 finalizer_called = false; 746 destructor dealloc_func = [](PyObject* self) { 747 dealloc_called = true; 748 if (PyObject_CallFinalizerFromDealloc(self) < 0) return; 749 PyTypeObject* type = Py_TYPE(self); 750 PyObject_Del(self); 751 Py_DECREF(type); 752 }; 753 destructor finalizer_func = [](PyObject*) { finalizer_called = true; }; 754 PyType_Slot slots[] = { 755 {Py_tp_dealloc, reinterpret_cast<void*>(dealloc_func)}, 756 {Py_tp_finalize, reinterpret_cast<void*>(finalizer_func)}, 757 {0, nullptr}, 758 }; 759 static PyType_Spec spec; 760 spec = { 761 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, slots, 762 }; 763 PyObjectPtr type(PyType_FromSpec(&spec)); 764 ASSERT_NE(type, nullptr); 765 allocfunc func = reinterpret_cast<allocfunc>( 766 PyType_GetSlot(type.asTypeObject(), Py_tp_alloc)); 767 ASSERT_NE(func, nullptr); 768 PyObject* obj = (*func)(type.asTypeObject(), 0); 769 ASSERT_NE(obj, nullptr); 770 EXPECT_GE(Py_REFCNT(obj), 1); 771 Py_DECREF(obj); // Drop the reference to it 772 // Trigger a GC. PyObject_CallFinalizerFromDealloc is called during GC in 773 // Pyro and immmediately in the decref in CPython. 774 collectGarbage(); 775 EXPECT_TRUE(dealloc_called); 776 EXPECT_TRUE(finalizer_called); 777} 778 779TEST_F( 780 ObjectExtensionApiTest, 781 CallFinalizerFromDeallocWithTpFinalizeResurrectingObjectDoesNotGCObject) { 782 static bool dealloc_called; 783 static bool finalizer_called; 784 dealloc_called = false; 785 finalizer_called = false; 786 destructor dealloc_func = [](PyObject* self) { 787 dealloc_called = true; 788 if (PyObject_CallFinalizerFromDealloc(self) < 0) return; 789 PyTypeObject* type = Py_TYPE(self); 790 PyObject_Del(self); 791 Py_DECREF(type); 792 }; 793 destructor finalizer_func = [](PyObject* self) { 794 finalizer_called = true; 795 Py_INCREF(self); 796 }; 797 PyType_Slot slots[] = { 798 {Py_tp_dealloc, reinterpret_cast<void*>(dealloc_func)}, 799 {Py_tp_finalize, reinterpret_cast<void*>(finalizer_func)}, 800 {0, nullptr}, 801 }; 802 static PyType_Spec spec; 803 spec = { 804 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, slots, 805 }; 806 PyObjectPtr type(PyType_FromSpec(&spec)); 807 ASSERT_NE(type, nullptr); 808 allocfunc func = reinterpret_cast<allocfunc>( 809 PyType_GetSlot(type.asTypeObject(), Py_tp_alloc)); 810 ASSERT_NE(func, nullptr); 811 PyObject* obj = (*func)(type.asTypeObject(), 0); 812 ASSERT_NE(obj, nullptr); 813 EXPECT_GE(Py_REFCNT(obj), 1); 814 Py_DECREF(obj); // Drop the reference to it 815 // Trigger a GC. PyObject_CallFinalizerFromDealloc is called during GC in 816 // Pyro and immmediately in the decref in CPython. 817 collectGarbage(); 818 EXPECT_TRUE(dealloc_called); 819 EXPECT_TRUE(finalizer_called); 820 EXPECT_GE(Py_REFCNT(obj), 1); 821} 822 823TEST_F(ObjectExtensionApiTest, PyDeallocCallsDeallocTypeSlot) { 824 static bool dealloc_called; 825 dealloc_called = false; 826 destructor dealloc_func = [](PyObject* self) { 827 dealloc_called = true; 828 PyTypeObject* type = Py_TYPE(self); 829 PyObject_Del(self); 830 Py_DECREF(type); 831 }; 832 PyType_Slot slots[] = { 833 {Py_tp_dealloc, reinterpret_cast<void*>(dealloc_func)}, 834 {0, nullptr}, 835 }; 836 static PyType_Spec spec; 837 spec = { 838 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, slots, 839 }; 840 PyObjectPtr type(PyType_FromSpec(&spec)); 841 ASSERT_NE(type, nullptr); 842 allocfunc func = reinterpret_cast<allocfunc>( 843 PyType_GetSlot(type.asTypeObject(), Py_tp_alloc)); 844 ASSERT_NE(func, nullptr); 845 PyObject* obj = (*func)(type.asTypeObject(), 0); 846 ASSERT_NE(obj, nullptr); 847 EXPECT_GE(Py_REFCNT(obj), 1); 848 _Py_Dealloc(obj); 849 EXPECT_TRUE(dealloc_called); 850} 851 852TEST_F(ObjectExtensionApiTest, GenericGetAttrFindsCorrectlySetValue) { 853 ASSERT_EQ(PyRun_SimpleString(R"( 854class C: pass 855i = C() 856)"), 857 0); 858 859 PyObjectPtr i(mainModuleGet("i")); 860 ASSERT_NE(i, nullptr); 861 PyObjectPtr key(PyUnicode_FromString("key")); 862 PyObjectPtr value(PyUnicode_FromString("value")); 863 EXPECT_EQ(PyObject_GenericSetAttr(i, key, value), 0); 864 PyObjectPtr get_val(PyObject_GenericGetAttr(i, key)); 865 EXPECT_TRUE(isUnicodeEqualsCStr(get_val, "value")); 866} 867 868TEST_F(ObjectExtensionApiTest, GenericSetAttrWithSealedTypeReturnsNegOne) { 869 ASSERT_EQ(PyRun_SimpleString(R"( 870i = 3 871)"), 872 0); 873 874 PyObjectPtr i(mainModuleGet("i")); 875 ASSERT_NE(i, nullptr); 876 PyObjectPtr key(PyUnicode_FromString("key")); 877 PyObjectPtr value(PyUnicode_FromString("value")); 878 EXPECT_EQ(PyObject_GenericSetAttr(i, key, value), -1); 879 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError)); 880} 881 882TEST_F(ObjectExtensionApiTest, GetAttrIncrementsReferenceCount) { 883 static PyModuleDef def; 884 def = { 885 PyModuleDef_HEAD_INIT, 886 "test", 887 }; 888 PyObjectPtr module(PyModule_Create(&def)); 889 PyObjectPtr key(PyUnicode_FromString("test")); 890 PyObject* value = PyTuple_New(1); 891 ASSERT_EQ(PyObject_SetAttr(module, key, value), 0); 892 893 long refcnt = Py_REFCNT(value); 894 PyObject* result = PyObject_GetAttr(module, key); 895 EXPECT_EQ(Py_REFCNT(result), refcnt + 1); 896 Py_DECREF(result); 897 result = PyObject_GetAttr(module, key); 898 EXPECT_EQ(result, value); 899 EXPECT_EQ(Py_REFCNT(result), refcnt + 1); 900 Py_DECREF(result); 901 Py_DECREF(result); 902} 903 904TEST_F(ObjectExtensionApiTest, ReprOnNullReturnsSpecialNullString) { 905 PyObjectPtr repr(PyObject_Repr(nullptr)); 906 ASSERT_EQ(PyErr_Occurred(), nullptr); 907 EXPECT_TRUE(isUnicodeEqualsCStr(repr, "<NULL>")); 908} 909 910TEST_F(ObjectExtensionApiTest, ReprWithObjectWithBadDunderReprRaisesTypeError) { 911 PyRun_SimpleString(R"( 912class C: 913 __repr__ = None 914c = C() 915)"); 916 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 917 EXPECT_EQ(PyObject_Repr(pyc), nullptr); 918 ASSERT_NE(PyErr_Occurred(), nullptr); 919 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 920} 921 922TEST_F(ObjectExtensionApiTest, ReprIsCorrectForObjectWithDunderRepr) { 923 PyRun_SimpleString(R"( 924class C: 925 def __repr__(self): 926 return "bongo" 927c = C() 928)"); 929 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 930 PyObjectPtr repr(PyObject_Repr(pyc)); 931 ASSERT_EQ(PyErr_Occurred(), nullptr); 932 EXPECT_TRUE(isUnicodeEqualsCStr(repr, "bongo")); 933} 934 935TEST_F(ObjectExtensionApiTest, 936 ReprWithRecursiveObjectDoesNotInfinitelyRecurse) { 937 PyRun_SimpleString(R"( 938a = [] 939a.append(a) 940)"); 941 PyObjectPtr a(PyObject_GetAttrString(PyImport_AddModule("__main__"), "a")); 942 PyObjectPtr repr(PyObject_Repr(a)); 943 ASSERT_EQ(PyErr_Occurred(), nullptr); 944 EXPECT_TRUE(isUnicodeEqualsCStr(repr, "[[...]]")); 945} 946 947TEST_F(ObjectExtensionApiTest, StrOnNullReturnsSpecialNullString) { 948 PyObjectPtr str(PyObject_Str(nullptr)); 949 ASSERT_EQ(PyErr_Occurred(), nullptr); 950 ASSERT_TRUE(isUnicodeEqualsCStr(str, "<NULL>")); 951} 952 953TEST_F(ObjectExtensionApiTest, StrCallsClassDunderReprWhenProvided) { 954 PyRun_SimpleString(R"( 955class C: 956 def __repr__(self): 957 return "bongo" 958c = C() 959)"); 960 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 961 PyObjectPtr str(PyObject_Str(pyc)); 962 ASSERT_EQ(PyErr_Occurred(), nullptr); 963 EXPECT_TRUE(isUnicodeEqualsCStr(str, "bongo")); 964} 965 966TEST_F(ObjectExtensionApiTest, StrWithObjectWithBadDunderStrRaisesTypeError) { 967 PyRun_SimpleString(R"( 968class C: 969 __str__ = None 970c = C() 971)"); 972 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 973 EXPECT_EQ(PyObject_Str(pyc), nullptr); 974 ASSERT_NE(PyErr_Occurred(), nullptr); 975 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 976} 977 978TEST_F(ObjectExtensionApiTest, StrCallsClassDunderStrWhenProvided) { 979 PyRun_SimpleString(R"( 980class C: 981 def __str__(self): 982 return "bongo" 983c = C() 984)"); 985 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 986 PyObjectPtr str(PyObject_Str(pyc)); 987 ASSERT_EQ(PyErr_Occurred(), nullptr); 988 EXPECT_TRUE(isUnicodeEqualsCStr(str, "bongo")); 989} 990 991TEST_F(ObjectExtensionApiTest, RichCompareWithNullLhsRaisesSystemError) { 992 ASSERT_EQ(PyObject_RichCompare(nullptr, Py_None, 0), nullptr); 993 ASSERT_NE(PyErr_Occurred(), nullptr); 994 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 995} 996 997TEST_F(ObjectExtensionApiTest, RichCompareWithNullRhsRaisesSystemError) { 998 ASSERT_EQ(PyObject_RichCompare(Py_None, nullptr, 0), nullptr); 999 ASSERT_NE(PyErr_Occurred(), nullptr); 1000 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 1001} 1002 1003TEST_F(ObjectExtensionApiTest, RichCompareWithSameType) { 1004 PyObjectPtr left(PyLong_FromLong(2)); 1005 PyObjectPtr right(PyLong_FromLong(3)); 1006 PyObjectPtr result(PyObject_RichCompare(left, right, Py_LT)); 1007 ASSERT_EQ(PyErr_Occurred(), nullptr); 1008 ASSERT_EQ(result, Py_True); 1009} 1010 1011TEST_F(ObjectExtensionApiTest, RichCompareNotComparableRaisesTypeError) { 1012 PyObjectPtr left(PyLong_FromLong(2)); 1013 PyObjectPtr right(PyUnicode_FromString("hello")); 1014 EXPECT_EQ(PyObject_RichCompare(left, right, Py_LT), nullptr); 1015 ASSERT_NE(PyErr_Occurred(), nullptr); 1016 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1017} 1018 1019TEST_F(ObjectExtensionApiTest, IsTrueReturnsTrueOnTrue) { 1020 EXPECT_EQ(PyObject_IsTrue(Py_True), 1); 1021 EXPECT_EQ(PyErr_Occurred(), nullptr); 1022} 1023 1024TEST_F(ObjectExtensionApiTest, IsTrueReturnsFalseOnFalse) { 1025 EXPECT_EQ(PyObject_IsTrue(Py_False), 0); 1026 EXPECT_EQ(PyErr_Occurred(), nullptr); 1027} 1028 1029TEST_F(ObjectExtensionApiTest, IsTrueReturnsFalseOnNone) { 1030 EXPECT_EQ(PyObject_IsTrue(Py_None), 0); 1031 EXPECT_EQ(PyErr_Occurred(), nullptr); 1032} 1033 1034TEST_F(ObjectExtensionApiTest, 1035 IsTrueWithObjectWithNonCallableDunderBoolRaisesTypeError) { 1036 PyRun_SimpleString(R"( 1037class C: 1038 __bool__ = 4 1039c = C() 1040)"); 1041 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1042 ASSERT_EQ(PyObject_IsTrue(pyc), -1); 1043 ASSERT_NE(PyErr_Occurred(), nullptr); 1044 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1045} 1046 1047TEST_F(ObjectExtensionApiTest, 1048 IsTrueWithObjectWithNonCallableDunderLenRaisesTypeError) { 1049 PyRun_SimpleString(R"( 1050class C: 1051 __len__ = 4 1052c = C() 1053)"); 1054 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1055 ASSERT_EQ(PyObject_IsTrue(pyc), -1); 1056 ASSERT_NE(PyErr_Occurred(), nullptr); 1057 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1058} 1059 1060TEST_F(ObjectExtensionApiTest, 1061 IsTrueWithObjectWithDunderBoolThatReturnsNonIntRaisesTypeError) { 1062 PyRun_SimpleString(R"( 1063class C: 1064 def __bool__(self): 1065 return "bongo" 1066c = C() 1067)"); 1068 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1069 ASSERT_EQ(PyObject_IsTrue(pyc), -1); 1070 ASSERT_NE(PyErr_Occurred(), nullptr); 1071 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1072} 1073 1074TEST_F(ObjectExtensionApiTest, 1075 IsTrueWithDunderLenThatReturnsNonIntRaisesTypeError) { 1076 PyRun_SimpleString(R"( 1077class C: 1078 def __len__(self): 1079 return "bongo" 1080c = C() 1081)"); 1082 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1083 ASSERT_EQ(PyObject_IsTrue(pyc), -1); 1084 ASSERT_NE(PyErr_Occurred(), nullptr); 1085 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1086} 1087 1088TEST_F(ObjectExtensionApiTest, IsTrueWithEmptyListReturnsFalse) { 1089 PyObjectPtr empty_list(PyList_New(0)); 1090 ASSERT_EQ(PyObject_IsTrue(empty_list), 0); 1091 EXPECT_EQ(PyErr_Occurred(), nullptr); 1092} 1093 1094TEST_F(ObjectExtensionApiTest, IsTrueWithNonEmptyListReturnsTrue) { 1095 PyObjectPtr list(PyList_New(0)); 1096 PyList_Append(list, Py_None); 1097 1098 ASSERT_EQ(PyObject_IsTrue(list), 1); 1099 EXPECT_EQ(PyErr_Occurred(), nullptr); 1100} 1101 1102TEST_F(ObjectExtensionApiTest, 1103 IsTrueWithObjectWithDunderLenReturningNegativeOneRaisesValueError) { 1104 PyRun_SimpleString(R"( 1105class C: 1106 def __len__(self): 1107 return -1 1108c = C() 1109)"); 1110 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1111 ASSERT_EQ(PyObject_IsTrue(pyc), -1); 1112 ASSERT_NE(PyErr_Occurred(), nullptr); 1113 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError)); 1114} 1115 1116TEST_F(ObjectExtensionApiTest, ClearWithNullDoesNotRaise) { 1117 PyObject* null = nullptr; 1118 Py_CLEAR(null); 1119 ASSERT_EQ(PyErr_Occurred(), nullptr); 1120 EXPECT_EQ(null, nullptr); 1121} 1122 1123TEST_F(ObjectExtensionApiTest, ClearWithObjectSetsNull) { 1124 PyObject* num = PyLong_FromLong(1); 1125 Py_CLEAR(num); 1126 ASSERT_EQ(PyErr_Occurred(), nullptr); 1127 EXPECT_EQ(num, nullptr); 1128} 1129 1130TEST_F(ObjectExtensionApiTest, ClearWithObjectDecrefsObject) { 1131 PyObject* original = PyTuple_New(1); 1132 PyObject* num = original; 1133 Py_ssize_t original_count = Py_REFCNT(original); 1134 Py_CLEAR(num); 1135 ASSERT_EQ(PyErr_Occurred(), nullptr); 1136 EXPECT_EQ(num, nullptr); 1137 EXPECT_LT(Py_REFCNT(original), original_count); 1138} 1139 1140TEST_F(ObjectExtensionApiTest, ASCIIOnNullReturnsSpecialNullString) { 1141 PyObjectPtr ascii(PyObject_ASCII(nullptr)); 1142 ASSERT_EQ(PyErr_Occurred(), nullptr); 1143 EXPECT_TRUE(isUnicodeEqualsCStr(ascii, "<NULL>")); 1144} 1145 1146TEST_F(ObjectExtensionApiTest, 1147 ASCIIWithObjectWithBadDunderReprRaisesTypeError) { 1148 PyRun_SimpleString(R"( 1149class C: 1150 __repr__ = None 1151c = C() 1152)"); 1153 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1154 EXPECT_EQ(PyObject_ASCII(pyc), nullptr); 1155 ASSERT_NE(PyErr_Occurred(), nullptr); 1156 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1157} 1158 1159TEST_F(ObjectExtensionApiTest, ASCIIcallsDunderRepr) { 1160 PyRun_SimpleString(R"( 1161class C: 1162 def __repr__(self): 1163 return "bongo" 1164c = C() 1165)"); 1166 PyObjectPtr pyc(PyObject_GetAttrString(PyImport_AddModule("__main__"), "c")); 1167 PyObjectPtr ascii(PyObject_ASCII(pyc)); 1168 ASSERT_EQ(PyErr_Occurred(), nullptr); 1169 EXPECT_TRUE(isUnicodeEqualsCStr(ascii, "bongo")); 1170} 1171 1172TEST_F(ObjectExtensionApiTest, SelfIterIncrementsRefcount) { 1173 PyObject* o = PyTuple_New(1); 1174 long refcnt = Py_REFCNT(o); 1175 EXPECT_GE(Py_REFCNT(o), 1); 1176 PyObject* o2 = PyObject_SelfIter(o); 1177 EXPECT_EQ(PyErr_Occurred(), nullptr); 1178 EXPECT_EQ(Py_REFCNT(o2), refcnt + 1); 1179 Py_DECREF(o); 1180 Py_DECREF(o); 1181} 1182 1183TEST_F(ObjectExtensionApiTest, NotWithTrueReturnsFalse) { 1184 EXPECT_EQ(PyObject_Not(Py_True), 0); 1185 EXPECT_EQ(PyErr_Occurred(), nullptr); 1186} 1187 1188TEST_F(ObjectExtensionApiTest, NotWithFalseReturnsTrue) { 1189 EXPECT_EQ(PyObject_Not(Py_False), 1); 1190 EXPECT_EQ(PyErr_Occurred(), nullptr); 1191} 1192 1193TEST_F(ObjectExtensionApiTest, NotWithNoneReturnsTrue) { 1194 EXPECT_EQ(PyObject_Not(Py_None), 1); 1195 EXPECT_EQ(PyErr_Occurred(), nullptr); 1196} 1197 1198TEST_F(ObjectExtensionApiTest, NotCallsDunderBool) { 1199 PyRun_SimpleString(R"( 1200sideeffect = 0 1201class C: 1202 def __bool__(self): 1203 global sideeffect 1204 sideeffect = 10 1205 return False 1206c = C() 1207)"); 1208 PyObjectPtr c(mainModuleGet("c")); 1209 EXPECT_EQ(PyObject_Not(c), 1); 1210 EXPECT_EQ(PyErr_Occurred(), nullptr); 1211 PyObjectPtr sideeffect(mainModuleGet("sideeffect")); 1212 EXPECT_EQ(PyLong_AsLong(sideeffect), 10); 1213} 1214 1215TEST_F(ObjectExtensionApiTest, 1216 NotWithDunderBoolRaisingExceptionRaisesTypeError) { 1217 PyRun_SimpleString(R"( 1218class C: 1219 def __bool__(self): 1220 return -10 1221c = C() 1222)"); 1223 PyObjectPtr c(mainModuleGet("c")); 1224 EXPECT_EQ(PyObject_Not(c), -1); 1225 EXPECT_NE(PyErr_Occurred(), nullptr); 1226 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1227} 1228 1229TEST_F(ObjectExtensionApiTest, HashWithUncallableDunderHashRaisesTypeError) { 1230 PyRun_SimpleString(R"( 1231class C: 1232 __hash__ = None 1233c = C() 1234)"); 1235 PyObjectPtr c(mainModuleGet("c")); 1236 EXPECT_EQ(PyObject_Hash(c), -1); 1237 EXPECT_NE(PyErr_Occurred(), nullptr); 1238 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1239} 1240 1241TEST_F(ObjectExtensionApiTest, HashCallsDunderHash) { 1242 PyRun_SimpleString(R"( 1243class C: 1244 def __hash__(self): 1245 return 7 1246c = C() 1247)"); 1248 PyObjectPtr c(mainModuleGet("c")); 1249 EXPECT_EQ(PyObject_Hash(c), 7); 1250 EXPECT_EQ(PyErr_Occurred(), nullptr); 1251} 1252 1253TEST_F(ObjectExtensionApiTest, HashPropagatesRaisedException) { 1254 PyRun_SimpleString(R"( 1255class C: 1256 def __hash__(self): 1257 raise IndexError 1258c = C() 1259)"); 1260 PyObjectPtr c(mainModuleGet("c")); 1261 EXPECT_EQ(PyObject_Hash(c), -1); 1262 EXPECT_NE(PyErr_Occurred(), nullptr); 1263 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError)); 1264} 1265 1266TEST_F(ObjectExtensionApiTest, HashNotImplementedRaisesTypeError) { 1267 EXPECT_EQ(PyObject_HashNotImplemented(Py_None), -1); 1268 EXPECT_NE(PyErr_Occurred(), nullptr); 1269 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1270} 1271 1272TEST_F(ObjectExtensionApiTest, 1273 RichCompareBoolEqWithLeftEqualsRightReturnsTrue) { 1274 EXPECT_EQ(PyObject_RichCompareBool(Py_None, Py_None, Py_EQ), 1); 1275 EXPECT_EQ(PyErr_Occurred(), nullptr); 1276} 1277 1278TEST_F(ObjectExtensionApiTest, 1279 RichCompareBoolNeWithLeftEqualsRightReturnsFalse) { 1280 EXPECT_EQ(PyObject_RichCompareBool(Py_None, Py_None, Py_NE), 0); 1281 EXPECT_EQ(PyErr_Occurred(), nullptr); 1282} 1283 1284TEST_F(ObjectExtensionApiTest, RichCompareBoolWithSameTypeReturnsTrue) { 1285 PyObjectPtr left(PyLong_FromLong(2)); 1286 PyObjectPtr right(PyLong_FromLong(3)); 1287 EXPECT_EQ(PyObject_RichCompareBool(left, right, Py_LT), 1); 1288 ASSERT_EQ(PyErr_Occurred(), nullptr); 1289} 1290 1291TEST_F(ObjectExtensionApiTest, RichCompareBoolNotComparableRaisesTypeError) { 1292 PyObjectPtr left(PyLong_FromLong(2)); 1293 PyObjectPtr right(PyUnicode_FromString("hello")); 1294 EXPECT_EQ(PyObject_RichCompareBool(left, right, Py_LT), -1); 1295 ASSERT_NE(PyErr_Occurred(), nullptr); 1296 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1297} 1298 1299TEST_F(ObjectExtensionApiTest, ReprEnterOnceReturnsZero) { 1300 PyObjectPtr obj(PyLong_FromLong(7)); 1301 EXPECT_EQ(Py_ReprEnter(obj), 0); 1302 EXPECT_EQ(PyErr_Occurred(), nullptr); 1303} 1304 1305TEST_F(ObjectExtensionApiTest, ReprEnterSecondTimeReturnsOne) { 1306 PyObjectPtr obj(PyLong_FromLong(7)); 1307 ASSERT_EQ(Py_ReprEnter(obj), 0); 1308 ASSERT_EQ(PyErr_Occurred(), nullptr); 1309 EXPECT_EQ(Py_ReprEnter(obj), 1); 1310 EXPECT_EQ(PyErr_Occurred(), nullptr); 1311} 1312 1313TEST_F(ObjectExtensionApiTest, ReprEnterThenLeaveRemovesFromSet) { 1314 PyObjectPtr obj(PyLong_FromLong(7)); 1315 ASSERT_EQ(Py_ReprEnter(obj), 0); 1316 ASSERT_EQ(PyErr_Occurred(), nullptr); 1317 ASSERT_EQ(Py_ReprEnter(obj), 1); 1318 ASSERT_EQ(PyErr_Occurred(), nullptr); 1319 Py_ReprLeave(obj); 1320 ASSERT_EQ(Py_ReprEnter(obj), 0); 1321 ASSERT_EQ(PyErr_Occurred(), nullptr); 1322} 1323 1324TEST_F(ObjectExtensionApiTest, InitWithNullRaisesNoMemoryError) { 1325 PyType_Slot slots[] = { 1326 {0, nullptr}, 1327 }; 1328 static PyType_Spec spec; 1329 spec = { 1330 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots, 1331 }; 1332 PyObjectPtr type(PyType_FromSpec(&spec)); 1333 ASSERT_NE(type, nullptr); 1334 ASSERT_TRUE(PyType_CheckExact(type)); 1335 PyObject_Init(nullptr, reinterpret_cast<PyTypeObject*>(type.get())); 1336 ASSERT_NE(PyErr_Occurred(), nullptr); 1337 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_MemoryError)); 1338} 1339 1340TEST_F(ObjectExtensionApiTest, NewReturnsAllocatedObject) { 1341 struct BarObject { 1342 PyObject_HEAD 1343 int value; 1344 }; 1345 PyType_Slot slots[] = { 1346 {0, nullptr}, 1347 }; 1348 static PyType_Spec spec; 1349 spec = { 1350 "foo.Bar", sizeof(BarObject), 0, Py_TPFLAGS_DEFAULT, slots, 1351 }; 1352 PyObjectPtr type(PyType_FromSpec(&spec)); 1353 Py_ssize_t refcnt = Py_REFCNT(type.get()); 1354 PyObjectPtr instance(reinterpret_cast<PyObject*>( 1355 PyObject_New(BarObject, type.asTypeObject()))); 1356 ASSERT_NE(instance, nullptr); 1357 EXPECT_EQ(PyErr_Occurred(), nullptr); 1358 // TODO(T53456038): Switch back to EXPECT_EQ, once initial refcount is fixed 1359 EXPECT_GE(Py_REFCNT(instance), 1); 1360 EXPECT_EQ(Py_REFCNT(type), refcnt + 1); 1361} 1362 1363TEST_F(ObjectExtensionApiTest, NewVarReturnsAllocatedObject) { 1364 struct BarObject { 1365 PyObject_HEAD 1366 int value; 1367 }; 1368 struct BarContainer { 1369 PyObject_VAR_HEAD 1370 BarObject* items[1]; 1371 }; 1372 PyType_Slot slots[] = { 1373 {0, nullptr}, 1374 }; 1375 static PyType_Spec spec; 1376 spec = { 1377 "foo.Bar", sizeof(BarContainer), sizeof(BarObject), Py_TPFLAGS_DEFAULT, 1378 slots, 1379 }; 1380 PyObjectPtr type(PyType_FromSpec(&spec)); 1381 PyObjectPtr instance(reinterpret_cast<PyObject*>( 1382 PyObject_NewVar(BarContainer, type.asTypeObject(), 5))); 1383 ASSERT_NE(instance, nullptr); 1384 EXPECT_EQ(PyErr_Occurred(), nullptr); 1385 // TODO(T53456038): Switch back to EXPECT_EQ, once initial refcount is fixed 1386 EXPECT_GE(Py_REFCNT(instance), 1); 1387 EXPECT_EQ(Py_SIZE(instance.get()), 5); 1388} 1389 1390TEST_F(ObjectExtensionApiTest, PyEllipsisIdentityIsEqual) { 1391 // Test Identitiy 1392 PyObject* ellipsis1 = Py_Ellipsis; 1393 PyObject* ellipsis2 = Py_Ellipsis; 1394 EXPECT_EQ(ellipsis1, ellipsis2); 1395} 1396 1397TEST_F(ObjectExtensionApiTest, DirWithoutExecutionFrameReturnsNull) { 1398 EXPECT_EQ(PyObject_Dir(nullptr), nullptr); 1399} 1400 1401TEST_F(ObjectExtensionApiTest, DirReturnsLocals) { 1402 PyRun_SimpleString(R"( 1403class C: pass 1404)"); 1405 PyObjectPtr c_type(mainModuleGet("C")); 1406 binaryfunc meth = [](PyObject*, PyObject*) { return PyObject_Dir(nullptr); }; 1407 static PyMethodDef foo_func = {"foo", meth, METH_NOARGS}; 1408 PyObjectPtr func(PyCFunction_NewEx(&foo_func, c_type, nullptr)); 1409 ASSERT_NE(func, nullptr); 1410 PyObject_SetAttrString(c_type, "foo", func); 1411 1412 PyRun_SimpleString(R"( 1413foo = 123 1414c = C() 1415obj = c.foo() 1416)"); 1417 PyObjectPtr obj(mainModuleGet("obj")); 1418 ASSERT_EQ(PyList_Check(obj), 1); 1419 PyObjectPtr foo(PyUnicode_FromString("foo")); 1420 EXPECT_EQ(PySequence_Contains(obj, foo), 1); 1421} 1422 1423TEST_F(ObjectExtensionApiTest, DirOnInstanceReturnsListOfAttributes) { 1424 PyRun_SimpleString(R"( 1425class C: 1426 def __init__(self): 1427 self.foo = 123 1428obj = C() 1429)"); 1430 PyObjectPtr obj(mainModuleGet("obj")); 1431 ASSERT_EQ(PyErr_Occurred(), nullptr); 1432 PyObjectPtr result(PyObject_Dir(obj)); 1433 ASSERT_EQ(PyList_Check(result), 1); 1434 PyObjectPtr foo(PyUnicode_FromString("foo")); 1435 EXPECT_EQ(PySequence_Contains(result, foo), 1); 1436} 1437 1438TEST_F(ObjectExtensionApiTest, DirOnInstanceWithDunderDirRaisingReturnsNull) { 1439 PyRun_SimpleString(R"( 1440class C: 1441 def __init__(self): 1442 self.foo = 123 1443 def __dir__(self): 1444 raise TypeError("no dir on this type") 1445obj = C() 1446)"); 1447 PyObjectPtr obj(mainModuleGet("obj")); 1448 ASSERT_EQ(PyErr_Occurred(), nullptr); 1449 PyObjectPtr result(PyObject_Dir(obj)); 1450 ASSERT_EQ(result, nullptr); 1451 ASSERT_NE(PyErr_Occurred(), nullptr); 1452 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1453} 1454 1455TEST_F(ObjectExtensionApiTest, 1456 DirOnInstanceWithNonIterableDunderDirReturnsNull) { 1457 PyRun_SimpleString(R"( 1458class C: 1459 def __init__(self): 1460 self.foo = 123 1461 def __dir__(self): 1462 return 123 1463obj = C() 1464)"); 1465 PyObjectPtr obj(mainModuleGet("obj")); 1466 ASSERT_EQ(PyErr_Occurred(), nullptr); 1467 PyObjectPtr result(PyObject_Dir(obj)); 1468 ASSERT_EQ(result, nullptr); 1469 ASSERT_NE(PyErr_Occurred(), nullptr); 1470 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 1471} 1472 1473TEST_F(ObjectExtensionApiTest, DirOnInstanceIgnoresInstanceDictionary) { 1474 PyRun_SimpleString(R"( 1475class C: 1476 def __init__(self): 1477 self.foo = 123 1478 1479def new_dir(self): 1480 return ("bar") 1481 1482obj = C() 1483obj.__dir__ = new_dir.__get__(obj, C) 1484)"); 1485 PyObjectPtr obj(mainModuleGet("obj")); 1486 ASSERT_EQ(PyErr_Occurred(), nullptr); 1487 PyObjectPtr result(PyObject_Dir(obj)); 1488 ASSERT_EQ(PyList_Check(result), 1); 1489 PyObjectPtr foo(PyUnicode_FromString("foo")); 1490 EXPECT_EQ(PySequence_Contains(result, foo), 1); 1491} 1492 1493TEST_F(ObjectExtensionApiTest, PyReturnNoneReturnsNone) { 1494 PyObjectPtr module(PyModule_New("mod")); 1495 binaryfunc meth = [](PyObject*, PyObject*) { Py_RETURN_NONE; }; 1496 static PyMethodDef foo_func = {"foo", meth, METH_NOARGS}; 1497 PyObjectPtr func(PyCFunction_NewEx(&foo_func, nullptr, module)); 1498 PyObjectPtr result(_PyObject_CallNoArg(func)); 1499 EXPECT_EQ(result, Py_None); 1500} 1501 1502TEST_F(ObjectExtensionApiTest, PyReturnNotImplementedReturnsNotImplemented) { 1503 PyObjectPtr module(PyModule_New("mod")); 1504 binaryfunc meth = [](PyObject*, PyObject*) { Py_RETURN_NOTIMPLEMENTED; }; 1505 static PyMethodDef foo_func = {"foo", meth, METH_NOARGS}; 1506 PyObjectPtr func(PyCFunction_NewEx(&foo_func, nullptr, module)); 1507 PyObjectPtr result(_PyObject_CallNoArg(func)); 1508 EXPECT_EQ(result, Py_NotImplemented); 1509} 1510 1511TEST_F(ObjectExtensionApiTest, PyEnumTypeIdentityIsEqual) { 1512 // Test Identitiy 1513 PyTypeObject* type1 = &PyEnum_Type; 1514 PyTypeObject* type2 = &PyEnum_Type; 1515 EXPECT_EQ(type1, type2); 1516} 1517 1518TEST_F(ObjectExtensionApiTest, PyEnumTypeIsInBuiltins) { 1519 PyObjectPtr builtins(borrow(PyEval_GetBuiltins())); 1520 PyObjectPtr enumerate(PyMapping_GetItemString(builtins, "enumerate")); 1521 EXPECT_EQ(enumerate.asTypeObject(), &PyEnum_Type); 1522} 1523 1524} // namespace testing 1525} // namespace py