this repo has no description
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 ImportExtensionApiTest = ExtensionApi;
12
13TEST_F(ImportExtensionApiTest, AddNonExistingModuleReturnsNewModule) {
14 const char* c_name = "foo";
15 PyObject* pyname = PyUnicode_FromString(c_name);
16 PyObject* new_module = PyImport_AddModuleObject(pyname);
17 ASSERT_TRUE(PyModule_CheckExact(new_module));
18
19 PyObject* module_name = PyModule_GetNameObject(new_module);
20 EXPECT_TRUE(isUnicodeEqualsCStr(module_name, c_name));
21 Py_DECREF(module_name);
22
23 PyObject* module = testing::importGetModule(pyname);
24 EXPECT_EQ(new_module, module);
25 Py_DECREF(pyname);
26 Py_DECREF(module);
27}
28
29TEST_F(ImportExtensionApiTest, AddExistingModuleReturnsModule) {
30 PyObject* pyname = PyUnicode_FromString("sys");
31 PyObject* module = PyImport_AddModuleObject(pyname);
32 ASSERT_TRUE(PyModule_CheckExact(module));
33
34 Py_ssize_t refcnt = Py_REFCNT(module);
35 PyObject* module2 = PyImport_AddModuleObject(pyname);
36 EXPECT_EQ(refcnt, Py_REFCNT(module2));
37 EXPECT_EQ(module, module2);
38 Py_DECREF(pyname);
39}
40
41TEST_F(ImportExtensionApiTest, ExecCodeModulePopulatesModuleFromCAPI) {
42 PyObjectPtr code_object(
43 Py_CompileString("a = 21 + 21", "test_module.py", Py_file_input));
44 ASSERT_NE(code_object, nullptr);
45
46 PyObjectPtr module(PyImport_ExecCodeModule("test_module", code_object));
47 ASSERT_NE(module, nullptr);
48
49 PyObjectPtr a(PyObject_GetAttrString(module, "a"));
50 EXPECT_EQ(PyErr_Occurred(), nullptr);
51 EXPECT_TRUE(isLongEqualsLong(a, 42));
52}
53
54TEST_F(ImportExtensionApiTest, ExecCodeModuleAddsModuleToModules) {
55 PyObjectPtr code(
56 Py_CompileString("a = 21 + 21", "test_module.py", Py_file_input));
57 ASSERT_NE(code, nullptr);
58
59 PyObjectPtr module(PyImport_ExecCodeModule("test_module", code));
60 ASSERT_NE(module, nullptr);
61
62 PyImport_ImportModule("test_module");
63 ASSERT_EQ(PyErr_Occurred(), nullptr);
64 PyObjectPtr a(moduleGet("test_module", "a"));
65 EXPECT_EQ(PyErr_Occurred(), nullptr);
66 EXPECT_TRUE(isLongEqualsLong(a, 42));
67}
68
69TEST_F(ImportExtensionApiTest, ExecCodeModuleWithInvalidCodeDoesNotAddModule) {
70 PyObjectPtr code(
71 Py_CompileString("b = nonexistent.foo", "test_module.py", Py_file_input));
72 ASSERT_NE(code, nullptr);
73
74 PyObjectPtr module(PyImport_ExecCodeModule("test_module", code));
75 ASSERT_EQ(module, nullptr);
76 PyErr_Clear();
77
78 PyImport_ImportModule("test_module");
79 ASSERT_NE(PyErr_Occurred(), nullptr);
80 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ModuleNotFoundError));
81}
82
83TEST_F(ImportExtensionApiTest,
84 GetMagicNumberWithNonIntMagicNumberRaisesTypeError) {
85 PyObjectPtr importlib(PyImport_ImportModule("_frozen_importlib_external"));
86 ASSERT_EQ(PyObject_SetAttrString(importlib, "_RAW_MAGIC_NUMBER", Py_None), 0);
87 EXPECT_EQ(PyImport_GetMagicNumber(), -1);
88 ASSERT_NE(PyErr_Occurred(), nullptr);
89 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
90}
91
92TEST_F(ImportExtensionApiTest,
93 GetMagicNumberReturnsMagicNumberFromImportlibExternal) {
94 EXPECT_NE(PyImport_GetMagicNumber(), -1);
95 EXPECT_EQ(PyErr_Occurred(), nullptr);
96}
97
98TEST_F(ImportExtensionApiTest, GetModuleWithNotExistingModuleNameReturnsNull) {
99 PyObjectPtr name(PyUnicode_FromString("not_existing"));
100 EXPECT_EQ(PyImport_GetModule(name), nullptr);
101 EXPECT_EQ(PyErr_Occurred(), nullptr);
102}
103
104TEST_F(ImportExtensionApiTest,
105 GetModuleWithNotNotYetLoadedModuleNameReturnsNull) {
106 PyObjectPtr name(PyUnicode_FromString("test"));
107 EXPECT_EQ(PyImport_GetModule(name), nullptr);
108 EXPECT_EQ(PyErr_Occurred(), nullptr);
109}
110
111TEST_F(ImportExtensionApiTest,
112 GetModuleWithObjectRaisingNonKeyErrorPropagatesIt) {
113 PyRun_SimpleString(R"(
114class C:
115 def __hash__(self):
116 raise UserWarning("do not call me")
117
118c = C()
119 )");
120 PyObjectPtr c(mainModuleGet("c"));
121 EXPECT_EQ(PyImport_GetModule(c), nullptr);
122 ASSERT_NE(PyErr_Occurred(), nullptr);
123 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
124}
125
126// TODO(T67033642): Add a test verifying that a non-dict modules supresses
127// KeyError.
128TEST_F(ImportExtensionApiTest, GetModuleWithObjectRaisingKeyErrorPropagatesIt) {
129 PyRun_SimpleString(R"(
130class C:
131 def __hash__(self):
132 raise KeyError("key_error")
133
134c = C()
135 )");
136 PyObjectPtr c(mainModuleGet("c"));
137 EXPECT_EQ(PyImport_GetModule(c), nullptr);
138 ASSERT_NE(PyErr_Occurred(), nullptr);
139 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_KeyError));
140}
141
142TEST_F(ImportExtensionApiTest, GetModuleWithExistingModuleNameReturnsModule) {
143 PyObjectPtr imported_module(PyImport_ImportModule("test"));
144 ASSERT_TRUE(PyModule_Check(imported_module));
145 ASSERT_EQ(PyErr_Occurred(), nullptr);
146
147 PyObjectPtr name(PyUnicode_FromString("test"));
148 PyObjectPtr found_module(PyImport_GetModule(name));
149 EXPECT_EQ(PyErr_Occurred(), nullptr);
150 ASSERT_TRUE(PyModule_Check(found_module));
151 EXPECT_EQ(imported_module, found_module);
152}
153
154TEST_F(ImportExtensionApiTest, PyImportAcquireLockAndReleaseLockDoesNothing) {
155 _PyImport_AcquireLock();
156 EXPECT_EQ(_PyImport_ReleaseLock(), 1);
157}
158
159TEST_F(ImportExtensionApiTest,
160 PyImportReleaseLockWithoutAcquireLockReturnsMinusOne) {
161 EXPECT_EQ(_PyImport_ReleaseLock(), -1);
162}
163
164TEST_F(ImportExtensionApiTest, ImportInvalidModuleReturnsNull) {
165 PyObject* module = PyImport_ImportModule("this_file_should_not_exist");
166 ASSERT_EQ(module, nullptr);
167 EXPECT_NE(PyErr_Occurred(), nullptr);
168 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ModuleNotFoundError));
169}
170
171TEST_F(ImportExtensionApiTest, ImportModuleReturnsModule) {
172 PyObject* module = PyImport_ImportModule("operator");
173 ASSERT_NE(module, nullptr);
174 EXPECT_EQ(PyErr_Occurred(), nullptr);
175 EXPECT_TRUE(PyModule_Check(module));
176 Py_DECREF(module);
177}
178
179TEST_F(ImportExtensionApiTest,
180 ImportModuleWithSubmoduleReturnsLowestLevelModule) {
181 PyObjectPtr module(PyImport_ImportModule("collections.abc"));
182 ASSERT_NE(module, nullptr);
183 EXPECT_EQ(PyErr_Occurred(), nullptr);
184 EXPECT_TRUE(PyModule_Check(module));
185 PyObjectPtr name(PyModule_GetNameObject(module));
186 ASSERT_NE(name, nullptr);
187 EXPECT_TRUE(isUnicodeEqualsCStr(name, "collections.abc"));
188}
189
190TEST_F(ImportExtensionApiTest, ImportModuleNoBlockReturnsModule) {
191 PyObject* module = PyImport_ImportModuleNoBlock("operator");
192 ASSERT_NE(module, nullptr);
193 EXPECT_EQ(PyErr_Occurred(), nullptr);
194 EXPECT_TRUE(PyModule_Check(module));
195 Py_DECREF(module);
196}
197
198TEST_F(ImportExtensionApiTest, ImportFrozenModuleReturnsZeroPyro) {
199 int result = PyImport_ImportFrozenModule("operator");
200 EXPECT_EQ(PyErr_Occurred(), nullptr);
201 EXPECT_EQ(result, 0);
202}
203
204TEST_F(ImportExtensionApiTest, ImportReturnsModule) {
205 PyObject* name = PyUnicode_FromString("operator");
206 PyObject* module = PyImport_Import(name);
207 ASSERT_NE(module, nullptr);
208 EXPECT_EQ(PyErr_Occurred(), nullptr);
209 EXPECT_TRUE(PyModule_Check(module));
210 Py_DECREF(name);
211 Py_DECREF(module);
212}
213
214TEST_F(ImportExtensionApiTest, ImportFrozenModuleObjectReturnsZeroPyro) {
215 PyObject* name = PyUnicode_FromString("operator");
216 int result = PyImport_ImportFrozenModuleObject(name);
217 EXPECT_EQ(PyErr_Occurred(), nullptr);
218 EXPECT_EQ(result, 0);
219 Py_DECREF(name);
220}
221
222TEST_F(ImportExtensionApiTest, ImportModuleLevelReturnsModule) {
223 PyObject* globals = PyDict_New();
224 PyObject* fromlist = PyList_New(0);
225 PyObject* module =
226 PyImport_ImportModuleLevel("operator", globals, nullptr, fromlist, 0);
227 ASSERT_NE(module, nullptr);
228 EXPECT_EQ(PyErr_Occurred(), nullptr);
229 EXPECT_TRUE(PyModule_Check(module));
230 Py_DECREF(globals);
231 Py_DECREF(fromlist);
232 Py_DECREF(module);
233}
234
235TEST_F(ImportExtensionApiTest, ImportModuleLevelObjectReturnsModule) {
236 PyObject* name = PyUnicode_FromString("operator");
237 PyObject* globals = PyDict_New();
238 PyObject* fromlist = PyList_New(0);
239 PyObject* module =
240 PyImport_ImportModuleLevelObject(name, globals, nullptr, fromlist, 0);
241 ASSERT_NE(module, nullptr);
242 EXPECT_EQ(PyErr_Occurred(), nullptr);
243 EXPECT_TRUE(PyModule_Check(module));
244 Py_DECREF(globals);
245 Py_DECREF(fromlist);
246 Py_DECREF(name);
247 Py_DECREF(module);
248}
249
250TEST_F(ImportExtensionApiTest,
251 ImportModuleLevelObjectWithNullNameRaisesValueError) {
252 PyObject* globals = PyDict_New();
253 PyObject* fromlist = PyList_New(0);
254 PyObject* module =
255 PyImport_ImportModuleLevelObject(nullptr, globals, nullptr, fromlist, 0);
256 EXPECT_EQ(module, nullptr);
257 EXPECT_NE(PyErr_Occurred(), nullptr);
258 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
259 Py_DECREF(globals);
260 Py_DECREF(fromlist);
261}
262
263TEST_F(ImportExtensionApiTest,
264 ImportModuleLevelObjectWithNegativeLevelRaisesValueError) {
265 PyObject* name = PyUnicode_FromString("operator");
266 PyObject* globals = PyDict_New();
267 PyObject* fromlist = PyList_New(0);
268 PyObject* module =
269 PyImport_ImportModuleLevelObject(name, globals, nullptr, fromlist, -1);
270 EXPECT_EQ(module, nullptr);
271 EXPECT_NE(PyErr_Occurred(), nullptr);
272 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
273 Py_DECREF(globals);
274 Py_DECREF(fromlist);
275 Py_DECREF(name);
276}
277
278TEST_F(ImportExtensionApiTest,
279 ImportModuleLevelObjectWithNullGlobalsRaisesKeyError) {
280 PyObject* name = PyUnicode_FromString("operator");
281 PyObject* fromlist = PyList_New(0);
282 PyObject* module =
283 PyImport_ImportModuleLevelObject(name, nullptr, nullptr, fromlist, 1);
284 EXPECT_EQ(module, nullptr);
285 EXPECT_NE(PyErr_Occurred(), nullptr);
286 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_KeyError));
287 Py_DECREF(fromlist);
288 Py_DECREF(name);
289}
290
291} // namespace testing
292} // namespace py