1 #define CATCH_CONFIG_MAIN
2 #define SOL_CHECK_ARGUMENTS
3 
4 #include <catch.hpp>
5 #include <sol.hpp>
6 
7 #include <fstream>
8 #include <iostream>
9 #include <map>
10 #include <unordered_map>
11 #include <vector>
12 
13 #include "test_stack_guard.hpp"
14 
func_opt_ret_bool(sol::optional<int> i)15 bool func_opt_ret_bool(sol::optional<int> i) {
16 	if (i)
17 	{
18 		INFO(i.value());
19 	}
20 	else
21 	{
22 		INFO("optional isn't set");
23 	}
24 	return true;
25 }
26 
27 TEST_CASE("table/traversal", "ensure that we can chain requests and tunnel down into a value if we desire") {
28 
29 	sol::state lua;
30 	int begintop = 0, endtop = 0;
31 
32 	sol::function scriptload = lua.load("t1 = {t2 = {t3 = 24}};");
33 	scriptload();
34 	{
35 		test_stack_guard g(lua.lua_state(), begintop, endtop);
36 		int traversex24 = lua.traverse_get<int>("t1", "t2", "t3");
37 		REQUIRE(traversex24 == 24);
38 	} REQUIRE(begintop == endtop);
39 
40 	{
41 		test_stack_guard g(lua.lua_state(), begintop, endtop);
42 		int x24 = lua["t1"]["t2"]["t3"];
43 		REQUIRE(x24 == 24);
44 	} REQUIRE(begintop == endtop);
45 
46 	{
47 		test_stack_guard g(lua.lua_state(), begintop, endtop);
48 		lua["t1"]["t2"]["t3"] = 64;
49 		int traversex64 = lua.traverse_get<int>("t1", "t2", "t3");
50 		REQUIRE(traversex64 == 64);
51 	} REQUIRE(begintop == endtop);
52 
53 	{
54 		test_stack_guard g(lua.lua_state(), begintop, endtop);
55 		int x64 = lua["t1"]["t2"]["t3"];
56 		REQUIRE(x64 == 64);
57 	} REQUIRE(begintop == endtop);
58 
59 	{
60 		test_stack_guard g(lua.lua_state(), begintop, endtop);
61 		lua.traverse_set("t1", "t2", "t3", 13);
62 		int traversex13 = lua.traverse_get<int>("t1", "t2", "t3");
63 		REQUIRE(traversex13 == 13);
64 	} REQUIRE(begintop == endtop);
65 
66 	{
67 		test_stack_guard g(lua.lua_state(), begintop, endtop);
68 		int x13 = lua["t1"]["t2"]["t3"];
69 		REQUIRE(x13 == 13);
70 	} REQUIRE(begintop == endtop);
71 }
72 
73 TEST_CASE("simple/set", "Check if the set works properly.") {
74 	sol::state lua;
75 	int begintop = 0, endtop = 0;
76 	{
77 		test_stack_guard g(lua.lua_state(), begintop, endtop);
78 		lua.set("a", 9);
79 	} REQUIRE(begintop == endtop);
80 	REQUIRE_NOTHROW(lua.script("if a ~= 9 then error('wrong value') end"));
81 	{
82 		test_stack_guard g(lua.lua_state(), begintop, endtop);
83 		lua.set("d", "hello");
84 	} REQUIRE(begintop == endtop);
85 	REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end"));
86 
87 	{
88 		test_stack_guard g(lua.lua_state(), begintop, endtop);
89 		lua.set("e", std::string("hello"), "f", true);
90 	} REQUIRE(begintop == endtop);
91 	REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end"));
92 	REQUIRE_NOTHROW(lua.script("if f ~= true then error('wrong value') end"));
93 }
94 
95 TEST_CASE("simple/get", "Tests if the get function works properly.") {
96 	sol::state lua;
97 	int begintop = 0, endtop = 0;
98 
99 	lua.script("a = 9");
100 	{
101 		test_stack_guard g(lua.lua_state(), begintop, endtop);
102 		auto a = lua.get<int>("a");
103 		REQUIRE(a == 9.0);
104 	} REQUIRE(begintop == endtop);
105 
106 	lua.script("b = nil");
107 	{
108 		test_stack_guard g(lua.lua_state(), begintop, endtop);
109 		REQUIRE_NOTHROW(lua.get<sol::nil_t>("b"));
110 	} REQUIRE(begintop == endtop);
111 
112 	lua.script("d = 'hello'");
113 	lua.script("e = true");
114 	{
115 		test_stack_guard g(lua.lua_state(), begintop, endtop);
116 		std::string d;
117 		bool e;
118 		std::tie(d, e) = lua.get<std::string, bool>("d", "e");
119 		REQUIRE(d == "hello");
120 		REQUIRE(e == true);
121 	} REQUIRE(begintop == endtop);
122 }
123 
124 TEST_CASE("simple/set-get-global-integer", "Tests if the get function works properly with global integers") {
125 	sol::state lua;
126 	lua[1] = 25.4;
127 	lua.script("b = 1");
128 	double a = lua.get<double>(1);
129 	double b = lua.get<double>("b");
130 	REQUIRE(a == 25.4);
131 	REQUIRE(b == 1);
132 }
133 
134 TEST_CASE("simple/get_or", "check if table.get_or works correctly") {
135 	sol::state lua;
136 
137 	auto bob_table = lua.create_table("bob");
138 	bob_table.set("is_set", 42);
139 
140 	int is_set = bob_table.get_or("is_set", 3);
141 	int is_not_set = bob_table.get_or("is_not_set", 22);
142 
143 	REQUIRE(is_set == 42);
144 	REQUIRE(is_not_set == 22);
145 
146 	lua["joe"] = 55.6;
147 	double bark = lua.get_or<double>("joe", 60);
148 	REQUIRE(bark == 55.6);
149 }
150 
151 TEST_CASE("simple/proxy_get_or", "check if proxy.get_or works correctly") {
152 	sol::state lua;
153 
154 	auto bob_table = lua.create_table("bob");
155 	bob_table.set("is_set", 42);
156 
157 	int is_set = bob_table["is_set"].get_or(3);
158 	int is_not_set = bob_table["is_not_set"].get_or(22);
159 
160 	REQUIRE(is_set == 42);
161 	REQUIRE(is_not_set == 22);
162 
163 	lua["joe"] = 55.6;
164 	double bark = lua["joe"].get_or<double>(60);
165 	REQUIRE(bark == 55.6);
166 }
167 
168 TEST_CASE("simple/addition", "check if addition works and can be gotten through lua.get and lua.set") {
169 	sol::state lua;
170 
171 	lua.set("b", 0.2);
172 	lua.script("c = 9 + b");
173 	auto c = lua.get<double>("c");
174 
175 	REQUIRE(c == 9.2);
176 }
177 
178 TEST_CASE("simple/if", "check if if statements work through lua") {
179 	sol::state lua;
180 
181 	std::string program = "if true then f = 0.1 else f = 'test' end";
182 	lua.script(program);
183 	auto f = lua.get<double>("f");
184 
185 	REQUIRE(f == 0.1);
186 	REQUIRE((f == lua["f"]));
187 }
188 
189 TEST_CASE("negative/basic_errors", "Check if error handling works correctly") {
190 	sol::state lua;
191 
192 	REQUIRE_THROWS(lua.script("nil[5]"));
193 }
194 
195 TEST_CASE("libraries", "Check if we can open libraries") {
196 	sol::state lua;
197 	REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base, sol::lib::os));
198 }
199 
200 TEST_CASE("libraries2", "Check if we can open ALL the libraries") {
201 	sol::state lua;
202 	REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base,
203 		sol::lib::bit32,
204 		sol::lib::coroutine,
205 		sol::lib::debug,
206 		sol::lib::ffi,
207 		sol::lib::jit,
208 		sol::lib::math,
209 		sol::lib::os,
210 		sol::lib::package,
211 		sol::lib::string,
212 		sol::lib::table));
213 }
214 
215 TEST_CASE("interop/null-to-nil-and-back", "nil should be the given type when a pointer from C++ is returned as nullptr, and nil should result in nullptr in connected C++ code") {
216 	sol::state lua;
217 	lua.open_libraries(sol::lib::base);
218 
__anon45e098250102() 219 	lua.set_function("lol", []() -> int* {
220 		return nullptr;
221 	});
__anon45e098250202(int* x) 222 	lua.set_function("rofl", [](int* x) {
223 		INFO(x);
224 	});
225 	REQUIRE_NOTHROW(lua.script("x = lol()\n"
226 		"rofl(x)\n"
227 		"assert(x == nil)"));
228 }
229 
230 TEST_CASE("utilities/this_state", "Ensure this_state argument can be gotten anywhere in the function.") {
231 	struct bark {
with_statebark232 		int with_state(sol::this_state l, int a, int b) {
233 			lua_State* L = l;
234 			int c = lua_gettop(L);
235 			return a + b + (c - c);
236 		}
237 
with_state_2bark238 		static int with_state_2(int a, sol::this_state l, int b) {
239 			INFO("inside with_state_2");
240 			lua_State* L = l;
241 			INFO("L is" << (void*)L);
242 			int c = lua_gettop(L);
243 			return a * b + (c - c);
244 		}
245 	};
246 
247 	sol::state lua;
248 	INFO("created lua state");
249 	lua.open_libraries(sol::lib::base);
250 	lua.new_usertype<bark>("bark",
251 		"with_state", &bark::with_state
252 		);
253 
254 	INFO("setting b and with_state_2");
255 	bark b;
256 	lua.set("b", &b);
257 	lua.set("with_state_2", bark::with_state_2);
258 	INFO("finished setting");
259 	INFO("getting fx");
260 	sol::function fx = lua["with_state_2"];
261 	INFO("calling fx");
262 	int a = fx(25, 25);
263 	INFO("finished setting fx");
264 	INFO("calling a script");
265 	lua.script("a = with_state_2(25, 25)");
266 	INFO("calling c script");
267 	lua.script("c = b:with_state(25, 25)");
268 	INFO("getting a");
269 	int la = lua["a"];
270 	INFO("getting b");
271 	int lc = lua["c"];
272 
273 	REQUIRE(lc == 50);
274 	REQUIRE(a == 625);
275 	REQUIRE(la == 625);
276 }
277 
278 TEST_CASE("object/conversions", "make sure all basic reference types can be made into objects") {
279 	sol::state lua;
280 	lua.open_libraries(sol::lib::base);
281 
282 	struct d {};
283 
284 	lua.script("function f () print('bark') end");
285 	lua["d"] = d{};
286 	lua["l"] = static_cast<void*>(nullptr);
287 
288 	sol::table t = lua.create_table();
289 	sol::thread th = sol::thread::create(lua);
290 	sol::function f = lua["f"];
291 	sol::protected_function pf = lua["f"];
292 	sol::userdata ud = lua["d"];
293 	sol::lightuserdata lud = lua["l"];
294 
295 	sol::object ot(t);
296 	sol::object ot2 = ot;
297 	sol::object oth(th);
298 	sol::object of(f);
299 	sol::object opf(pf);
300 	sol::object od(ud);
301 	sol::object ol(lud);
302 
303 	auto oni = sol::make_object(lua, 50);
304 	auto ond = sol::make_object(lua, 50.0);
305 
306 	std::string somestring = "look at this text isn't it nice";
307 	auto osl = sol::make_object(lua, "Bark bark bark");
308 	auto os = sol::make_object(lua, somestring);
309 
310 	auto omn = sol::make_object(lua, sol::nil);
311 
312 	REQUIRE(ot.get_type() == sol::type::table);
313 	REQUIRE(ot2.get_type() == sol::type::table);
314 	REQUIRE(oth.get_type() == sol::type::thread);
315 	REQUIRE(of.get_type() == sol::type::function);
316 	REQUIRE(opf.get_type() == sol::type::function);
317 	REQUIRE(od.get_type() == sol::type::userdata);
318 	REQUIRE(ol.get_type() == sol::type::lightuserdata);
319 	REQUIRE(oni.get_type() == sol::type::number);
320 	REQUIRE(ond.get_type() == sol::type::number);
321 	REQUIRE(osl.get_type() == sol::type::string);
322 	REQUIRE(os.get_type() == sol::type::string);
323 	REQUIRE(omn.get_type() == sol::type::nil);
324 }
325 
326 TEST_CASE("state/require_file", "opening files as 'requires'") {
327 	static const char FILE_NAME[] = "./tmp_thingy.lua";
328 
329 	std::fstream file(FILE_NAME, std::ios::out);
330 
331 	sol::state lua;
332 	lua.open_libraries(sol::lib::base);
333 
334 	SECTION("with usertypes")
335 	{
336 		struct foo {
foofoo337 			foo(int bar) : bar(bar) {}
338 
339 			const int bar;
340 		};
341 
342 		lua.new_usertype<foo>("foo",
343 			sol::constructors<sol::types<int>>{},
344 			"bar", &foo::bar
345 			);
346 
347 		file << "return { modfunc = function () return foo.new(221) end }" << std::endl;
348 		file.close();
349 
350 		const sol::table thingy1 = lua.require_file("thingy", FILE_NAME);
351 
352 		CHECK(thingy1.valid());
353 
354 		const foo foo_v = thingy1["modfunc"]();
355 
356 		int val1 = foo_v.bar;
357 
358 		CHECK(val1 == 221);
359 	}
360 
361 	SECTION("simple")
362 	{
363 		file << "return { modfunc = function () return 221 end }" << std::endl;
364 		file.close();
365 
366 		const sol::table thingy1 = lua.require_file("thingy", FILE_NAME);
367 		const sol::table thingy2 = lua.require_file("thingy", FILE_NAME);
368 
369 		CHECK(thingy1.valid());
370 		CHECK(thingy2.valid());
371 
372 		int val1 = thingy1["modfunc"]();
373 		int val2 = thingy2["modfunc"]();
374 
375 		CHECK(val1 == 221);
376 		CHECK(val2 == 221);
377 		// must have loaded the same table
378 		CHECK(thingy1 == thingy2);
379 	}
380 
381 	std::remove(FILE_NAME);
382 }
383 
384 TEST_CASE("state/require_script", "opening strings as 'requires' clauses") {
385 	std::string code = "return { modfunc = function () return 221 end }";
386 
387 	sol::state lua;
388 	sol::table thingy1 = lua.require_script("thingy", code);
389 	sol::table thingy2 = lua.require_script("thingy", code);
390 
391 	int val1 = thingy1["modfunc"]();
392 	int val2 = thingy2["modfunc"]();
393 	REQUIRE(val1 == 221);
394 	REQUIRE(val2 == 221);
395 	// must have loaded the same table
396 	REQUIRE(thingy1 == thingy2);
397 }
398 
399 TEST_CASE("state/require", "opening using a file") {
400 	struct open {
open_funcopen401 		static int open_func(lua_State* L) {
402 			sol::state_view lua = L;
403 			return sol::stack::push(L, lua.create_table_with("modfunc", sol::as_function([]() { return 221; })));
404 		}
405 	};
406 
407 	sol::state lua;
408 	sol::table thingy1 = lua.require("thingy", open::open_func);
409 	sol::table thingy2 = lua.require("thingy", open::open_func);
410 
411 	int val1 = thingy1["modfunc"]();
412 	int val2 = thingy2["modfunc"]();
413 	REQUIRE(val1 == 221);
414 	REQUIRE(val2 == 221);
415 	// THIS IS ONLY REQUIRED IN LUA 5.3, FOR SOME REASON
416 	// must have loaded the same table
417 	// REQUIRE(thingy1 == thingy2);
418 }
419 
420 TEST_CASE("state/multi-require", "make sure that requires transfers across hand-rolled script implementation and standard requiref") {
421 	struct open {
open_funcopen422 		static int open_func(lua_State* L) {
423 			sol::state_view lua = L;
424 			return sol::stack::push(L, lua.create_table_with("modfunc", sol::as_function([]() { return 221; })));
425 		}
426 	};
427 
428 	std::string code = "return { modfunc = function () return 221 end }";
429 	sol::state lua;
430 	sol::table thingy1 = lua.require("thingy", open::open_func);
431 	sol::table thingy2 = lua.require("thingy", open::open_func);
432 	sol::table thingy3 = lua.require_script("thingy", code);
433 
434 	int val1 = thingy1["modfunc"]();
435 	int val2 = thingy2["modfunc"]();
436 	int val3 = thingy3["modfunc"]();
437 	REQUIRE(val1 == 221);
438 	REQUIRE(val2 == 221);
439 	REQUIRE(val3 == 221);
440 	// must have loaded the same table
441 	// Lua is not obliged to give a shit. Thanks, Lua
442 	//REQUIRE(thingy1 == thingy2);
443 	// But we care, thankfully
444 	//REQUIRE(thingy1 == thingy3);
445 	REQUIRE(thingy2 == thingy3);
446 }
447 
448 TEST_CASE("feature/indexing-overrides", "make sure index functions can be overridden on types") {
449 	struct PropertySet {
get_property_luaPropertySet450 		sol::object get_property_lua(const char* name, sol::this_state s)
451 		{
452 			auto& var = props[name];
453 			return sol::make_object(s, var);
454 		}
455 
set_property_luaPropertySet456 		void set_property_lua(const char* name, sol::stack_object object)
457 		{
458 			props[name] = object.as<std::string>();
459 		}
460 
461 		std::unordered_map<std::string, std::string> props;
462 	};
463 
464 	struct DynamicObject {
get_dynamic_propsDynamicObject465 		PropertySet& get_dynamic_props() {
466 			return dynamic_props;
467 		}
468 
469 		PropertySet dynamic_props;
470 	};
471 
472 	sol::state lua;
473 	lua.open_libraries(sol::lib::base);
474 
475 	lua.new_usertype<PropertySet>("PropertySet"
476 		, sol::meta_function::new_index, &PropertySet::set_property_lua
477 		, sol::meta_function::index, &PropertySet::get_property_lua
478 		);
479 	lua.new_usertype<DynamicObject>("DynamicObject"
480 		, "props", sol::property(&DynamicObject::get_dynamic_props)
481 		);
482 
483 	lua.script(R"__(
484 obj = DynamicObject:new()
485 obj.props.name = 'test name'
486 print('name = ' .. obj.props.name)
487 )__");
488 
489 	std::string name = lua["obj"]["props"]["name"];
490 	REQUIRE(name == "test name");
491 }
492 
493 TEST_CASE("features/indexing-numbers", "make sure indexing functions can be override on usertypes") {
494 	class vector {
495 	public:
496 		double data[3];
497 
vector()498 		vector() : data{ 0,0,0 } {}
499 
operator [](int i)500 		double& operator[](int i)
501 		{
502 			return data[i];
503 		}
504 
505 
my_index(vector & v,int i)506 		static double my_index(vector& v, int i)
507 		{
508 			return v[i];
509 		}
510 
my_new_index(vector & v,int i,double x)511 		static void my_new_index(vector& v, int i, double x)
512 		{
513 			v[i] = x;
514 		}
515 	};
516 
517 	sol::state lua;
518 	lua.open_libraries(sol::lib::base);
519 	lua.new_usertype<vector>("vector", sol::constructors<sol::types<>>(),
520 		sol::meta_function::index, &vector::my_index,
521 		sol::meta_function::new_index, &vector::my_new_index);
522 	lua.script("v = vector.new()\n"
523 		"print(v[1])\n"
524 		"v[2] = 3\n"
525 		"print(v[2])\n"
526 	);
527 
528 	vector& v = lua["v"];
529 	REQUIRE(v[0] == 0.0);
530 	REQUIRE(v[1] == 0.0);
531 	REQUIRE(v[2] == 3.0);
532 }
533 
534 TEST_CASE("features/multiple-inheritance", "Ensure that multiple inheritance works as advertised") {
535 	struct base1 {
536 		int a1 = 250;
537 	};
538 
539 	struct base2 {
540 		int a2 = 500;
541 	};
542 
543 	struct simple : base1 {
544 
545 	};
546 
547 	struct complex : base1, base2 {
548 
549 	};
550 
551 
552 	sol::state lua;
553 	lua.open_libraries(sol::lib::base);
554 	lua.new_usertype<base1>("base1",
555 		"a1", &base1::a1
556 		);
557 	lua.new_usertype<base2>("base2",
558 		"a2", &base2::a2
559 		);
560 	lua.new_usertype<simple>("simple",
561 		"a1", &simple::a1,
562 		sol::base_classes, sol::bases<base1>()
563 		);
564 	lua.new_usertype<complex>("complex",
565 		"a1", &complex::a1,
566 		"a2", &complex::a2,
567 		sol::base_classes, sol::bases<base1, base2>()
568 		);
569 	lua.script("c = complex.new()\n"
570 		"s = simple.new()\n"
571 		"b1 = base1.new()\n"
572 		"b2 = base1.new()\n"
573 	);
574 
575 	base1* sb1 = lua["s"];
576 	REQUIRE(sb1 != nullptr);
577 	REQUIRE(sb1->a1 == 250);
578 
579 	base1* cb1 = lua["c"];
580 	base2* cb2 = lua["c"];
581 
582 	REQUIRE(cb1 != nullptr);
583 	REQUIRE(cb2 != nullptr);
584 	REQUIRE(cb1->a1 == 250);
585 	REQUIRE(cb2->a2 == 500);
586 }
587 
588 
589 TEST_CASE("regressions/std::ref", "Ensure that std::reference_wrapper<> isn't considered as a function by using unwrap_unqualified_t trait") {
590 	struct base1 {
591 		int a1 = 250;
592 	};
593 
594 	sol::state lua;
595 	base1 v;
596 	lua["vp"] = &v;
597 	lua["vr"] = std::ref(v);
598 
599 	base1* vp = lua["vp"];
600 	base1& vr = lua["vr"];
601 	REQUIRE(vp != nullptr);
602 	REQUIRE(vp == &v);
603 
604 	REQUIRE(vp->a1 == 250);
605 	REQUIRE(vr.a1 == 250);
606 
607 	v.a1 = 568;
608 
609 	REQUIRE(vp->a1 == 568);
610 	REQUIRE(vr.a1 == 568);
611 }
612 
613 TEST_CASE("optional/left-out-args", "Make sure arguments can be left out of optional without tanking miserably") {
614 
615 	sol::state lua;
616 	lua.open_libraries(sol::lib::base);
617 
618 	// sol::optional needs an argument no matter what?
619 	lua.set_function("func_opt_ret_bool", func_opt_ret_bool);
620 	REQUIRE_NOTHROW(
621 	lua.script(R"(
622         func_opt_ret_bool(42)
623         func_opt_ret_bool()
624         print('ok')
625         )");
626 	);
627 }
628 
629 TEST_CASE("pusher/constness", "Make sure more types can handle being const and junk") {
630 	struct Foo {
FooFoo631 		Foo(const sol::function& f) : _f(f) {}
632 		const sol::function& _f;
633 
fFoo634 		const sol::function& f() const { return _f; }
635 	};
636 
637 	sol::state lua;
638 
639 	lua.new_usertype<Foo>("Foo",
640 		sol::call_constructor, sol::no_constructor,
641 		"f", &Foo::f
642 		);
643 
__anon45e098250502() 644 	lua["func"] = []() { return 20; };
645 	sol::function f = lua["func"];
646 	lua["foo"] = Foo(f);
647 	Foo& foo = lua["foo"];
648 	int x = foo.f()();
649 	REQUIRE(x == 20);
650 }
651 
652 TEST_CASE("proxy/proper-pushing", "allow proxies to reference other proxies and be serialized as the proxy itself and not a function or something") {
653 	sol::state lua;
654 	lua.open_libraries(sol::lib::base, sol::lib::io);
655 
656 	class T {};
657 	lua.new_usertype<T>("T");
658 
659 	T t;
660 	lua["t1"] = &t;
661 	lua["t2"] = lua["t1"];
662 	lua.script("b = t1 == t2");
663 	bool b = lua["b"];
664 	REQUIRE(b);
665 }
666 
667 TEST_CASE("proxy/equality", "check to make sure equality tests work") {
668 	sol::state lua;
669 	REQUIRE((lua["a"] == sol::nil));
670 	REQUIRE_FALSE((lua["a"] == nullptr));
671 	REQUIRE_FALSE((lua["a"] == 0));
672 	REQUIRE_FALSE((lua["a"] == 2));
673 
674 	lua["a"] = 2;
675 
676 	REQUIRE_FALSE((lua["a"] == sol::nil)); //0
677 	REQUIRE_FALSE((lua["a"] == nullptr)); //0
678 	REQUIRE_FALSE((lua["a"] == 0)); //0
679 	REQUIRE((lua["a"] == 2)); //1
680 }
681 
682 TEST_CASE("compilation/const-regression", "make sure constness in tables is respected all the way down") {
683 	struct State {
684 	public:
StateState685 		State() {
686 			this->state_.registry()["state"] = this;
687 		}
688 
689 		sol::state state_;
690 	};
691 
692 	State state;
693 	State* s = state.state_.registry()["state"];
694 	REQUIRE(s == &state);
695 }
696 
697 TEST_CASE("numbers/integers", "make sure integers are detectable on most platforms") {
698 	sol::state lua;
699 
700 	lua["a"] = 50; // int
701 	lua["b"] = 50.5; // double
702 
703 	sol::object a = lua["a"];
704 	sol::object b = lua["b"];
705 
706 	bool a_is_int = a.is<int>();
707 	bool a_is_double = a.is<double>();
708 
709 	bool b_is_int = b.is<int>();
710 	bool b_is_double = b.is<double>();
711 
712 	REQUIRE(a_is_int);
713 	REQUIRE(a_is_double);
714 
715 	// TODO: will this fail on certain lower Lua versions?
716 	REQUIRE_FALSE(b_is_int);
717 	REQUIRE(b_is_double);
718 }
719 
720 TEST_CASE("state/script-returns", "make sure script returns are done properly") {
721 	std::string script =
722 		R"(
723 local example =
724 {
725     str = "this is a string",
726     num = 1234,
727 
728     func = function(self)
729         print(self.str)
730 		return "fstr"
731     end
732 }
733 
734 return example;
735 )";
736 
__anon45e098250602(sol::this_state l) 737 	auto bar = [&script](sol::this_state l) {
738 		sol::state_view lua = l;
739 		sol::table data = lua.script(script);
740 
741 		std::string str = data["str"];
742 		int num = data["num"];
743 		std::string fstr = data["func"](data);
744 		REQUIRE(str == "this is a string");
745 		REQUIRE(fstr == "fstr");
746 		REQUIRE(num == 1234);
747 	};
748 
__anon45e098250702(int, sol::this_state l) 749 	auto foo = [&script](int, sol::this_state l) {
750 		sol::state_view lua = l;
751 		sol::table data = lua.script(script);
752 
753 		std::string str = data["str"];
754 		int num = data["num"];
755 		std::string fstr = data["func"](data);
756 		REQUIRE(str == "this is a string");
757 		REQUIRE(fstr == "fstr");
758 		REQUIRE(num == 1234);
759 	};
760 
__anon45e098250802(sol::this_state l) 761 	auto bar2 = [&script](sol::this_state l) {
762 		sol::state_view lua = l;
763 		sol::table data = lua.do_string(script);
764 
765 		std::string str = data["str"];
766 		int num = data["num"];
767 		std::string fstr = data["func"](data);
768 		REQUIRE(str == "this is a string");
769 		REQUIRE(fstr == "fstr");
770 		REQUIRE(num == 1234);
771 	};
772 
__anon45e098250902(int, sol::this_state l) 773 	auto foo2 = [&script](int, sol::this_state l) {
774 		sol::state_view lua = l;
775 		sol::table data = lua.do_string(script);
776 
777 		std::string str = data["str"];
778 		int num = data["num"];
779 		std::string fstr = data["func"](data);
780 		REQUIRE(str == "this is a string");
781 		REQUIRE(fstr == "fstr");
782 		REQUIRE(num == 1234);
783 	};
784 
785 	sol::state lua;
786 	lua.open_libraries();
787 
788 	lua.set_function("foo", foo);
789 	lua.set_function("foo2", foo2);
790 	lua.set_function("bar", bar);
791 	lua.set_function("bar2", bar2);
792 
793 	lua.script("bar() bar2() foo(1) foo2(1)");
794 }
795