1 #define SOL_CHECK_ARGUMENTS
2 
3 #include <sol.hpp>
4 #include <catch.hpp>
5 
6 #include <iostream>
7 #include <list>
8 #include <memory>
9 #include <mutex>
10 
11 TEST_CASE("usertype/simple-usertypes", "Ensure that simple usertypes properly work here") {
12 	struct marker {
13 		bool value = false;
14 	};
15 	struct bark {
16 		int var = 50;
17 		marker mark;
18 
funbark19 		void fun() {
20 			var = 51;
21 		}
22 
getbark23 		int get() const {
24 			return var;
25 		}
26 
setbark27 		int set(int x) {
28 			var = x;
29 			return var;
30 		}
31 
specialbark32 		std::string special() const {
33 			return mark.value ? "woof" : "pantpant";
34 		}
35 
the_markerbark36 		const marker& the_marker() const {
37 			return mark;
38 		}
39 	};
40 
41 	sol::state lua;
42 	lua.new_simple_usertype<bark>("bark",
43 		"fun", &bark::fun,
44 		"get", &bark::get,
45 		"var", sol::as_function( &bark::var ),
46 		"the_marker", sol::as_function(&bark::the_marker),
47 		"x", sol::overload(&bark::get),
48 		"y", sol::overload(&bark::set),
49 		"z", sol::overload(&bark::get, &bark::set)
50 	);
51 
52 	lua.script("b = bark.new()");
53 	bark& b = lua["b"];
54 
55 	lua.script("b:fun()");
56 	int var = b.var;
57 	REQUIRE(var == 51);
58 
59 	lua.script("b:var(20)");
60 	lua.script("v = b:var()");
61 	int v = lua["v"];
62 	REQUIRE(v == 20);
63 	REQUIRE(b.var == 20);
64 
65 	lua.script("m = b:the_marker()");
66 	marker& m = lua["m"];
67 	REQUIRE_FALSE(b.mark.value);
68 	REQUIRE_FALSE(m.value);
69 	m.value = true;
70 	REQUIRE(&b.mark == &m);
71 	REQUIRE(b.mark.value);
72 
73 	sol::table barktable = lua["bark"];
74 	barktable["special"] = &bark::special;
75 
76 	lua.script("s = b:special()");
77 	std::string s = lua["s"];
78 	REQUIRE(s == "woof");
79 
80 	lua.script("b:y(24)");
81 	lua.script("x = b:x()");
82 	int x = lua["x"];
83 	REQUIRE(x == 24);
84 
85 	lua.script("z = b:z(b:z() + 5)");
86 	int z = lua["z"];
87 	REQUIRE(z == 29);
88 }
89 
90 TEST_CASE("usertype/simple-usertypes-constructors", "Ensure that calls with specific arguments work") {
91 	struct marker {
92 		bool value = false;
93 	};
94 	struct bark {
95 		int var = 50;
96 		marker mark;
97 
barkbark98 		bark() {}
barkbark99 		bark(int v) : var(v) {}
100 
funbark101 		void fun() {
102 			var = 51;
103 		}
104 
getbark105 		int get() const {
106 			return var;
107 		}
108 
setbark109 		int set(int x) {
110 			var = x;
111 			return var;
112 		}
113 
specialbark114 		std::string special() const {
115 			return mark.value ? "woof" : "pantpant";
116 		}
117 
the_markerbark118 		const marker& the_marker() const {
119 			return mark;
120 		}
121 	};
122 
123 	sol::state lua;
124 	lua.new_simple_usertype<bark>("bark",
125 		sol::constructors<sol::types<>, sol::types<int>>(),
126 		"fun", sol::protect( &bark::fun ),
127 		"get", &bark::get,
128 		"var", sol::as_function( &bark::var ),
129 		"the_marker", &bark::the_marker,
130 		"x", sol::overload(&bark::get),
131 		"y", sol::overload(&bark::set),
132 		"z", sol::overload(&bark::get, &bark::set)
133 	);
134 
135 	lua.script("bx = bark.new(760)");
136 	bark& bx = lua["bx"];
137 	REQUIRE(bx.var == 760);
138 
139 	lua.script("b = bark.new()");
140 	bark& b = lua["b"];
141 
142 	lua.script("b:fun()");
143 	int var = b.var;
144 	REQUIRE(var == 51);
145 
146 	lua.script("b:var(20)");
147 	lua.script("v = b:var()");
148 	int v = lua["v"];
149 	REQUIRE(v == 20);
150 
151 	lua.script("m = b:the_marker()");
152 	marker& m = lua["m"];
153 	REQUIRE_FALSE(b.mark.value);
154 	REQUIRE_FALSE(m.value);
155 	m.value = true;
156 	REQUIRE(&b.mark == &m);
157 	REQUIRE(b.mark.value);
158 
159 	sol::table barktable = lua["bark"];
160 	barktable["special"] = &bark::special;
161 
162 	lua.script("s = b:special()");
163 	std::string s = lua["s"];
164 	REQUIRE(s == "woof");
165 
166 	lua.script("b:y(24)");
167 	lua.script("x = b:x()");
168 	int x = lua["x"];
169 	REQUIRE(x == 24);
170 
171 	lua.script("z = b:z(b:z() + 5)");
172 	int z = lua["z"];
173 	REQUIRE(z == 29);
174 }
175 
176 TEST_CASE("usertype/simple-shared-ptr-regression", "simple usertype metatables should not screw over unique usertype metatables") {
177 	static int created = 0;
178 	static int destroyed = 0;
179 	struct test {
testtest180 		test() {
181 			++created;
182 		}
183 
~testtest184 		~test() {
185 			++destroyed;
186 		}
187 	};
188 	{
189 		std::list<std::shared_ptr<test>> tests;
190 		sol::state lua;
191 		lua.open_libraries();
192 
193 		lua.new_simple_usertype<test>("test",
__anonfb40a62e0102() 194 			"create", [&]() -> std::shared_ptr<test> {
195 			tests.push_back(std::make_shared<test>());
196 			return tests.back();
197 		}
198 		);
199 		REQUIRE(created == 0);
200 		REQUIRE(destroyed == 0);
201 		lua.script("x = test.create()");
202 		REQUIRE(created == 1);
203 		REQUIRE(destroyed == 0);
204 		REQUIRE_FALSE(tests.empty());
205 		std::shared_ptr<test>& x = lua["x"];
206 		std::size_t xuse = x.use_count();
207 		std::size_t tuse = tests.back().use_count();
208 		REQUIRE(xuse == tuse);
209 	}
210 	REQUIRE(created == 1);
211 	REQUIRE(destroyed == 1);
212 }
213 
214 TEST_CASE("usertype/simple-vars", "simple usertype vars can bind various values (no ref)") {
215 	int muh_variable = 10;
216 	int through_variable = 25;
217 
218 	sol::state lua;
219 	lua.open_libraries();
220 
221 	struct test {};
222 	lua.new_simple_usertype<test>("test",
223 		"straight", sol::var(2),
224 		"global", sol::var(muh_variable),
225 		"global2", sol::var(through_variable),
226 		"global3", sol::var(std::ref(through_variable))
227 	);
228 
229 	through_variable = 20;
230 
231 	lua.script(R"(
232 print(test.straight)
233 s = test.straight
234 print(test.global)
235 g = test.global
236 print(test.global2)
237 g2 = test.global2
238 print(test.global3)
239 g3 = test.global3
240 )");
241 
242 	int s = lua["s"];
243 	int g = lua["g"];
244 	int g2 = lua["g2"];
245 	int g3 = lua["g3"];
246 	REQUIRE(s == 2);
247 	REQUIRE(g == 10);
248 	REQUIRE(g2 == 25);
249 	REQUIRE(g3 == 20);
250 }
251 
252 TEST_CASE("usertypes/simple-variable-control", "test to see if usertypes respond to inheritance and variable controls") {
253 	class A {
254 	public:
a()255 		virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); };
256 	};
257 
258 	class B : public A {
259 	public:
a()260 		virtual void a() override { }
261 	};
262 
263 	class sA {
264 	public:
a()265 		virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); };
266 	};
267 
268 	class sB : public sA {
269 	public:
a()270 		virtual void a() override { }
271 	};
272 
273 	struct sV {
274 		int a = 10;
275 		int b = 20;
276 
get_bsV277 		int get_b() const {
278 			return b + 2;
279 		}
280 
set_bsV281 		void set_b(int value) {
282 			b = value;
283 		}
284 	};
285 
286 	struct sW : sV {};
287 
288 	sol::state lua;
289 	lua.open_libraries();
290 
291 	lua.new_usertype<A>("A", "a", &A::a);
292 	lua.new_usertype<B>("B", sol::base_classes, sol::bases<A>());
293 	lua.new_simple_usertype<sA>("sA", "a", &sA::a);
294 	lua.new_simple_usertype<sB>("sB", sol::base_classes, sol::bases<sA>());
295 	lua.new_simple_usertype<sV>("sV", "a", &sV::a, "b", &sV::b, "pb", sol::property(&sV::get_b, &sV::set_b));
296 	lua.new_simple_usertype<sW>("sW", sol::base_classes, sol::bases<sV>());
297 
298 	B b;
299 	lua.set("b", &b);
300 	lua.script("b:a()");
301 
302 	sB sb;
303 	lua.set("sb", &sb);
304 	lua.script("sb:a()");
305 
306 	sV sv;
307 	lua.set("sv", &sv);
308 	lua.script("print(sv.b)assert(sv.b == 20)");
309 
310 	sW sw;
311 	lua.set("sw", &sw);
312 	lua.script("print(sw.a)assert(sw.a == 10)");
313 	lua.script("print(sw.b)assert(sw.b == 20)");
314 	lua.script("print(sw.pb)assert(sw.pb == 22)");
315 	lua.script("sw.a = 11");
316 	lua.script("sw.b = 21");
317 	lua.script("print(sw.a)assert(sw.a == 11)");
318 	lua.script("print(sw.b)assert(sw.b == 21)");
319 	lua.script("print(sw.pb)assert(sw.pb == 23)");
320 	lua.script("sw.pb = 25");
321 	lua.script("print(sw.b)assert(sw.b == 25)");
322 	lua.script("print(sw.pb)assert(sw.pb == 27)");
323 }
324 
325 TEST_CASE("usertype/simple-factory-constructor-overload-usage", "simple usertypes should probably invoke types") {
326 	class A {
327 	public:
a()328 		virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); };
329 	};
330 
331 	class B : public A {
332 	public:
333 		int bvar = 24;
a()334 		virtual void a() override { }
f()335 		void f() {}
336 	};
337 
338 	sol::state lua;
339 	lua.open_libraries();
340 	sol::constructors<sol::types<>, sol::types<const B&>> c;
341 	lua.new_simple_usertype<B>("B",
342 		sol::call_constructor, c,
__anonfb40a62e0202() 343 		"new", sol::factories([]() { return B(); }),
__anonfb40a62e0402(B& mem, int v) 344 		"new2", sol::initializers([](B& mem) { new(&mem)B(); }, [](B& mem, int v) { new(&mem)B(); mem.bvar = v; }),
345 		"f", sol::as_function(&B::bvar),
__anonfb40a62e0602(B&, int v) 346 		"g", sol::overload([](B&) { return 2; }, [](B&, int v) { return v; })
347 	);
348 
349 	lua.script("b = B()");
350 	lua.script("b2 = B.new()");
351 	lua.script("b3 = B.new2()");
352 	lua.script("b4 = B.new2(11)");
353 
354 	lua.script("x = b:f()");
355 	lua.script("x2 = b2:f()");
356 	lua.script("x3 = b3:f()");
357 	lua.script("x4 = b4:f()");
358 	int x = lua["x"];
359 	int x2 = lua["x2"];
360 	int x3 = lua["x3"];
361 	int x4 = lua["x4"];
362 	REQUIRE(x == 24);
363 	REQUIRE(x2 == 24);
364 	REQUIRE(x3 == 24);
365 	REQUIRE(x4 == 11);
366 
367 	lua.script("y = b:g()");
368 	lua.script("y2 = b2:g(3)");
369 	lua.script("y3 = b3:g()");
370 	lua.script("y4 = b4:g(3)");
371 	int y = lua["y"];
372 	int y2 = lua["y2"];
373 	int y3 = lua["y3"];
374 	int y4 = lua["y4"];
375 	REQUIRE(y == 2);
376 	REQUIRE(y2 == 3);
377 	REQUIRE(y3 == 2);
378 	REQUIRE(y4 == 3);
379 }
380 
381 TEST_CASE("usertype/simple-runtime-append", "allow extra functions to be appended at runtime directly to the metatable itself") {
382 	class A {
383 	};
384 
385 	class B : public A {
386 	};
387 
388 	sol::state lua;
389 	lua.new_simple_usertype<A>("A");
390 	lua.new_simple_usertype<B>("B", sol::base_classes, sol::bases<A>());
391 	lua.set("b", std::make_unique<B>());
__anonfb40a62e0702() 392 	lua["A"]["method"] = []() { return 200; };
__anonfb40a62e0802(B&) 393 	lua["B"]["method2"] = [](B&) { return 100; };
394 	lua.script("x = b.method()");
395 	lua.script("y = b:method()");
396 
397 	int x = lua["x"];
398 	int y = lua["y"];
399 	REQUIRE(x == 200);
400 	REQUIRE(y == 200);
401 
402 	lua.script("z = b.method2(b)");
403 	lua.script("w = b:method2()");
404 	int z = lua["z"];
405 	int w = lua["w"];
406 	REQUIRE(z == 100);
407 	REQUIRE(w == 100);
408 }
409 
410 TEST_CASE("usertype/simple-destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") {
411 	sol::state lua;
412 
413 	class CrashClass {
414 	public:
CrashClass()415 		CrashClass() {
416 		}
417 
~CrashClass()418 		~CrashClass() {
419 			a = 10; // This will cause a crash.
420 		}
421 
422 	private:
423 		int a;
424 	};
425 
426 	lua.new_simple_usertype<CrashClass>("CrashClass",
427 		sol::call_constructor, sol::constructors<sol::types<>>()
428 		);
429 
430 	lua.script(R"(
431 		function testCrash()
432 			local x = CrashClass()
433 			end
434 		)");
435 
436 	for (int i = 0; i < 1000; ++i) {
437 		lua["testCrash"]();
438 	}
439 }
440 
441 TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta table also affects the internal function table for pointers as well") {
442 	struct A {
funcA443 		int func() {
444 			return 5000;
445 		}
446 	};
447 
448 	sol::state lua;
449 	lua.open_libraries();
450 
451 	lua.new_simple_usertype<A>("A");
452 	sol::table table = lua["A"];
453 	table["func"] = &A::func;
454 	A a;
455 	lua.set("a", &a);
456 	lua.set("pa", &a);
457 	lua.set("ua", std::make_unique<A>());
458 	REQUIRE_NOTHROW(
459 		lua.script("assert(a:func() == 5000)");
460 		lua.script("assert(pa:func() == 5000)");
461 		lua.script("assert(ua:func() == 5000)");
462 	);
463 }
464