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