this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "under-imp-module.h"
3
4#include "cpython-types.h"
5#include "gtest/gtest.h"
6
7#include "builtins.h"
8#include "runtime.h"
9#include "test-utils.h"
10
11namespace py {
12namespace testing {
13
14using UnderImpModuleTest = RuntimeFixture;
15using ImportBuiltinsDeathTest = RuntimeFixture;
16using ImportBuiltinsTest = RuntimeFixture;
17
18TEST_F(UnderImpModuleTest, ModuleImporting) {
19 ASSERT_FALSE(runFromCStr(runtime_, R"(
20import _imp
21 )")
22 .isError());
23 RawObject imp = mainModuleAt(runtime_, "_imp");
24 EXPECT_TRUE(imp.isModule());
25}
26
27TEST_F(ImportBuiltinsTest, AcquireLockAndReleaseLockWorks) {
28 runBuiltin(FUNC(_imp, acquire_lock));
29 runBuiltin(FUNC(_imp, release_lock));
30}
31
32TEST_F(ImportBuiltinsTest, CreateBuiltinWithoutArgsRaisesTypeError) {
33 EXPECT_TRUE(raised(runFromCStr(runtime_, R"(
34import _imp
35_imp.create_builtin()
36)"),
37 LayoutId::kTypeError));
38}
39
40TEST_F(ImportBuiltinsTest, CreateBuiltinWithoutSpecNameRaisesTypeError) {
41 EXPECT_TRUE(raised(runFromCStr(runtime_, R"(
42import _imp
43_imp.create_builtin(123)
44)"),
45 LayoutId::kTypeError));
46}
47
48TEST_F(ImportBuiltinsTest, CreateBuiltinWithNonStrSpecNameRaisesTypeError) {
49 // Mock of importlib._bootstrap.ModuleSpec
50 EXPECT_TRUE(raised(runFromCStr(runtime_, R"(
51import _imp
52class DummyModuleSpec:
53 def __init__(self, name):
54 self.name = name
55spec = DummyModuleSpec(5)
56_imp.create_builtin(spec)
57)"),
58 LayoutId::kTypeError));
59}
60
61TEST_F(ImportBuiltinsTest, CreateBuiltinWithNonExistentModuleReturnsNone) {
62 // Mock of importlib._bootstrap.ModuleSpec
63 ASSERT_FALSE(runFromCStr(runtime_, R"(
64import _imp
65class DummyModuleSpec:
66 def __init__(self, name):
67 self.name = name
68spec = DummyModuleSpec("non_existent_module")
69result = _imp.create_builtin(spec)
70)")
71 .isError());
72 HandleScope scope(thread_);
73 Object result(&scope, mainModuleAt(runtime_, "result"));
74 EXPECT_TRUE(result.isNoneType());
75}
76
77TEST_F(ImportBuiltinsTest, CreateBuiltinReturnsModule) {
78 // Mock of importlib._bootstrap.ModuleSpec
79 ASSERT_FALSE(runFromCStr(runtime_, R"(
80import _imp
81class DummyModuleSpec:
82 def __init__(self, name):
83 self.name = name
84spec = DummyModuleSpec("errno")
85result = _imp.create_builtin(spec)
86)")
87 .isError());
88 HandleScope scope(thread_);
89 Object result(&scope, mainModuleAt(runtime_, "result"));
90 ASSERT_TRUE(result.isModule());
91 EXPECT_TRUE(isStrEqualsCStr(Module::cast(*result).name(), "errno"));
92}
93
94TEST_F(ImportBuiltinsTest, CreateBuiltinWithExArgsReturnsModule) {
95 // Mock of importlib._bootstrap.ModuleSpec
96 ASSERT_FALSE(runFromCStr(runtime_, R"(
97import _imp
98class DummyModuleSpec:
99 def __init__(self, name):
100 self.name = name
101spec = (DummyModuleSpec("errno"),)
102result = _imp.create_builtin(*spec)
103)")
104 .isError());
105 HandleScope scope(thread_);
106 Object result(&scope, mainModuleAt(runtime_, "result"));
107 ASSERT_TRUE(result.isModule());
108 EXPECT_TRUE(isStrEqualsCStr(Module::cast(*result).name(), "errno"));
109}
110
111TEST_F(ImportBuiltinsTest, ExecBuiltinWithNonModuleReturnsZero) {
112 HandleScope scope(thread_);
113 Int not_mod(&scope, runtime_->newInt(1));
114 Object a(&scope, runBuiltin(FUNC(_imp, exec_builtin), not_mod));
115 EXPECT_TRUE(isIntEqualsWord(*a, 0));
116}
117
118TEST_F(ImportBuiltinsTest, ExecBuiltinWithModuleWithNoDefReturnsZero) {
119 ASSERT_FALSE(runFromCStr(runtime_, R"(
120class DummyModuleSpec():
121 def __init__(self, name):
122 self.name = name
123spec = DummyModuleSpec("errno")
124)")
125 .isError());
126 HandleScope scope(thread_);
127 Object spec(&scope, mainModuleAt(runtime_, "spec"));
128 Object module(&scope, runBuiltin(FUNC(_imp, create_builtin), spec));
129 ASSERT_TRUE(module.isModule());
130
131 Object a(&scope, runBuiltin(FUNC(_imp, exec_builtin), module));
132 EXPECT_TRUE(isIntEqualsWord(*a, 0));
133}
134
135TEST_F(ImportBuiltinsTest, ExecBuiltinWithSingleSlotExecutesCorrectly) {
136 using slot_func = int (*)(Module*);
137 slot_func mod_exec = [](Module* module) {
138 module->setName(Thread::current()->runtime()->newStrFromCStr("testing"));
139 return 0;
140 };
141
142 static PyModuleDef_Slot slots[] = {
143 {Py_mod_exec, reinterpret_cast<void*>(mod_exec)},
144 {0, nullptr},
145 };
146 static PyModuleDef def = {
147 // Empty header to mimic a PyModuleDef_HEAD_INIT
148 {{0, 0}, nullptr, 0, nullptr}, "mymodule", nullptr, 0, nullptr, slots,
149 };
150
151 HandleScope scope(thread_);
152 Str name(&scope, runtime_->newStrFromCStr("mymodule"));
153 Module module(&scope, runtime_->newModule(name));
154 module.setDef(runtime_->newIntFromCPtr(&def));
155
156 Object a(&scope, runBuiltin(FUNC(_imp, exec_builtin), module));
157 EXPECT_TRUE(isIntEqualsWord(*a, 0));
158
159 Str mod_name(&scope, module.name());
160 EXPECT_TRUE(mod_name.equalsCStr("testing"));
161}
162
163TEST_F(ImportBuiltinsTest, ExecDynamic) {
164 ASSERT_FALSE(runFromCStr(runtime_, R"(
165import _imp
166mod = _imp.exec_dynamic("foo")
167 )")
168 .isError());
169 HandleScope scope(thread_);
170 Object mod(&scope, mainModuleAt(runtime_, "mod"));
171 ASSERT_TRUE(mod.isNoneType());
172}
173
174TEST_F(ImportBuiltinsTest, IsBuiltinReturnsZero) {
175 HandleScope scope(thread_);
176 Object module_name(&scope, runtime_->newStrFromCStr("foo"));
177 Object result(&scope, runBuiltin(FUNC(_imp, is_builtin), module_name));
178 EXPECT_TRUE(isIntEqualsWord(*result, 0));
179}
180
181TEST_F(ImportBuiltinsTest, IsBuiltinReturnsOne) {
182 HandleScope scope(thread_);
183 Object module_name(&scope, runtime_->newStrFromCStr("errno"));
184 Object result(&scope, runBuiltin(FUNC(_imp, is_builtin), module_name));
185 EXPECT_TRUE(isIntEqualsWord(*result, 1));
186}
187
188TEST_F(ImportBuiltinsTest, IsBuiltinWithFrozenPackageReturnsZero) {
189 HandleScope scope(thread_);
190 Object module_name(&scope, runtime_->newStrFromCStr("compiler"));
191 Object result(&scope, runBuiltin(FUNC(_imp, is_builtin), module_name));
192 EXPECT_TRUE(isIntEqualsWord(*result, 0));
193}
194
195TEST_F(ImportBuiltinsTest, IsFrozenWithFrozenModuleReturnsTrue) {
196 HandleScope scope(thread_);
197 Object module_name(&scope, runtime_->newStrFromCStr("zipimport"));
198 Object result(&scope, runBuiltin(FUNC(_imp, is_frozen), module_name));
199 ASSERT_TRUE(result.isBool());
200 EXPECT_TRUE(Bool::cast(*result).value());
201}
202
203TEST_F(ImportBuiltinsTest, IsFrozenWithNewModuleReturnsFalse) {
204 HandleScope scope(thread_);
205 Object module_name(&scope, runtime_->newStrFromCStr("foo"));
206 Object result(&scope, runBuiltin(FUNC(_imp, is_frozen), module_name));
207 ASSERT_TRUE(result.isBool());
208 EXPECT_FALSE(Bool::cast(*result).value());
209}
210
211TEST_F(ImportBuiltinsTest, IsFrozenPackageWithNotFrozenModuleReturnsFalse) {
212 HandleScope scope(thread_);
213 Object module_name(&scope, runtime_->newStrFromCStr("foo"));
214 Object result(&scope, runBuiltin(FUNC(_imp, is_frozen_package), module_name));
215 ASSERT_TRUE(result.isBool());
216 EXPECT_FALSE(Bool::cast(*result).value());
217}
218
219TEST_F(ImportBuiltinsTest,
220 IsFrozenPackageWithFrozenModuleNotAPackageReturnsFalse) {
221 HandleScope scope(thread_);
222 Object module_name(&scope, runtime_->newStrFromCStr("array"));
223 Object result(&scope, runBuiltin(FUNC(_imp, is_frozen_package), module_name));
224 ASSERT_TRUE(result.isBool());
225 EXPECT_FALSE(Bool::cast(*result).value());
226}
227
228TEST_F(ImportBuiltinsTest, IsFrozenPackageWithFrozenPackageReturnsTrue) {
229 HandleScope scope(thread_);
230 Object module_name(&scope, runtime_->newStrFromCStr("compiler"));
231 Object result(&scope, runBuiltin(FUNC(_imp, is_frozen_package), module_name));
232 ASSERT_TRUE(result.isBool());
233 EXPECT_TRUE(Bool::cast(*result).value());
234}
235
236TEST_F(ImportBuiltinsTest, GetFrozenObjectWithNonStrRaisesTypeError) {
237 HandleScope scope(thread_);
238 Object non_str(&scope, runtime_->newInt(5));
239 EXPECT_TRUE(raisedWithStr(runBuiltin(FUNC(_imp, get_frozen_object), non_str),
240 LayoutId::kTypeError,
241 "get_frozen_object requires a str object"));
242}
243
244TEST_F(ImportBuiltinsTest,
245 GetFrozenObjectWithNonFrozenModuleRaisesImportError) {
246 HandleScope scope(thread_);
247 Object module_name(&scope, runtime_->newStrFromCStr("nonexistent"));
248 EXPECT_TRUE(raisedWithStr(
249 runBuiltin(FUNC(_imp, get_frozen_object), module_name),
250 LayoutId::kImportError, "No such frozen object named 'nonexistent'"));
251}
252
253TEST_F(ImportBuiltinsTest, GetFrozenObjectWithFrozenModuleReturnsCode) {
254 HandleScope scope(thread_);
255 Object module_name(&scope, runtime_->newStrFromCStr("zipimport"));
256 Object result(&scope, runBuiltin(FUNC(_imp, get_frozen_object), module_name));
257 ASSERT_TRUE(result.isCode());
258}
259
260TEST_F(ImportBuiltinsTest, LockHeldReturnsFalseInitially) {
261 EXPECT_EQ(runBuiltin(FUNC(_imp, lock_held)), Bool::falseObj());
262}
263
264TEST_F(ImportBuiltinsTest, LockHeldReturnsTrueAfterAcquireLock) {
265 ASSERT_EQ(runBuiltin(FUNC(_imp, acquire_lock)), NoneType::object());
266 EXPECT_EQ(runBuiltin(FUNC(_imp, lock_held)), Bool::trueObj());
267 ASSERT_EQ(runBuiltin(FUNC(_imp, release_lock)), NoneType::object());
268}
269
270TEST_F(ImportBuiltinsTest, LockHeldReturnsFalseAfterReleaseLock) {
271 ASSERT_EQ(runBuiltin(FUNC(_imp, acquire_lock)), NoneType::object());
272 ASSERT_EQ(runBuiltin(FUNC(_imp, lock_held)), Bool::trueObj());
273 ASSERT_EQ(runBuiltin(FUNC(_imp, release_lock)), NoneType::object());
274 EXPECT_EQ(runBuiltin(FUNC(_imp, lock_held)), Bool::falseObj());
275}
276
277TEST_F(ImportBuiltinsTest, ReleaseLockWithoutAcquireRaisesRuntimeError) {
278 HandleScope scope(thread_);
279 Object result(&scope, runBuiltin(FUNC(_imp, release_lock)));
280 EXPECT_TRUE(raised(*result, LayoutId::kRuntimeError));
281}
282
283TEST_F(ImportBuiltinsTest, AcquireLockCheckRecursiveCallsWorks) {
284 HandleScope scope(thread_);
285 runBuiltin(FUNC(_imp, acquire_lock));
286 runBuiltin(FUNC(_imp, acquire_lock));
287 runBuiltin(FUNC(_imp, release_lock));
288 runBuiltin(FUNC(_imp, release_lock));
289 // Make sure that additional releases raise.
290 Object result(&scope, runBuiltin(FUNC(_imp, release_lock)));
291 EXPECT_TRUE(result.isError());
292}
293
294TEST_F(ImportBuiltinsTest, CreateExistingBuiltinDoesNotOverride) {
295 // Mock of importlib._bootstrap.ModuleSpec
296 ASSERT_FALSE(runFromCStr(runtime_, R"(
297import _imp
298class DummyModuleSpec:
299 def __init__(self, name):
300 self.name = name
301spec = (DummyModuleSpec("errno"),)
302result1 = _imp.create_builtin(*spec)
303result2 = _imp.create_builtin(*spec)
304)")
305 .isError());
306 HandleScope scope(thread_);
307 Object result1(&scope, mainModuleAt(runtime_, "result1"));
308 ASSERT_TRUE(result1.isModule());
309 EXPECT_TRUE(isStrEqualsCStr(Module::cast(*result1).name(), "errno"));
310 Object result2(&scope, mainModuleAt(runtime_, "result2"));
311 ASSERT_TRUE(result2.isModule());
312 EXPECT_TRUE(isStrEqualsCStr(Module::cast(*result2).name(), "errno"));
313 EXPECT_EQ(*result1, *result2);
314}
315
316} // namespace testing
317} // namespace py