this repo has no description
at trunk 208 lines 7.5 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include <sys/stat.h> 3#include <sys/types.h> 4 5#include "gtest/gtest.h" 6 7#include "module-builtins.h" 8#include "objects.h" 9#include "runtime.h" 10#include "test-utils.h" 11 12namespace py { 13namespace testing { 14 15using ImportlibTest = RuntimeFixture; 16 17TEST_F(ImportlibTest, SimpleImport) { 18 TemporaryDirectory tempdir; 19 writeFile(tempdir.path + "foo.py", "x = 42"); 20 writeFile(tempdir.path + "bar.py", "x = 67"); 21 22 HandleScope scope(thread_); 23 List sys_path(&scope, moduleAtByCStr(runtime_, "sys", "path")); 24 sys_path.setNumItems(0); 25 Str temp_dir_str(&scope, runtime_->newStrFromCStr(tempdir.path.c_str())); 26 runtime_->listAdd(thread_, sys_path, temp_dir_str); 27 ASSERT_FALSE(runFromCStr(runtime_, R"( 28import foo 29import bar 30)") 31 .isError()); 32 Object foo_obj(&scope, mainModuleAt(runtime_, "foo")); 33 ASSERT_TRUE(foo_obj.isModule()); 34 Module foo(&scope, *foo_obj); 35 EXPECT_TRUE(isStrEqualsCStr(foo.name(), "foo")); 36 37 Object name(&scope, moduleAtById(thread_, foo, ID(__name__))); 38 EXPECT_TRUE(isStrEqualsCStr(*name, "foo")); 39 Object package(&scope, moduleAtById(thread_, foo, ID(__package__))); 40 EXPECT_TRUE(isStrEqualsCStr(*package, "")); 41 Object doc(&scope, moduleAtById(thread_, foo, ID(__doc__))); 42 EXPECT_TRUE(doc.isNoneType()); 43 Str str_x(&scope, runtime_->newStrFromCStr("x")); 44 Object x(&scope, moduleAt(foo, str_x)); 45 EXPECT_TRUE(isIntEqualsWord(*x, 42)); 46} 47 48TEST_F(ImportlibTest, ImportsEmptyModule) { 49 TemporaryDirectory tempdir; 50 std::string module_dir = tempdir.path + "somedir"; 51 ASSERT_EQ(mkdir(module_dir.c_str(), S_IRWXU), 0); 52 53 HandleScope scope(thread_); 54 List sys_path(&scope, moduleAtByCStr(runtime_, "sys", "path")); 55 sys_path.setNumItems(0); 56 Str temp_dir_str(&scope, runtime_->newStrFromCStr(tempdir.path.c_str())); 57 runtime_->listAdd(thread_, sys_path, temp_dir_str); 58 ASSERT_FALSE(runFromCStr(runtime_, R"( 59import somedir 60)") 61 .isError()); 62 Object somedir(&scope, mainModuleAt(runtime_, "somedir")); 63 ASSERT_TRUE(somedir.isModule()); 64} 65 66TEST_F(ImportlibTest, ImportsModuleWithInitPy) { 67 TemporaryDirectory tempdir; 68 std::string module_dir = tempdir.path + "bar"; 69 ASSERT_EQ(mkdir(module_dir.c_str(), S_IRWXU), 0); 70 writeFile(module_dir + "/__init__.py", "y = 13"); 71 72 HandleScope scope(thread_); 73 List sys_path(&scope, moduleAtByCStr(runtime_, "sys", "path")); 74 sys_path.setNumItems(0); 75 Str temp_dir_str(&scope, runtime_->newStrFromCStr(tempdir.path.c_str())); 76 runtime_->listAdd(thread_, sys_path, temp_dir_str); 77 ASSERT_FALSE(runFromCStr(runtime_, R"( 78import bar 79)") 80 .isError()); 81 Object bar_obj(&scope, mainModuleAt(runtime_, "bar")); 82 ASSERT_TRUE(bar_obj.isModule()); 83 Module bar(&scope, *bar_obj); 84 Str str_y(&scope, runtime_->newStrFromCStr("y")); 85 Object y(&scope, moduleAt(bar, str_y)); 86 EXPECT_TRUE(isIntEqualsWord(*y, 13)); 87} 88 89TEST_F(ImportlibTest, SubModuleImport) { 90 TemporaryDirectory tempdir; 91 std::string module_dir = tempdir.path + "baz"; 92 ASSERT_EQ(mkdir(module_dir.c_str(), S_IRWXU), 0); 93 writeFile(module_dir + "/blam.py", "z = 7"); 94 95 HandleScope scope(thread_); 96 List sys_path(&scope, moduleAtByCStr(runtime_, "sys", "path")); 97 sys_path.setNumItems(0); 98 Str temp_dir_str(&scope, runtime_->newStrFromCStr(tempdir.path.c_str())); 99 runtime_->listAdd(thread_, sys_path, temp_dir_str); 100 ASSERT_FALSE(runFromCStr(runtime_, R"( 101import baz.blam 102)") 103 .isError()); 104 Object baz_obj(&scope, mainModuleAt(runtime_, "baz")); 105 ASSERT_TRUE(baz_obj.isModule()); 106 Module baz(&scope, *baz_obj); 107 Str blam_str(&scope, runtime_->newStrFromCStr("blam")); 108 Object blam_obj(&scope, moduleAt(baz, blam_str)); 109 ASSERT_TRUE(blam_obj.isModule()); 110 Module blam(&scope, *blam_obj); 111 112 Str str_z(&scope, runtime_->newStrFromCStr("z")); 113 Object z(&scope, moduleAt(blam, str_z)); 114 EXPECT_TRUE(isIntEqualsWord(*z, 7)); 115} 116 117TEST_F(ImportlibTest, FromImportsWithRelativeName) { 118 TemporaryDirectory tempdir; 119 writeFile(tempdir.path + "a.py", "val = 'top val'"); 120 std::string submodule = tempdir.path + "submodule"; 121 ASSERT_EQ(mkdir(submodule.c_str(), S_IRWXU), 0); 122 writeFile(submodule + "/__init__.py", "from .a import val"); 123 writeFile(submodule + "/a.py", "val = 'submodule val'"); 124 125 HandleScope scope(thread_); 126 List sys_path(&scope, moduleAtByCStr(runtime_, "sys", "path")); 127 sys_path.setNumItems(0); 128 Str temp_dir_str(&scope, runtime_->newStrFromCStr(tempdir.path.c_str())); 129 runtime_->listAdd(thread_, sys_path, temp_dir_str); 130 ASSERT_FALSE(runFromCStr(runtime_, R"( 131import a 132import submodule 133from submodule.a import val 134)") 135 .isError()); 136 137 Object top_val(&scope, moduleAtByCStr(runtime_, "a", "val")); 138 EXPECT_TRUE(isStrEqualsCStr(*top_val, "top val")); 139 Object subdir_val(&scope, moduleAtByCStr(runtime_, "submodule", "val")); 140 EXPECT_TRUE(isStrEqualsCStr(*subdir_val, "submodule val")); 141 Object main_val_from_submodule(&scope, mainModuleAt(runtime_, "val")); 142 EXPECT_TRUE(isStrEqualsCStr(*main_val_from_submodule, "submodule val")); 143} 144 145TEST_F(ImportlibTest, BuiltinsDunderImportWithSubmoduleReturnsToplevelModule) { 146 TemporaryDirectory tempdir; 147 std::string topmodule_dir = tempdir.path + "top"; 148 ASSERT_EQ(mkdir(topmodule_dir.c_str(), S_IRWXU), 0); 149 std::string submodule_dir = tempdir.path + "top/sub"; 150 ASSERT_EQ(mkdir(submodule_dir.c_str(), S_IRWXU), 0); 151 writeFile(submodule_dir + "/__init__.py", "initialized = True"); 152 153 HandleScope scope(thread_); 154 List sys_path(&scope, moduleAtByCStr(runtime_, "sys", "path")); 155 sys_path.setNumItems(0); 156 Str temp_dir_str(&scope, runtime_->newStrFromCStr(tempdir.path.c_str())); 157 runtime_->listAdd(thread_, sys_path, temp_dir_str); 158 159 Object subname(&scope, runtime_->newStrFromCStr("top.sub")); 160 Object globals(&scope, NoneType::object()); 161 Object locals(&scope, NoneType::object()); 162 Object fromlist(&scope, runtime_->emptyTuple()); 163 Object level(&scope, runtime_->newInt(0)); 164 Object m0(&scope, 165 thread_->invokeFunction5(ID(builtins), ID(__import__), subname, 166 globals, locals, fromlist, level)); 167 ASSERT_TRUE(m0.isModule()); 168 EXPECT_TRUE(isStrEqualsCStr(Module::cast(*m0).name(), "top")); 169 170 Object initialized(&scope, 171 moduleAtByCStr(runtime_, "top.sub", "initialized")); 172 EXPECT_EQ(initialized, Bool::trueObj()); 173 174 Object topname(&scope, runtime_->newStrFromCStr("top")); 175 Object m1(&scope, 176 thread_->invokeFunction5(ID(builtins), ID(__import__), topname, 177 globals, locals, fromlist, level)); 178 EXPECT_EQ(m0, m1); 179 180 // Import a 2nd time so we hit the cache. 181 Object m2(&scope, 182 thread_->invokeFunction5(ID(builtins), ID(__import__), subname, 183 globals, locals, fromlist, level)); 184 EXPECT_EQ(m0, m2); 185 Object m3(&scope, 186 thread_->invokeFunction5(ID(builtins), ID(__import__), topname, 187 globals, locals, fromlist, level)); 188 EXPECT_EQ(m0, m3); 189} 190 191TEST_F(ImportlibTest, ImportFindsDefaultModules) { 192 EXPECT_FALSE(runFromCStr(runtime_, "import stat").isError()); 193} 194 195TEST_F(ImportlibTest, SysMetaPathIsList) { 196 HandleScope scope(thread_); 197 ASSERT_FALSE(runFromCStr(runtime_, R"( 198import sys 199 200meta_path = sys.meta_path 201)") 202 .isError()); 203 Object meta_path(&scope, mainModuleAt(runtime_, "meta_path")); 204 ASSERT_TRUE(meta_path.isList()); 205} 206 207} // namespace testing 208} // namespace py