1 // sol2 2 3 // The MIT License (MIT) 4 5 // Copyright (c) 2013-2018 Rapptz, ThePhD and contributors 6 7 // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 // this software and associated documentation files (the "Software"), to deal in 9 // the Software without restriction, including without limitation the rights to 10 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 // the Software, and to permit persons to whom the Software is furnished to do so, 12 // subject to the following conditions: 13 14 // The above copyright notice and this permission notice shall be included in all 15 // copies or substantial portions of the Software. 16 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24 #include "test_sol.hpp" 25 26 #include <catch.hpp> 27 28 #include <iostream> 29 30 TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") { 31 sol::state lua; 32 sol::stack_guard luasg(lua); 33 lua.open_libraries(sol::lib::base); 34 35 auto result1 = lua.safe_script("f = function() return test end", sol::script_pass_on_error); 36 REQUIRE(result1.valid()); 37 sol::function f = lua["f"]; 38 39 sol::environment env_f(lua, sol::create); 40 env_f["test"] = 31; 41 sol::set_environment(env_f, f); 42 43 int result = f(); 44 REQUIRE(result == 31); 45 46 auto result2 = lua.safe_script("g = function() test = 5 end", sol::script_pass_on_error); 47 REQUIRE(result2.valid()); 48 sol::function g = lua["g"]; 49 sol::environment env_g(lua, sol::create); 50 env_g.set_on(g); 51 52 g(); 53 54 int test = env_g["test"]; 55 REQUIRE(test == 5); 56 57 sol::object global_test = lua["test"]; 58 REQUIRE(!global_test.valid()); 59 60 auto result3 = lua.safe_script("h = function() end", sol::script_pass_on_error); 61 REQUIRE(result3.valid()); 62 63 lua.set_function("check_f_env", __anoneb3148600102(sol::object target) 64 [&lua, &env_f](sol::object target) { 65 sol::stack_guard sg(lua); 66 sol::environment target_env(sol::env_key, target); 67 int test_env_f = env_f["test"]; 68 int test_target_env = target_env["test"]; 69 REQUIRE(test_env_f == test_target_env); 70 REQUIRE(test_env_f == 31); 71 REQUIRE(env_f == target_env); 72 }); 73 lua.set_function("check_g_env", __anoneb3148600202(sol::function target) 74 [&lua, &env_g](sol::function target) { 75 sol::stack_guard sg(lua); 76 sol::environment target_env = sol::get_environment(target); 77 int test_env_g = env_g["test"]; 78 int test_target_env = target_env["test"]; 79 REQUIRE(test_env_g == test_target_env); 80 REQUIRE(test_env_g == 5); 81 REQUIRE(env_g == target_env); 82 }); 83 lua.set_function("check_h_env", __anoneb3148600302(sol::function target) 84 [&lua](sol::function target) { 85 sol::stack_guard sg(lua); 86 sol::environment target_env = sol::get_environment(target); 87 }); 88 89 auto checkf = lua.safe_script("check_f_env(f)"); 90 REQUIRE(checkf.valid()); 91 auto checkg = lua.safe_script("check_g_env(g)"); 92 REQUIRE(checkg.valid()); 93 auto checkh = lua.safe_script("check_h_env(h)"); 94 REQUIRE(checkh.valid()); 95 } 96 97 TEST_CASE("environments/shadowing", "Environments can properly shadow and fallback on variables") { 98 99 sol::state lua; 100 lua["b"] = 2142; 101 102 SECTION("no fallback") { 103 sol::environment plain_env(lua, sol::create); 104 auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); 105 REQUIRE(result1.valid()); 106 sol::optional<int> maybe_env_a = plain_env["a"]; 107 sol::optional<int> maybe_global_a = lua["a"]; 108 sol::optional<int> maybe_env_b = plain_env["b"]; 109 sol::optional<int> maybe_global_b = lua["b"]; 110 111 REQUIRE(maybe_env_a != sol::nullopt); 112 REQUIRE(maybe_env_a.value() == 24); 113 REQUIRE(maybe_env_b == sol::nullopt); 114 115 REQUIRE(maybe_global_a == sol::nullopt); 116 REQUIRE(maybe_global_b != sol::nullopt); 117 REQUIRE(maybe_global_b.value() == 2142); 118 } 119 SECTION("fallback") { 120 sol::environment env_with_fallback(lua, sol::create, lua.globals()); 121 auto result1 = lua.safe_script("a = 56", env_with_fallback, sol::script_pass_on_error); 122 REQUIRE(result1.valid()); 123 sol::optional<int> maybe_env_a = env_with_fallback["a"]; 124 sol::optional<int> maybe_global_a = lua["a"]; 125 sol::optional<int> maybe_env_b = env_with_fallback["b"]; 126 sol::optional<int> maybe_global_b = lua["b"]; 127 128 REQUIRE(maybe_env_a != sol::nullopt); 129 REQUIRE(maybe_env_a.value() == 56); 130 REQUIRE(maybe_env_b != sol::nullopt); 131 REQUIRE(maybe_env_b.value() == 2142); 132 133 REQUIRE(maybe_global_a == sol::nullopt); 134 REQUIRE(maybe_global_b != sol::nullopt); 135 REQUIRE(maybe_global_b.value() == 2142); 136 } 137 SECTION("from name") { 138 sol::environment env_with_fallback(lua, sol::create, lua.globals()); 139 lua["env"] = env_with_fallback; 140 sol::environment env = lua["env"]; 141 auto result1 = lua.safe_script("a = 56", env, sol::script_pass_on_error); 142 REQUIRE(result1.valid()); 143 sol::optional<int> maybe_env_a = env["a"]; 144 sol::optional<int> maybe_global_a = lua["a"]; 145 sol::optional<int> maybe_env_b = env["b"]; 146 sol::optional<int> maybe_global_b = lua["b"]; 147 148 REQUIRE(maybe_env_a != sol::nullopt); 149 REQUIRE(maybe_env_a.value() == 56); 150 REQUIRE(maybe_env_b != sol::nullopt); 151 REQUIRE(maybe_env_b.value() == 2142); 152 153 REQUIRE(maybe_global_a == sol::nullopt); 154 REQUIRE(maybe_global_b != sol::nullopt); 155 REQUIRE(maybe_global_b.value() == 2142); 156 } 157 SECTION("name with newtable") { 158 lua["blank_env"] = sol::new_table(0, 1); 159 sol::environment plain_env = lua["blank_env"]; 160 auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); 161 REQUIRE(result1.valid()); 162 163 sol::optional<int> maybe_env_a = plain_env["a"]; 164 sol::optional<int> maybe_global_a = lua["a"]; 165 sol::optional<int> maybe_env_b = plain_env["b"]; 166 sol::optional<int> maybe_global_b = lua["b"]; 167 168 REQUIRE(maybe_env_a != sol::nullopt); 169 REQUIRE(maybe_env_a.value() == 24); 170 REQUIRE(maybe_env_b == sol::nullopt); 171 172 REQUIRE(maybe_global_a == sol::nullopt); 173 REQUIRE(maybe_global_b != sol::nullopt); 174 REQUIRE(maybe_global_b.value() == 2142); 175 } 176 } 177 178 TEST_CASE("environments/functions", "see if environments on functions are working properly") { 179 180 SECTION("basic") { 181 sol::state lua; 182 183 auto result1 = lua.safe_script("a = function() return 5 end", sol::script_pass_on_error); 184 REQUIRE(result1.valid()); 185 186 sol::function a = lua["a"]; 187 188 int result0 = a(); 189 REQUIRE(result0 == 5); 190 191 sol::environment env(lua, sol::create); 192 sol::set_environment(env, a); 193 194 int value = a(); 195 REQUIRE(value == 5); 196 } 197 SECTION("return environment value") { 198 sol::state lua; 199 200 auto result1 = lua.safe_script("a = function() return test end", sol::script_pass_on_error); 201 REQUIRE(result1.valid()); 202 203 sol::function a = lua["a"]; 204 sol::environment env(lua, sol::create); 205 env["test"] = 5; 206 env.set_on(a); 207 208 // the function returns the value from the environment table 209 int result = a(); 210 REQUIRE(result == 5); 211 } 212 213 SECTION("set environment value") { 214 sol::state lua; 215 auto result1 = lua.safe_script("a = function() test = 5 end", sol::script_pass_on_error); 216 REQUIRE(result1.valid()); 217 218 sol::function a = lua["a"]; 219 sol::environment env(lua, sol::create); 220 sol::set_environment(env, a); 221 222 a(); 223 224 // the value can be retrieved from the env table 225 int result = env["test"]; 226 REQUIRE(result == 5); 227 228 // the global environment is not polluted 229 auto gtest = lua["test"]; 230 REQUIRE(!gtest.valid()); 231 } 232 } 233 234 TEST_CASE("environments/this_environment", "test various situations of pulling out an environment") { 235 static std::string code = "return (f(10))"; 236 237 sol::state lua; 238 __anoneb3148600402(sol::this_environment te, int x, sol::this_state ts) 239 lua["f"] = [](sol::this_environment te, int x, sol::this_state ts) { 240 if (te) { 241 sol::environment& env = te; 242 return x + static_cast<int>(env["x"]); 243 } 244 sol::state_view lua = ts; 245 return x + static_cast<int>(lua["x"]); 246 }; 247 248 sol::environment e(lua, sol::create, lua.globals()); 249 lua["x"] = 5; 250 e["x"] = 20; 251 SECTION("from Lua script") { 252 auto result1 = lua.safe_script(code, e, sol::script_pass_on_error); 253 REQUIRE(result1.valid()); 254 int value = result1; 255 REQUIRE(value == 30); 256 } 257 SECTION("from C++") { 258 sol::function f = lua["f"]; 259 e.set_on(f); 260 int value = f(10); 261 REQUIRE(value == 30); 262 } 263 SECTION("from C++, with no env") { 264 sol::function f = lua["f"]; 265 int value = f(10); 266 REQUIRE(value == 15); 267 } 268 } 269