this repo has no description
at trunk 188 lines 5.5 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 8extern "C" int _PyThreadState_GetRecursionDepth(PyThreadState*); 9 10namespace py { 11namespace testing { 12 13using PystateExtensionApiTest = ExtensionApi; 14using PystateExtensionApiTestDeathTest = ExtensionApi; 15 16TEST_F(PystateExtensionApiTestDeathTest, AddModuleWithNullDefDeathTest) { 17 EXPECT_DEATH(PyState_AddModule(Py_None, nullptr), 18 "Module Definition is NULL"); 19} 20 21TEST_F(PystateExtensionApiTestDeathTest, AddExistingModuleDoesNotOverride) { 22 static struct PyModuleDef def = { 23 PyModuleDef_HEAD_INIT, 24 "foo", 25 "docs", 26 0, 27 nullptr, 28 nullptr, 29 nullptr, 30 nullptr, 31 }; 32 PyModuleDef_Init(&def); 33 PyObjectPtr module(PyModule_New("foo")); 34 ASSERT_NE(module, nullptr); 35 ASSERT_EQ(PyState_AddModule(module, &def), 0); 36 EXPECT_DEATH(PyState_AddModule(module, &def), "Module already added!"); 37} 38 39TEST_F(PystateExtensionApiTest, AddModuleWithSlotsRaisesSystemError) { 40 struct PyModuleDef_Slot slots[] = { 41 {0, nullptr}, 42 }; 43 struct PyModuleDef def = { 44 PyModuleDef_HEAD_INIT, 45 "rutabaga", 46 "I'm sure this module will turnip somewhere.", 47 0, 48 nullptr, 49 slots, 50 nullptr, 51 nullptr, 52 }; 53 PyModuleDef_Init(&def); 54 EXPECT_EQ(PyState_AddModule(Py_None, &def), -1); 55 ASSERT_NE(PyErr_Occurred(), nullptr); 56 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 57} 58 59TEST_F(PystateExtensionApiTest, AddModuleAddsModule) { 60 static struct PyModuleDef def = { 61 PyModuleDef_HEAD_INIT, 62 "rutabaga", 63 "I'm sure this module will turnip somewhere.", 64 0, 65 nullptr, 66 nullptr, 67 nullptr, 68 nullptr, 69 }; 70 PyObject* module = PyModule_Create(&def); 71 ASSERT_NE(module, nullptr); 72 ASSERT_EQ(PyState_AddModule(module, &def), 0); 73 ASSERT_EQ(PyErr_Occurred(), nullptr); 74 PyObject* found_module = PyState_FindModule(&def); 75 ASSERT_NE(found_module, nullptr); 76 ASSERT_EQ(PyErr_Occurred(), nullptr); 77 ASSERT_TRUE(PyModule_CheckExact(found_module)); 78 PyObjectPtr found_name(PyModule_GetNameObject(found_module)); 79 PyObjectPtr module_name(PyModule_GetNameObject(module)); 80 EXPECT_EQ(PyUnicode_Compare(found_name, module_name), 0); 81 Py_DECREF(module); 82} 83 84TEST_F(PystateExtensionApiTest, _PyState_AddModuleWithSlotsRaisesSystemError) { 85 struct PyModuleDef_Slot slots[] = { 86 {0, nullptr}, 87 }; 88 struct PyModuleDef def = { 89 PyModuleDef_HEAD_INIT, "foo", "bar", 0, nullptr, slots, nullptr, nullptr, 90 }; 91 PyModuleDef_Init(&def); 92 EXPECT_EQ(PyState_AddModule(Py_None, &def), -1); 93 ASSERT_NE(PyErr_Occurred(), nullptr); 94 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 95} 96 97TEST_F(PystateExtensionApiTest, _PyState_AddModuleTwiceAddsModule) { 98 static struct PyModuleDef def = { 99 PyModuleDef_HEAD_INIT, 100 "foo", 101 "bar", 102 0, 103 nullptr, 104 nullptr, 105 nullptr, 106 nullptr, 107 }; 108 PyObject* module = PyModule_Create(&def); 109 ASSERT_NE(module, nullptr); 110 ASSERT_EQ(_PyState_AddModule(module, &def), 0); 111 ASSERT_EQ(PyErr_Occurred(), nullptr); 112 ASSERT_EQ(_PyState_AddModule(module, &def), 0); 113 ASSERT_EQ(PyErr_Occurred(), nullptr); 114 PyObject* found_module = PyState_FindModule(&def); 115 ASSERT_NE(found_module, nullptr); 116 ASSERT_EQ(PyErr_Occurred(), nullptr); 117 ASSERT_TRUE(PyModule_CheckExact(found_module)); 118 PyObjectPtr found_name(PyModule_GetNameObject(found_module)); 119 PyObjectPtr module_name(PyModule_GetNameObject(module)); 120 EXPECT_EQ(PyUnicode_Compare(found_name, module_name), 0); 121 Py_DECREF(module); 122} 123 124TEST_F(PystateExtensionApiTest, FindModuleWithSlotsReturnsNull) { 125 struct PyModuleDef def = { 126 PyModuleDef_HEAD_INIT, 127 "builtins", 128 "Uh, the builtins module, I guess", 129 0, 130 nullptr, 131 reinterpret_cast<PyModuleDef_Slot*>(5), 132 nullptr, 133 nullptr, 134 }; 135 PyModuleDef_Init(&def); 136 EXPECT_EQ(PyState_FindModule(&def), nullptr); 137 ASSERT_EQ(PyErr_Occurred(), nullptr); 138} 139 140TEST_F(PystateExtensionApiTest, FindModuleWithNonExistentModuleReturnsNull) { 141 struct PyModuleDef def = { 142 PyModuleDef_HEAD_INIT, 143 "rutabaga", 144 "I'm sure this module will turnip somewhere.", 145 0, 146 nullptr, 147 nullptr, 148 nullptr, 149 nullptr, 150 }; 151 PyModuleDef_Init(&def); 152 EXPECT_EQ(PyState_FindModule(&def), nullptr); 153 ASSERT_EQ(PyErr_Occurred(), nullptr); 154} 155 156static int recurseUntilLimit(PyThreadState* tstate, int limit) { 157 if (Py_EnterRecursiveCall("") != 0) { 158 return -1; 159 } 160 161 int result = 0; 162 if (_PyThreadState_GetRecursionDepth(tstate) != limit) { 163 result = recurseUntilLimit(tstate, limit); 164 } 165 Py_LeaveRecursiveCall(); 166 return result; 167} 168 169TEST_F(PystateExtensionApiTest, RecursionDepthStopsInfiniteRecursion) { 170 PyThreadState* tstate = PyThreadState_Get(); 171 Py_SetRecursionLimit(50); 172 int limit = Py_GetRecursionLimit() - 1; 173 EXPECT_EQ(recurseUntilLimit(tstate, limit), 0); 174 EXPECT_EQ(PyErr_Occurred(), nullptr); 175} 176 177TEST_F(PystateExtensionApiTest, 178 RecursionDepthExceedingLimitRaisesRecursionError) { 179 PyThreadState* tstate = PyThreadState_Get(); 180 Py_SetRecursionLimit(50); 181 int limit = Py_GetRecursionLimit() + 1; 182 EXPECT_EQ(recurseUntilLimit(tstate, limit), -1); 183 EXPECT_NE(PyErr_Occurred(), nullptr); 184 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_RecursionError)); 185} 186 187} // namespace testing 188} // namespace py