|
4 | 4 | #include <Python.h> |
5 | 5 | #include "CPy.h" |
6 | 6 |
|
7 | | -static bool is_initialized = false; |
8 | 7 | static PyObject *moduleDict; |
9 | 8 |
|
10 | 9 | static PyObject *int_from_str(const char *str) { |
@@ -84,21 +83,9 @@ class CAPITest : public ::testing::Test { |
84 | 83 | Py_ssize_t c_max_neg_long; |
85 | 84 |
|
86 | 85 | virtual void SetUp() { |
87 | | - if (!is_initialized) { |
88 | | - wchar_t *program = Py_DecodeLocale("test_capi", 0); |
89 | | - Py_SetProgramName(program); |
90 | | - Py_Initialize(); |
91 | | - PyObject *module = PyModule_New("test"); |
92 | | - if (module == 0) { |
93 | | - fail("Could not create module 'test'"); |
94 | | - } |
95 | | - moduleDict = PyModule_GetDict(module); |
96 | | - if (module == 0) { |
97 | | - fail("Could not fine module dictionary"); |
98 | | - } |
99 | | - is_initialized = true; |
| 86 | + if (!moduleDict) { |
| 87 | + fail("Could not find module dictionary"); |
100 | 88 | } |
101 | | - // TODO: Call Py_Finalize() and PyMem_RawFree(program) at the end somehow. |
102 | 89 |
|
103 | 90 | max_short = int_from_str("4611686018427387903"); // 2**62-1 |
104 | 91 | min_pos_long = int_from_str("4611686018427387904"); // 2**62 |
@@ -540,9 +527,52 @@ TEST_F(CAPITest, test_tagged_as_long_long) { |
540 | 527 | EXPECT_FALSE(PyErr_Occurred()); |
541 | 528 | EXPECT_TRUE(CPyTagged_AsSsize_t(l) == -1); |
542 | 529 | EXPECT_TRUE(PyErr_Occurred()); |
| 530 | + PyErr_Clear(); |
| 531 | +} |
| 532 | + |
| 533 | + |
| 534 | +//// |
| 535 | +// Python module glue to drive the C-API tests. |
| 536 | +// |
| 537 | +// The reason we have this as an extension module instead of a |
| 538 | +// standalone binary is because building an extension module is pretty |
| 539 | +// well behaved (just specify it with distutils/setuptools and it will |
| 540 | +// get compiled and linked against the running python) while linking a |
| 541 | +// library against libpython is a huge non-standard |
| 542 | +// PITA: python-config locations are janky and it behaves in weird |
| 543 | +// ways that I don't understand, while this works very cleanly. |
| 544 | + |
| 545 | +static PyObject *run_tests(PyObject *dummy, PyObject *should_be_null) { |
| 546 | + // Fake command line arguments. We could arrange to actually pass |
| 547 | + // in command line arguments (either real ones or ones given as |
| 548 | + // arguments) but have not bothered. |
| 549 | + int argc = 1; |
| 550 | + char asdf[] = "test_capi"; // InitGoogleTest wants char** which means it can't be const... |
| 551 | + char *argv[] = {asdf, NULL}; |
| 552 | + ::testing::InitGoogleTest(&argc, argv); |
| 553 | + return PyLong_FromLong(RUN_ALL_TESTS()); |
543 | 554 | } |
544 | 555 |
|
545 | | -int main(int argc, char **argv) { |
546 | | - ::testing::InitGoogleTest(&argc, argv); |
547 | | - return RUN_ALL_TESTS(); |
| 556 | + |
| 557 | +static PyMethodDef test_methods[] = { |
| 558 | + {"run_tests", run_tests, METH_NOARGS, "Run the C API tests"}, |
| 559 | + {NULL, NULL, 0, NULL} |
| 560 | +}; |
| 561 | + |
| 562 | +static struct PyModuleDef test_module = { |
| 563 | + PyModuleDef_HEAD_INIT, |
| 564 | + "test_capi", |
| 565 | + NULL, |
| 566 | + -1, |
| 567 | + test_methods |
| 568 | +}; |
| 569 | + |
| 570 | +PyMODINIT_FUNC |
| 571 | +PyInit_test_capi(void) |
| 572 | +{ |
| 573 | + PyObject *module = PyModule_Create(&test_module); |
| 574 | + if (module) { |
| 575 | + moduleDict = PyModule_GetDict(module); |
| 576 | + } |
| 577 | + return module; |
548 | 578 | } |
0 commit comments