this repo has no description
at trunk 774 lines 23 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 ModuleExtensionApiTest = ExtensionApi; 12// Used to convert non-capturing closures into function pointers. 13using slot_func = int (*)(PyObject*); 14 15TEST_F(ModuleExtensionApiTest, SpamModule) { 16 static PyModuleDef def; 17 def = { 18 PyModuleDef_HEAD_INIT, 19 "spam", 20 }; 21 22 // PyInit_spam 23 const long val = 5; 24 { 25 PyObjectPtr m(PyModule_Create(&def)); 26 PyObject* de = PyDict_New(); 27 PyModule_AddObject(m, "constants", de); 28 29 const char* c = "CONST"; 30 PyObjectPtr u(PyUnicode_FromString(c)); 31 PyObjectPtr v(PyLong_FromLong(val)); 32 PyModule_AddIntConstant(m, c, val); 33 PyDict_SetItem(de, v, u); 34 ASSERT_EQ(testing::moduleSet("__main__", "spam", m), 0); 35 } 36 37 PyRun_SimpleString("x = spam.CONST"); 38 39 PyObjectPtr x(testing::mainModuleGet("x")); 40 long result = PyLong_AsLong(x); 41 ASSERT_EQ(result, val); 42} 43 44TEST_F(ModuleExtensionApiTest, GetDictReturnsMapping) { 45 PyRun_SimpleString(R"( 46foo = 42 47)"); 48 PyObjectPtr name(PyUnicode_FromString("__main__")); 49 PyObjectPtr main(importGetModule(name)); 50 ASSERT_TRUE(PyModule_Check(main)); 51 PyObject* module_dict = PyModule_GetDict(main); 52 PyObjectPtr value(PyMapping_GetItemString(module_dict, "foo")); 53 EXPECT_TRUE(isLongEqualsLong(value, 42)); 54} 55 56TEST_F(ModuleExtensionApiTest, NewObjectWithNonStringNameReturnsModule) { 57 testing::PyObjectPtr long_name(PyLong_FromLong(2)); 58 testing::PyObjectPtr module(PyModule_NewObject(long_name)); 59 ASSERT_TRUE(PyModule_CheckExact(module)); 60 61 testing::PyObjectPtr mod_name(PyObject_GetAttrString(module, "__name__")); 62 EXPECT_EQ(mod_name, long_name); 63 EXPECT_EQ(PyErr_Occurred(), nullptr); 64} 65 66TEST_F(ModuleExtensionApiTest, NewObjectDoesNotAddModuleToModuleDict) { 67 testing::PyObjectPtr name(PyUnicode_FromString("mymodule")); 68 testing::PyObjectPtr module(PyModule_NewObject(name)); 69 ASSERT_TRUE(PyModule_CheckExact(module)); 70 71 PyObject* mods = PyImport_GetModuleDict(); 72 PyObject* item = PyDict_GetItem(mods, name); 73 EXPECT_EQ(item, nullptr); 74 75 EXPECT_EQ(PyErr_Occurred(), nullptr); 76} 77 78TEST_F(ModuleExtensionApiTest, NewWithEmptyStringReturnsModule) { 79 testing::PyObjectPtr module(PyModule_New("")); 80 ASSERT_TRUE(PyModule_CheckExact(module)); 81 82 testing::PyObjectPtr mod_name(PyObject_GetAttrString(module, "__name__")); 83 EXPECT_TRUE(isUnicodeEqualsCStr(mod_name, "")); 84 EXPECT_EQ(PyErr_Occurred(), nullptr); 85} 86 87TEST_F(ModuleExtensionApiTest, NewDoesNotAddModuleToModuleDict) { 88 testing::PyObjectPtr module(PyModule_New("mymodule")); 89 ASSERT_TRUE(PyModule_CheckExact(module)); 90 91 PyObject* mods = PyImport_GetModuleDict(); 92 testing::PyObjectPtr name(PyUnicode_FromString("mymodule")); 93 PyObject* item = PyDict_GetItem(mods, name); 94 EXPECT_EQ(item, nullptr); 95 96 EXPECT_EQ(PyErr_Occurred(), nullptr); 97} 98 99TEST_F(ModuleExtensionApiTest, CreateAddsDocstring) { 100 const char* mod_doc = "documentation for spam"; 101 static PyModuleDef def; 102 def = { 103 PyModuleDef_HEAD_INIT, 104 "mymodule", 105 mod_doc, 106 }; 107 108 PyObjectPtr module(PyModule_Create(&def)); 109 ASSERT_NE(module, nullptr); 110 EXPECT_TRUE(PyModule_CheckExact(module)); 111 112 PyObjectPtr doc(PyObject_GetAttrString(module, "__doc__")); 113 EXPECT_TRUE(isUnicodeEqualsCStr(doc, mod_doc)); 114 EXPECT_EQ(PyErr_Occurred(), nullptr); 115} 116 117TEST_F(ModuleExtensionApiTest, CreateSetsStateNull) { 118 static PyModuleDef def; 119 def = { 120 PyModuleDef_HEAD_INIT, 121 "mymodule", 122 }; 123 124 testing::PyObjectPtr module(PyModule_Create(&def)); 125 ASSERT_NE(module, nullptr); 126 EXPECT_TRUE(PyModule_CheckExact(module)); 127 128 ASSERT_EQ(PyModule_GetState(module), nullptr); 129 EXPECT_EQ(PyErr_Occurred(), nullptr); 130} 131 132TEST_F(ModuleExtensionApiTest, GetStateAllocatesAndAllowsMutation) { 133 struct MyState { 134 char letter; 135 int number; 136 double big_number; 137 PyObject* object; 138 }; 139 140 static PyModuleDef def; 141 def = { 142 PyModuleDef_HEAD_INIT, 143 "mymodule", 144 "doc", 145 sizeof(MyState), 146 }; 147 148 testing::PyObjectPtr module(PyModule_Create(&def)); 149 ASSERT_NE(module, nullptr); 150 ASSERT_EQ(PyState_AddModule(module, &def), 0); 151 EXPECT_TRUE(PyModule_CheckExact(module)); 152 153 void* state = PyModule_GetState(module); 154 ASSERT_NE(state, nullptr); 155 MyState* mod_state = static_cast<MyState*>(state); 156 mod_state->letter = 'a'; 157 mod_state->number = 2; 158 mod_state->big_number = 2.1; 159 testing::PyObjectPtr unique_obj(PyTuple_New(0)); 160 mod_state->object = unique_obj; 161 162 ASSERT_EQ(PyModule_GetState(module), state); 163 EXPECT_EQ(mod_state->letter, 'a'); 164 EXPECT_EQ(mod_state->number, 2); 165 EXPECT_EQ(mod_state->big_number, 2.1); 166 EXPECT_EQ(mod_state->object, unique_obj); 167 168 EXPECT_EQ(PyErr_Occurred(), nullptr); 169} 170 171TEST_F(ModuleExtensionApiTest, GetStateFailsOnNonModule) { 172 testing::PyObjectPtr not_a_module(PyLong_FromLong(0)); 173 174 EXPECT_EQ(PyModule_GetState(not_a_module), nullptr); 175 ASSERT_NE(PyErr_Occurred(), nullptr); 176 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 177} 178 179TEST_F(ModuleExtensionApiTest, GetStateReturnsValidStateAfterGarbageCollected) { 180 struct MyState { 181 char letter; 182 }; 183 184 static PyModuleDef def; 185 def = { 186 PyModuleDef_HEAD_INIT, 187 "mymodule", 188 "doc", 189 sizeof(MyState), 190 }; 191 192 PyObject* module = PyModule_Create(&def); 193 ASSERT_NE(module, nullptr); 194 ASSERT_EQ(PyState_AddModule(module, &def), 0); 195 EXPECT_TRUE(PyModule_CheckExact(module)); 196 197 void* state = PyModule_GetState(module); 198 ASSERT_NE(state, nullptr); 199 MyState* mod_state = static_cast<MyState*>(state); 200 mod_state->letter = 'a'; 201 202 // Decrease the reference count to zero. 203 Py_DECREF(module); 204 205 // Trigger GC to remove the module object from the handle table. 206 collectGarbage(); 207 208 // Verify that the module still retains the state. 209 module = PyState_FindModule(&def); 210 ASSERT_NE(module, nullptr); 211 ASSERT_EQ(PyModule_GetState(module), state); 212 mod_state = static_cast<MyState*>(state); 213 EXPECT_EQ(mod_state->letter, 'a'); 214 EXPECT_EQ(PyErr_Occurred(), nullptr); 215} 216 217TEST_F(ModuleExtensionApiTest, GetDefWithExtensionModuleRetunsNonNull) { 218 static PyModuleDef def; 219 def = { 220 PyModuleDef_HEAD_INIT, 221 "mymodule", 222 "mydoc", 223 }; 224 225 PyObjectPtr module(PyModule_Create(&def)); 226 ASSERT_NE(module, nullptr); 227 228 PyModuleDef* result = PyModule_GetDef(module); 229 EXPECT_EQ(result, &def); 230} 231 232TEST_F(ModuleExtensionApiTest, GetDefWithNonModuleRetunsNull) { 233 PyObject* integer = PyBool_FromLong(0); 234 PyModuleDef* result = PyModule_GetDef(integer); 235 EXPECT_EQ(result, nullptr); 236} 237 238TEST_F(ModuleExtensionApiTest, GetDefWithNonExtensionModuleReturnsNull) { 239 PyRun_SimpleString(""); 240 PyObjectPtr module_name(PyUnicode_FromString("__main__")); 241 PyObjectPtr main_module(testing::importGetModule(module_name)); 242 PyModuleDef* result = PyModule_GetDef(main_module); 243 EXPECT_EQ(result, nullptr); 244} 245 246TEST_F(ModuleExtensionApiTest, CheckTypeOnNonModuleReturnsZero) { 247 PyObjectPtr pylong(PyLong_FromLong(10)); 248 EXPECT_FALSE(PyModule_Check(pylong)); 249 EXPECT_FALSE(PyModule_CheckExact(pylong)); 250 EXPECT_EQ(PyErr_Occurred(), nullptr); 251} 252 253TEST_F(ModuleExtensionApiTest, CheckTypeOnModuleReturnsOne) { 254 static PyModuleDef def; 255 def = { 256 PyModuleDef_HEAD_INIT, 257 "mymodule", 258 }; 259 PyObjectPtr module(PyModule_Create(&def)); 260 EXPECT_TRUE(PyModule_Check(module)); 261 EXPECT_TRUE(PyModule_CheckExact(module)); 262 EXPECT_EQ(PyErr_Occurred(), nullptr); 263} 264 265TEST_F(ModuleExtensionApiTest, SetDocStringChangesDoc) { 266 const char* mod_doc = "mymodule doc"; 267 static PyModuleDef def; 268 def = { 269 PyModuleDef_HEAD_INIT, 270 "mymodule", 271 mod_doc, 272 }; 273 274 PyObjectPtr module(PyModule_Create(&def)); 275 ASSERT_NE(module, nullptr); 276 EXPECT_TRUE(PyModule_CheckExact(module)); 277 278 PyObjectPtr orig_doc(PyObject_GetAttrString(module, "__doc__")); 279 EXPECT_TRUE(isUnicodeEqualsCStr(orig_doc, mod_doc)); 280 EXPECT_EQ(PyErr_Occurred(), nullptr); 281 282 const char* edit_mod_doc = "edited doc"; 283 int result = PyModule_SetDocString(module, edit_mod_doc); 284 ASSERT_EQ(result, 0); 285 286 PyObjectPtr edit_doc(PyObject_GetAttrString(module, "__doc__")); 287 EXPECT_TRUE(isUnicodeEqualsCStr(edit_doc, edit_mod_doc)); 288 EXPECT_EQ(PyErr_Occurred(), nullptr); 289} 290 291TEST_F(ModuleExtensionApiTest, SetDocStringCreatesDoc) { 292 static PyModuleDef def; 293 def = { 294 PyModuleDef_HEAD_INIT, 295 "mymodule", 296 }; 297 298 PyObjectPtr module(PyModule_Create(&def)); 299 ASSERT_NE(module, nullptr); 300 EXPECT_TRUE(PyModule_CheckExact(module)); 301 302 const char* edit_mod_doc = "edited doc"; 303 ASSERT_EQ(PyModule_SetDocString(module, edit_mod_doc), 0); 304 305 PyObjectPtr doc(PyObject_GetAttrString(module, "__doc__")); 306 EXPECT_TRUE(isUnicodeEqualsCStr(doc, edit_mod_doc)); 307 EXPECT_EQ(PyErr_Occurred(), nullptr); 308} 309 310TEST_F(ModuleExtensionApiTest, SetDocStringSetsObjectAttribute) { 311 PyRun_SimpleString(R"( 312class C: pass 313not_a_module = C() 314)"); 315 PyObjectPtr not_a_module(mainModuleGet("not_a_module")); 316 EXPECT_EQ(PyModule_SetDocString(not_a_module, "baz"), 0); 317 PyObjectPtr value(PyObject_GetAttrString(not_a_module, "__doc__")); 318 EXPECT_TRUE(isUnicodeEqualsCStr(value, "baz")); 319} 320 321TEST_F(ModuleExtensionApiTest, ModuleCreateDoesNotAddToModuleDict) { 322 const char* name = "mymodule"; 323 static PyModuleDef def; 324 def = { 325 PyModuleDef_HEAD_INIT, 326 name, 327 }; 328 PyObjectPtr module(PyModule_Create(&def)); 329 ASSERT_NE(module, nullptr); 330 PyObject* mods = PyImport_GetModuleDict(); 331 PyObjectPtr name_obj(PyUnicode_FromString(name)); 332 EXPECT_EQ(PyDict_GetItem(mods, name_obj), nullptr); 333} 334 335TEST_F(ModuleExtensionApiTest, GetNameObjectGetsName) { 336 const char* mod_name = "mymodule"; 337 static PyModuleDef def; 338 def = { 339 PyModuleDef_HEAD_INIT, 340 mod_name, 341 }; 342 343 PyObject* module = PyModule_Create(&def); 344 ASSERT_NE(module, nullptr); 345 EXPECT_TRUE(PyModule_Check(module)); 346 347 PyObject* result = PyModule_GetNameObject(module); 348 EXPECT_TRUE(isUnicodeEqualsCStr(result, mod_name)); 349 EXPECT_EQ(PyErr_Occurred(), nullptr); 350 Py_DECREF(result); 351 352 Py_DECREF(module); 353} 354 355TEST_F(ModuleExtensionApiTest, GetNameObjectFailsIfNotModule) { 356 PyObject* not_a_module = PyTuple_New(10); 357 PyObject* result = PyModule_GetNameObject(not_a_module); 358 EXPECT_EQ(result, nullptr); 359 360 ASSERT_NE(PyErr_Occurred(), nullptr); 361 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 362 363 Py_DECREF(not_a_module); 364} 365 366TEST_F(ModuleExtensionApiTest, GetNameObjectFailsIfNotString) { 367 static PyModuleDef def; 368 def = { 369 PyModuleDef_HEAD_INIT, 370 "mymodule", 371 }; 372 373 PyObject* module = PyModule_Create(&def); 374 ASSERT_NE(module, nullptr); 375 EXPECT_TRUE(PyModule_CheckExact(module)); 376 377 PyObject* not_a_module = PyTuple_New(10); 378 PyObject_SetAttrString(module, "__name__", not_a_module); 379 PyObject* result = PyModule_GetNameObject(module); 380 EXPECT_EQ(result, nullptr); 381 382 ASSERT_NE(PyErr_Occurred(), nullptr); 383 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 384 385 Py_DECREF(module); 386 Py_DECREF(not_a_module); 387} 388 389TEST_F(ModuleExtensionApiTest, GetNameObjectWithModuleSubclassReturnsString) { 390 PyRun_SimpleString(R"( 391import builtins 392ModuleType = type(builtins) 393class C(ModuleType): 394 pass 395module = C("foo") 396)"); 397 PyObjectPtr module(mainModuleGet("module")); 398 PyObjectPtr result(PyModule_GetNameObject(module)); 399 EXPECT_TRUE(isUnicodeEqualsCStr(result, "foo")); 400} 401 402TEST_F(ModuleExtensionApiTest, GetFilenameObjectReturnsFilename) { 403 static PyModuleDef def; 404 def = { 405 PyModuleDef_HEAD_INIT, 406 "mymodule", 407 }; 408 409 testing::PyObjectPtr module(PyModule_Create(&def)); 410 ASSERT_NE(module, nullptr); 411 EXPECT_TRUE(PyModule_Check(module)); 412 413 const char* filename = "file"; 414 PyModule_AddObject(module, "__file__", PyUnicode_FromString(filename)); 415 testing::PyObjectPtr result(PyModule_GetFilenameObject(module)); 416 EXPECT_TRUE(isUnicodeEqualsCStr(result, filename)); 417 EXPECT_EQ(PyErr_Occurred(), nullptr); 418} 419 420TEST_F(ModuleExtensionApiTest, GetFilenameObjectWithSubclassReturnsFilename) { 421 PyRun_SimpleString(R"( 422import builtins 423ModuleType = type(builtins) 424class C(ModuleType): 425 __file__ = "bar" 426module = C("foo") 427module.__file__ = "baz" 428)"); 429 PyObjectPtr module(mainModuleGet("module")); 430 PyObjectPtr result(PyModule_GetFilenameObject(module)); 431 EXPECT_TRUE(isUnicodeEqualsCStr(result, "baz")); 432} 433 434TEST_F(ModuleExtensionApiTest, GetFilenameObjectFailsIfNotModule) { 435 testing::PyObjectPtr not_a_module(PyLong_FromLong(1)); 436 testing::PyObjectPtr result(PyModule_GetFilenameObject(not_a_module)); 437 EXPECT_EQ(result, nullptr); 438 ASSERT_NE(PyErr_Occurred(), nullptr); 439 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 440} 441 442TEST_F(ModuleExtensionApiTest, GetFilenameObjectFailsIfFilenameNotString) { 443 static PyModuleDef def; 444 def = { 445 PyModuleDef_HEAD_INIT, 446 "mymodule", 447 }; 448 449 PyObjectPtr module(PyModule_Create(&def)); 450 ASSERT_NE(module, nullptr); 451 EXPECT_TRUE(PyModule_CheckExact(module)); 452 453 PyObject* not_a_string = PyLong_FromLong(1); 454 455 PyModule_AddObject(module, "__file__", not_a_string); 456 testing::PyObjectPtr result(PyModule_GetFilenameObject(module)); 457 EXPECT_EQ(result, nullptr); 458 459 ASSERT_NE(PyErr_Occurred(), nullptr); 460 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 461} 462 463TEST_F(ModuleExtensionApiTest, ExecDefReturnsZeroWithNoSlots) { 464 static PyModuleDef def; 465 def = { 466 PyModuleDef_HEAD_INIT, 467 "mymodule", 468 }; 469 470 testing::PyObjectPtr module(PyModule_Create(&def)); 471 ASSERT_NE(module, nullptr); 472 EXPECT_TRUE(PyModule_CheckExact(module)); 473 474 EXPECT_EQ(PyModule_ExecDef(module, &def), 0); 475 EXPECT_EQ(PyErr_Occurred(), nullptr); 476} 477 478TEST_F(ModuleExtensionApiTest, ExecDefFailsIfPassedNamelessModule) { 479 static PyModuleDef def; 480 def = { 481 PyModuleDef_HEAD_INIT, 482 "mymodule", 483 }; 484 485 testing::PyObjectPtr module(PyModule_NewObject(Py_None)); 486 ASSERT_NE(module, nullptr); 487 EXPECT_TRUE(PyModule_CheckExact(module)); 488 489 EXPECT_EQ(PyModule_ExecDef(module, &def), -1); 490 EXPECT_NE(PyErr_Occurred(), nullptr); 491} 492 493// TODO(T37048769): Replace _Create with _FromDefAndSpec and run with CPython 494TEST_F(ModuleExtensionApiTest, ExecDefFailsIfDefHasUnknownSlotPyro) { 495 slot_func mod_exec = [](PyObject* module) { 496 PyModule_SetDocString(module, "testing"); 497 return 0; 498 }; 499 500 static PyModuleDef_Slot slots[] = { 501 {-1, reinterpret_cast<void*>(mod_exec)}, 502 {0, nullptr}, 503 }; 504 static PyModuleDef def; 505 def = { 506 PyModuleDef_HEAD_INIT, "mymodule", nullptr, 0, nullptr, slots, 507 }; 508 509 testing::PyObjectPtr module(PyModule_Create(&def)); 510 ASSERT_NE(module, nullptr); 511 EXPECT_TRUE(PyModule_CheckExact(module)); 512 513 EXPECT_EQ(PyModule_ExecDef(module, &def), -1); 514 ASSERT_NE(PyErr_Occurred(), nullptr); 515 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 516} 517 518// TODO(T37048769): Replace _Create with _FromDefAndSpec and run with CPython 519TEST_F(ModuleExtensionApiTest, ExecDefRunsCorrectSingleSlotPyro) { 520 slot_func mod_exec = [](PyObject* module) { 521 PyModule_SetDocString(module, "testing"); 522 return 0; 523 }; 524 525 static PyModuleDef_Slot slots[] = { 526 {Py_mod_exec, reinterpret_cast<void*>(mod_exec)}, 527 {0, nullptr}, 528 }; 529 static PyModuleDef def; 530 def = { 531 PyModuleDef_HEAD_INIT, "mymodule", nullptr, 0, nullptr, slots, 532 }; 533 534 testing::PyObjectPtr module(PyModule_Create(&def)); 535 ASSERT_NE(module, nullptr); 536 EXPECT_TRUE(PyModule_CheckExact(module)); 537 538 EXPECT_EQ(PyModule_ExecDef(module, &def), 0); 539 540 testing::PyObjectPtr doc(PyObject_GetAttrString(module, "__doc__")); 541 EXPECT_TRUE(isUnicodeEqualsCStr(doc, "testing")); 542 EXPECT_EQ(PyErr_Occurred(), nullptr); 543} 544 545// TODO(T37048769): Replace _Create with _FromDefAndSpec and run with CPython 546TEST_F(ModuleExtensionApiTest, ExecDefRunsMultipleSlotsInOrderPyro) { 547 slot_func mod_exec = [](PyObject* module) { 548 PyModule_SetDocString(module, "doc test"); 549 return 0; 550 }; 551 552 slot_func mod_exec_second = [](PyObject* module) { 553 PyObjectPtr doc(PyObject_GetAttrString(module, "__doc__")); 554 if (doc != nullptr) { 555 PyObjectPtr attr(PyUnicode_FromString("testing1")); 556 PyObject_SetAttrString(module, "test1", attr); 557 } 558 return 0; 559 }; 560 561 slot_func mod_exec_third = [](PyObject* module) { 562 PyObjectPtr doc(PyObject_GetAttrString(module, "__doc__")); 563 if (doc != nullptr) { 564 PyObjectPtr attr(PyUnicode_FromString("testing2")); 565 PyObject_SetAttrString(module, "test2", attr); 566 } 567 return 0; 568 }; 569 570 static PyModuleDef_Slot slots[] = { 571 {Py_mod_exec, reinterpret_cast<void*>(mod_exec)}, 572 {Py_mod_exec, reinterpret_cast<void*>(mod_exec_second)}, 573 {Py_mod_exec, reinterpret_cast<void*>(mod_exec_third)}, 574 {0, nullptr}, 575 }; 576 static PyModuleDef def; 577 def = { 578 PyModuleDef_HEAD_INIT, "mymodule", nullptr, 0, nullptr, slots, 579 }; 580 581 testing::PyObjectPtr module(PyModule_Create(&def)); 582 ASSERT_NE(module, nullptr); 583 EXPECT_TRUE(PyModule_CheckExact(module)); 584 585 EXPECT_EQ(PyModule_ExecDef(module, &def), 0); 586 587 testing::PyObjectPtr doc(PyObject_GetAttrString(module, "__doc__")); 588 EXPECT_TRUE(isUnicodeEqualsCStr(doc, "doc test")); 589 testing::PyObjectPtr test_attr_one(PyObject_GetAttrString(module, "test1")); 590 EXPECT_TRUE(isUnicodeEqualsCStr(test_attr_one, "testing1")); 591 testing::PyObjectPtr test_attr_two(PyObject_GetAttrString(module, "test2")); 592 EXPECT_TRUE(isUnicodeEqualsCStr(test_attr_two, "testing2")); 593 EXPECT_EQ(PyErr_Occurred(), nullptr); 594} 595 596// TODO(T37048769): Replace _Create with _FromDefAndSpec and run with CPython 597TEST_F(ModuleExtensionApiTest, ExecDefFailsIfSlotHasErrorButReturnsZeroPyro) { 598 slot_func mod_exec_fail_silently = [](PyObject* module) { 599 testing::PyObjectPtr attr(PyObject_GetAttrString(module, "non-existent")); 600 static_cast<void>(attr); 601 return 0; 602 }; 603 604 static PyModuleDef_Slot slots[] = { 605 {Py_mod_exec, reinterpret_cast<void*>(mod_exec_fail_silently)}, 606 {0, nullptr}, 607 }; 608 static PyModuleDef def; 609 def = { 610 PyModuleDef_HEAD_INIT, "mymodule", nullptr, 0, nullptr, slots, 611 }; 612 613 testing::PyObjectPtr module(PyModule_Create(&def)); 614 ASSERT_NE(module, nullptr); 615 EXPECT_TRUE(PyModule_CheckExact(module)); 616 617 EXPECT_EQ(PyModule_ExecDef(module, &def), -1); 618 ASSERT_NE(PyErr_Occurred(), nullptr); 619 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 620} 621 622// TODO(T37048769): Replace _Create with _FromDefAndSpec and run with CPython 623TEST_F(ModuleExtensionApiTest, ExecDefFailsIfSlotFailsButDoesntSetErrorPyro) { 624 slot_func mod_exec_fail_no_error = [](PyObject* module) { 625 testing::PyObjectPtr attr(PyObject_GetAttrString(module, "non-existent")); 626 static_cast<void>(attr); 627 PyErr_Clear(); 628 return -1; 629 }; 630 631 static PyModuleDef_Slot slots[] = { 632 {Py_mod_exec, reinterpret_cast<void*>(mod_exec_fail_no_error)}, 633 {0, nullptr}, 634 }; 635 static PyModuleDef def; 636 def = { 637 PyModuleDef_HEAD_INIT, "mymodule", nullptr, 0, nullptr, slots, 638 }; 639 640 testing::PyObjectPtr module(PyModule_Create(&def)); 641 ASSERT_NE(module, nullptr); 642 EXPECT_TRUE(PyModule_CheckExact(module)); 643 644 EXPECT_EQ(PyModule_ExecDef(module, &def), -1); 645 ASSERT_NE(PyErr_Occurred(), nullptr); 646 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 647} 648 649// TODO(T37048769): Replace _Create with _FromDefAndSpec and run with CPython 650TEST_F(ModuleExtensionApiTest, ExecDefFailsIfSlotFailsAndPropogatesErrorPyro) { 651 slot_func mod_exec_fail = [](PyObject* module) { 652 testing::PyObjectPtr attr(PyObject_GetAttrString(module, "non-existent")); 653 static_cast<void>(attr); 654 return -1; 655 }; 656 657 static PyModuleDef_Slot slots[] = { 658 {Py_mod_exec, reinterpret_cast<void*>(mod_exec_fail)}, 659 {0, nullptr}, 660 }; 661 static PyModuleDef def; 662 def = { 663 PyModuleDef_HEAD_INIT, "mymodule", nullptr, 0, nullptr, slots, 664 }; 665 666 testing::PyObjectPtr module(PyModule_Create(&def)); 667 ASSERT_NE(module, nullptr); 668 EXPECT_TRUE(PyModule_CheckExact(module)); 669 670 EXPECT_EQ(PyModule_ExecDef(module, &def), -1); 671 ASSERT_NE(PyErr_Occurred(), nullptr); 672 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError)); 673} 674 675TEST_F(ModuleExtensionApiTest, GetNameGetsName) { 676 const char* mod_name = "mymodule"; 677 static PyModuleDef def; 678 def = { 679 PyModuleDef_HEAD_INIT, 680 mod_name, 681 }; 682 683 testing::PyObjectPtr module(PyModule_Create(&def)); 684 ASSERT_NE(module, nullptr); 685 EXPECT_TRUE(PyModule_Check(module)); 686 687 EXPECT_STREQ(PyModule_GetName(module), mod_name); 688 EXPECT_EQ(PyErr_Occurred(), nullptr); 689} 690 691TEST_F(ModuleExtensionApiTest, GetNameReturnsNullIfNoName) { 692 testing::PyObjectPtr not_a_module(PyLong_FromLong(1)); 693 EXPECT_EQ(PyModule_GetName(not_a_module), nullptr); 694 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 695} 696 697TEST_F(ModuleExtensionApiTest, GetNameDoesNotIncrementModuleNameRefcount) { 698 const char* mod_name = "mymodule"; 699 static PyModuleDef def; 700 def = { 701 PyModuleDef_HEAD_INIT, 702 mod_name, 703 }; 704 705 testing::PyObjectPtr module(PyModule_Create(&def)); 706 ASSERT_NE(module, nullptr); 707 EXPECT_TRUE(PyModule_Check(module)); 708 709 PyObjectPtr name(PyModule_GetNameObject(module)); 710 EXPECT_TRUE(isUnicodeEqualsCStr(name, mod_name)); 711 712 Py_ssize_t name_count = Py_REFCNT(name); 713 EXPECT_STREQ(PyModule_GetName(module), mod_name); 714 EXPECT_EQ(Py_REFCNT(name), name_count); 715 EXPECT_EQ(PyErr_Occurred(), nullptr); 716} 717 718TEST_F(ModuleExtensionApiTest, MethodWithClassFlagRaisesException) { 719 binaryfunc foo_func = [](PyObject*, PyObject*) { 720 return PyLong_FromLong(10); 721 }; 722 PyMethodDef foo_methods[] = { 723 {"longValue", foo_func, METH_NOARGS | METH_CLASS}, {nullptr}}; 724 static PyModuleDef def; 725 def = { 726 PyModuleDef_HEAD_INIT, "foo", nullptr, 0, foo_methods, 727 }; 728 PyObjectPtr module(PyModule_Create(&def)); 729 EXPECT_EQ(module, nullptr); 730 EXPECT_NE(PyErr_Occurred(), nullptr); 731 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError)); 732} 733 734static PyObject* init_extra_builtin_module(void) { 735 static PyModuleDef def; 736 def = {PyModuleDef_HEAD_INIT, "extra_builtin"}; 737 return PyModule_Create(&def); 738} 739 740static PyObject* init_extra_extra_builtin_module(void) { 741 static PyModuleDef def; 742 def = {PyModuleDef_HEAD_INIT, "extra_extra_builtin"}; 743 return PyModule_Create(&def); 744} 745 746TEST(ModuleExtensionApiTestNoFixture, PyImportAppendInittabExtendInittab) { 747 resetPythonEnv(); 748 PyImport_AppendInittab("extra_builtin", init_extra_builtin_module); 749 PyImport_AppendInittab("extra_extra_builtin", 750 init_extra_extra_builtin_module); 751 Py_Initialize(); 752 753 PyRun_SimpleString(R"( 754import sys 755a = "extra_builtin" in sys.builtin_module_names 756b = "extra_extra_builtin" in sys.builtin_module_names 757c = "not_added" in sys.builtin_module_names 758)"); 759 ASSERT_EQ(PyErr_Occurred(), nullptr); 760 PyObjectPtr pybool_true(PyBool_FromLong(1)); 761 PyObjectPtr pybool_false(PyBool_FromLong(0)); 762 PyObjectPtr a(mainModuleGet("a")); 763 PyObjectPtr b(mainModuleGet("b")); 764 PyObjectPtr c(mainModuleGet("c")); 765 766 ASSERT_EQ(pybool_true, a); 767 ASSERT_EQ(pybool_true, b); 768 ASSERT_EQ(pybool_false, c); 769 770 Py_FinalizeEx(); 771} 772 773} // namespace testing 774} // namespace py