1 #define SOL_CHECK_ARGUMENTS
2
3 #include <catch.hpp>
4 #include <sol.hpp>
5 #include <iostream>
6 #include "test_stack_guard.hpp"
7
makefn()8 std::function<int()> makefn() {
9 auto fx = []() -> int {
10 return 0x1456789;
11 };
12 return fx;
13 }
14
15 template <typename T>
va_func(sol::variadic_args va,T first)16 T va_func(sol::variadic_args va, T first) {
17 T s = 0;
18 for (auto arg : va) {
19 T v = arg;
20 s += v;
21 }
22 std::cout << first << std::endl;
23 std::cout << s << std::endl;
24
25 return s;
26 }
27
takefn(std::function<int ()> purr)28 void takefn(std::function<int()> purr) {
29 if (purr() != 0x1456789)
30 throw 0;
31 }
32
33 struct A {
barkA34 int a = 0xA; int bark() { return 1; }
35 };
36
bark(int num_value,A * a)37 std::tuple<int, int> bark(int num_value, A* a) {
38 return std::tuple<int, int>(num_value * 2, a->bark());
39 }
40
test_free_func(std::function<void ()> f)41 void test_free_func(std::function<void()> f) {
42 f();
43 }
44
test_free_func2(std::function<int (int)> f,int arg1)45 void test_free_func2(std::function<int(int)> f, int arg1) {
46 int val = f(arg1);
47 if (val != arg1)
48 throw sol::error("failed function call!");
49 }
50
overloaded(int x)51 int overloaded(int x) {
52 INFO(x);
53 return 3;
54 }
55
overloaded(int x,int y)56 int overloaded(int x, int y) {
57 INFO(x << " " << y);
58 return 7;
59 }
60
overloaded(int x,int y,int z)61 int overloaded(int x, int y, int z) {
62 INFO(x << " " << y << " " << z);
63 return 11;
64 }
65
non_overloaded(int x,int y,int z)66 int non_overloaded(int x, int y, int z) {
67 INFO(x << " " << y << " " << z);
68 return 13;
69 }
70
71 namespace sep {
plop_xyz(int x,int y,std::string z)72 int plop_xyz(int x, int y, std::string z) {
73 INFO(x << " " << y << " " << z);
74 return 11;
75 }
76 }
77
func_1(int)78 int func_1(int) {
79 return 1;
80 }
81
func_1s(std::string a)82 std::string func_1s(std::string a) {
83 return "string: " + a;
84 }
85
func_2(int,int)86 int func_2(int, int) {
87 return 2;
88 }
89
func_3(int,int,int)90 void func_3(int, int, int) {
91
92 }
93
f1(int)94 int f1(int) { return 32; }
f2(int,int)95 int f2(int, int) { return 1; }
96 struct fer {
f3fer97 double f3(int, int) {
98 return 2.5;
99 }
100 };
101
102 TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") {
103 sol::state lua;
104 lua.script("function f() return '3', 4 end");
105
106 std::tuple<std::string, int> result = lua["f"]();
107 auto s = std::get<0>(result);
108 auto v = std::get<1>(result);
109 REQUIRE(s == "3");
110 REQUIRE(v == 4);
111 }
112
113 TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") {
114 sol::state lua;
115 lua.open_libraries(sol::lib::base);
116
117 lua.set_function("non_overloaded", non_overloaded);
118 REQUIRE_NOTHROW(lua.script("x = non_overloaded(1, 2, 3)\nprint(x)"));
119
120 /*
121 // Cannot reasonably support: clang++ refuses to try enough
122 // deductions to make this work
123 lua.set_function<int>("overloaded", overloaded);
124 REQUIRE_NOTHROW(lua.script("print(overloaded(1))"));
125
126 lua.set_function<int, int>("overloaded", overloaded);
127 REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))"));
128
129 lua.set_function<int, int, int>("overloaded", overloaded);
130 REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
131 */
132 lua.set_function("overloaded", sol::resolve<int(int)>(overloaded));
133 REQUIRE_NOTHROW(lua.script("print(overloaded(1))"));
134
135 lua.set_function("overloaded", sol::resolve<int(int, int)>(overloaded));
136 REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))"));
137
138 lua.set_function("overloaded", sol::resolve<int(int, int, int)>(overloaded));
139 REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))"));
140 }
141
142 TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") {
143 const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12);
144 const static std::tuple<int, float> paired = std::make_tuple(10, 10.f);
145 sol::state lua;
__anone56a74e20202null146 lua.set_function("f", [] {
147 return std::make_tuple(10, 11, 12);
148 });
149 int a = 0;
__anone56a74e20302() 150 lua.set_function("h", []() {
151 return std::make_tuple(10, 10.0f);
152 });
153 lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
154 auto tcpp = lua.get<sol::function>("f").call<int, int, int>();
155 auto tlua = lua.get<sol::function>("g").call<int, int, int>();
156 auto tcpp2 = lua.get<sol::function>("h").call<int, float>();
157 auto tluaget = lua.get<int, int, int>("x", "y", "z");
158 REQUIRE(tcpp == triple);
159 REQUIRE(tlua == triple);
160 REQUIRE(tluaget == triple);
161 REQUIRE(tcpp2 == paired);
162 }
163
164 TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") {
165 const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12);
166 sol::state lua;
__anone56a74e20402() 167 lua.set_function("f_string", []() { return "this is a string!"; });
168 sol::function f_string = lua["f_string"];
169
170 // Make sure there are no overload collisions / compiler errors for automatic string conversions
171 std::string f_string_result = f_string();
172 REQUIRE(f_string_result == "this is a string!");
173 f_string_result = f_string();
174 REQUIRE(f_string_result == "this is a string!");
175
__anone56a74e20502null176 lua.set_function("f", [] {
177 return std::make_tuple(10, 11, 12);
178 });
179 lua.script("function g() return 10, 11, 12 end\nx,y,z = g()");
180 std::tuple<int, int, int> tcpp = lua.get<sol::function>("f")();
181 std::tuple<int, int, int> tlua = lua.get<sol::function>("g")();
182 std::tuple<int, int, int> tluaget = lua.get<int, int, int>("x", "y", "z");
183 INFO("cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp));
184 INFO("lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua));
185 INFO("lua xyz: " << lua.get<int>("x") << ',' << lua.get<int>("y") << ',' << lua.get<int>("z"));
186 REQUIRE(tcpp == triple);
187 REQUIRE(tlua == triple);
188 REQUIRE(tluaget == triple);
189 }
190
191 TEST_CASE("functions/optional-values", "check if optionals can be passed in to be nil or otherwise") {
192 struct thing {
193 int v;
194 };
195 sol::state lua;
196 lua.script(R"( function f (a)
197 return a
198 end )");
199
200 sol::function lua_bark = lua["f"];
201
202 sol::optional<int> testv = lua_bark(sol::optional<int>(29));
203 sol::optional<int> testn = lua_bark(sol::nullopt);
204 REQUIRE((bool)testv);
205 REQUIRE_FALSE((bool)testn);
206 REQUIRE(testv.value() == 29);
207 sol::optional<thing> v = lua_bark(sol::optional<thing>(thing{ 29 }));
208 REQUIRE_NOTHROW(sol::nil_t n = lua_bark(sol::nullopt));
209 REQUIRE(v->v == 29);
210 }
211
212 TEST_CASE("functions/pair-and-tuple-and-proxy-tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") {
213 sol::state lua;
214 lua.new_usertype<A>("A",
215 "bark", &A::bark);
216 lua.script(R"( function f (num_value, a)
217 return num_value * 2, a:bark()
218 end
219 function h (num_value, a, b)
220 return num_value * 2, a:bark(), b * 3
221 end
222 nested = { variables = { no = { problem = 10 } } } )");
223 lua.set_function("g", bark);
224
225 sol::function cpp_bark = lua["g"];
226 sol::function lua_bark = lua["f"];
227 sol::function lua_bark2 = lua["h"];
228
229 sol::reference lua_variable_x = lua["nested"]["variables"]["no"]["problem"];
230 A cpp_variable_y;
231
232 static const std::tuple<int, int> abdesired(20, 1);
233 static const std::pair<int, int> cddesired = { 20, 1 };
234 static const std::tuple<int, int, int> abcdesired(20, 1, 3);
235
236 std::tuple<int, int> ab = cpp_bark(lua_variable_x, cpp_variable_y);
237 std::pair<int, int> cd = lua_bark(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y);
238
239 REQUIRE(ab == abdesired);
240 REQUIRE(cd == cddesired);
241
242 ab = cpp_bark(std::make_pair(lua_variable_x, cpp_variable_y));
243 cd = lua_bark(std::make_pair(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y));
244
245 REQUIRE(ab == abdesired);
246 REQUIRE(cd == cddesired);
247
248 std::tuple<int, int, int> abc = lua_bark2(std::make_tuple(10, cpp_variable_y), sol::optional<int>(1));
249 REQUIRE(abc == abcdesired);
250 }
251
252 TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") {
253 sol::state lua;
254 lua.open_libraries(sol::lib::base);
255
256 lua.set_function("testFunc", test_free_func);
257 lua.set_function("testFunc2", test_free_func2);
258 lua.script(
259 "testFunc(function() print(\"hello std::function\") end)"
260 );
261 REQUIRE_NOTHROW(lua.script(
262 "function m(a)\n"
263 " print(\"hello std::function with arg \", a)\n"
264 " return a\n"
265 "end\n"
266 "\n"
267 "testFunc2(m, 1)"
268 ));
269 }
270
271 TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") {
272 sol::state lua;
273 lua.open_libraries(sol::lib::base);
274
275 lua.set_function("makefn", makefn);
276 lua.set_function("takefn", takefn);
277 lua.script("afx = makefn()\n"
278 "print(afx())\n"
279 "takefn(afx)\n");
280 }
281
282 TEST_CASE("functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers") {
283 sol::state lua;
284 lua.open_libraries(sol::lib::base, sol::lib::debug);
285 static const char unhandlederrormessage[] = "true error message";
286 static const char handlederrormessage[] = "doodle";
287 static const std::string handlederrormessage_s = handlederrormessage;
288
289 // Some function; just using a lambda to be cheap
__anone56a74e20602() 290 auto doomfx = []() {
291 INFO("doomfx called");
292 throw std::runtime_error(unhandlederrormessage);
293 };
__anone56a74e20702() 294 auto luadoomfx = [&lua]() {
295 INFO("luadoomfx called");
296 // Does not bypass error function, will call it
297 luaL_error(lua.lua_state(), unhandlederrormessage);
298 };
299 lua.set_function("doom", doomfx);
300 lua.set_function("luadoom", luadoomfx);
301
__anone56a74e20802(std::string x) 302 auto cpphandlerfx = [](std::string x) {
303 INFO("c++ handler called with: " << x);
304 return handlederrormessage;
305 };
306 lua.set_function("cpphandler", cpphandlerfx);
307 lua.script(
308 std::string("function luahandler ( message )")
309 + " print('lua handler called with: ' .. message)"
310 + " return '" + handlederrormessage + "'"
311 + "end"
312 );
__anone56a74e20902(lua_State*) 313 auto nontrampolinefx = [](lua_State*) -> int { throw "x"; };
314 lua_CFunction c_nontrampolinefx = nontrampolinefx;
315 lua.set("nontrampoline", c_nontrampolinefx);
__anone56a74e20a02() 316 lua.set_function("bark", []() -> int {return 100; });
317
318 sol::function luahandler = lua["luahandler"];
319 sol::function cpphandler = lua["cpphandler"];
320 sol::protected_function doom(lua["doom"], luahandler);
321 sol::protected_function luadoom(lua["luadoom"]);
322 sol::protected_function nontrampoline = lua["nontrampoline"];
323 sol::protected_function justfine = lua["bark"];
324 sol::protected_function justfinewithhandler = lua["bark"];
325 luadoom.error_handler = cpphandler;
326 nontrampoline.error_handler = cpphandler;
327 justfinewithhandler.error_handler = luahandler;
328 bool present = true;
329 {
330 sol::protected_function_result result = doom();
331 REQUIRE_FALSE(result.valid());
332 sol::optional<sol::error> operr = result;
333 sol::optional<int> opvalue = result;
334 present = (bool)operr;
335 REQUIRE(present);
336 present = (bool)opvalue;
337 REQUIRE_FALSE(present);
338 sol::error err = result;
339 REQUIRE(err.what() == handlederrormessage_s);
340 }
341 {
342 sol::protected_function_result result = luadoom();
343 REQUIRE_FALSE(result.valid());
344 sol::optional<sol::error> operr = result;
345 sol::optional<int> opvalue = result;
346 present = (bool)operr;
347 REQUIRE(present);
348 present = (bool)opvalue;
349 REQUIRE_FALSE(present);
350 sol::error err = result;
351 REQUIRE(err.what() == handlederrormessage_s);
352 }
353 {
354 sol::protected_function_result result = nontrampoline();
355 REQUIRE_FALSE(result.valid());
356 sol::optional<sol::error> operr = result;
357 sol::optional<int> opvalue = result;
358 present = (bool)operr;
359 REQUIRE(present);
360 present = (bool)opvalue;
361 REQUIRE_FALSE(present);
362 sol::error err = result;
363 REQUIRE(err.what() == handlederrormessage_s);
364 }
365 {
366 sol::protected_function_result result = justfine();
367 REQUIRE(result.valid());
368 sol::optional<sol::error> operr = result;
369 sol::optional<int> opvalue = result;
370 present = (bool)operr;
371 REQUIRE_FALSE(present);
372 present = (bool)opvalue;
373 REQUIRE(present);
374 int value = result;
375 REQUIRE(value == 100);
376 }
377 {
378 sol::protected_function_result result = justfinewithhandler();
379 REQUIRE(result.valid());
380 sol::optional<sol::error> operr = result;
381 sol::optional<int> opvalue = result;
382 present = (bool)operr;
383 REQUIRE_FALSE(present);
384 present = (bool)opvalue;
385 REQUIRE(present);
386 int value = result;
387 REQUIRE(value == 100);
388 }
389 }
390
391 TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") {
392 static int created = 0;
393 static int destroyed = 0;
394 static void* last_call = nullptr;
395 static void* static_call = reinterpret_cast<void*>(0x01);
396 typedef void(*fptr)();
397 struct x {
xx398 x() { ++created; }
xx399 x(const x&) { ++created; }
xx400 x(x&&) { ++created; }
operator =x401 x& operator=(const x&) { return *this; }
operator =x402 x& operator=(x&&) { return *this; }
funcx403 void func() { last_call = static_cast<void*>(this); };
~xx404 ~x() { ++destroyed; }
405 };
406 struct y {
yy407 y() { ++created; }
yy408 y(const x&) { ++created; }
yy409 y(x&&) { ++created; }
operator =y410 y& operator=(const x&) { return *this; }
operator =y411 y& operator=(x&&) { return *this; }
funcy412 static void func() { last_call = static_call; };
operator ()y413 void operator()() { func(); }
operator fptry414 operator fptr () { return func; }
~yy415 ~y() { ++destroyed; }
416 };
417
418 // stateful functors/member functions should always copy unless specified
419 {
420 created = 0;
421 destroyed = 0;
422 last_call = nullptr;
423 {
424 sol::state lua;
425 x x1;
426 lua.set_function("x1copy", &x::func, x1);
427 lua.script("x1copy()");
428 REQUIRE(created == 2);
429 REQUIRE(destroyed == 0);
430 REQUIRE_FALSE(last_call == &x1);
431
432 lua.set_function("x1ref", &x::func, std::ref(x1));
433 lua.script("x1ref()");
434 REQUIRE(created == 2);
435 REQUIRE(destroyed == 0);
436 REQUIRE(last_call == &x1);
437 }
438 REQUIRE(created == 2);
439 REQUIRE(destroyed == 2);
440 }
441
442 // things convertible to a static function should _never_ be forced to make copies
443 // therefore, pass through untouched
444 {
445 created = 0;
446 destroyed = 0;
447 last_call = nullptr;
448 {
449 sol::state lua;
450 y y1;
451 lua.set_function("y1copy", y1);
452 lua.script("y1copy()");
453 REQUIRE(created == 1);
454 REQUIRE(destroyed == 0);
455 REQUIRE(last_call == static_call);
456
457 last_call = nullptr;
458 lua.set_function("y1ref", std::ref(y1));
459 lua.script("y1ref()");
460 REQUIRE(created == 1);
461 REQUIRE(destroyed == 0);
462 REQUIRE(last_call == static_call);
463 }
464 REQUIRE(created == 1);
465 REQUIRE(destroyed == 1);
466 }
467 }
468
469
470 TEST_CASE("functions/all-kinds", "Register all kinds of functions, make sure they all compile and work") {
471 sol::state lua;
472
473 struct test_1 {
474 int a = 0xA;
barktest_1475 virtual int bark() {
476 return a;
477 }
478
bark_memtest_1479 int bark_mem() {
480 return a;
481 }
482
x_barktest_1483 static std::tuple<int, int> x_bark(int num_value, test_1* a) {
484 return std::tuple<int, int>(num_value * 2, a->a);
485 }
486 };
487
488 struct test_2 {
489 int a = 0xC;
barktest_2490 int bark() {
491 return 20;
492 }
493 };
494
495 struct inner {
496 const int z = 5653;
497 };
498
499 struct nested {
500 inner i;
501 };
502
__anone56a74e20b02() 503 auto a = []() { return 500; };
__anone56a74e20c02() 504 auto b = [&]() { return 501; };
__anone56a74e20d02() 505 auto c = [&]() { return 502; };
__anone56a74e20e02() 506 auto d = []() { return 503; };
507
508 lua.new_usertype<test_1>("test_1",
509 "bark", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>
510 );
511 lua.new_usertype<test_2>("test_2",
512 "bark", sol::c_call<decltype(&test_2::bark), &test_2::bark>
513 );
514 test_2 t2;
515
516 lua.set_function("a", a);
517 lua.set_function("b", b);
518 lua.set_function("c", std::ref(c));
519 lua.set_function("d", std::ref(d));
520 lua.set_function("f", &test_1::bark);
521 lua.set_function("g", test_1::x_bark);
522 lua.set_function("h", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>);
523 lua.set_function("i", &test_2::bark, test_2());
524 lua.set_function("j", &test_2::a, test_2());
525 lua.set_function("k", &test_2::a);
526 lua.set_function("l", sol::c_call<decltype(&test_1::a), &test_1::a>);
527 lua.set_function("m", &test_2::a, &t2);
528 lua.set_function("n", sol::c_call<decltype(&non_overloaded), &non_overloaded>);
529
530 lua.script(R"(
531 o1 = test_1.new()
532 o2 = test_2.new()
533 )");
534
535 lua.script(R"(
536 ob = o1:bark()
537
538 A = a()
539 B = b()
540 C = c()
541 D = d()
542 F = f(o1)
543 G0, G1 = g(2, o1)
544 H = h(o1)
545 I = i(o1)
546 I = i(o1)
547 )");
548
549
550 lua.script(R"(
551 J0 = j()
552 j(24)
553 J1 = j()
554 )");
555
556 lua.script(R"(
557 K0 = k(o2)
558 k(o2, 1024)
559 K1 = k(o2)
560 )");
561
562 lua.script(R"(
563 L0 = l(o1)
564 l(o1, 678)
565 L1 = l(o1)
566 )");
567
568
569 lua.script(R"(
570 M0 = m()
571 m(256)
572 M1 = m()
573 )");
574
575 lua.script(R"(
576 N = n(1, 2, 3)
577 )");
578 int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N;
579 std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N)
580 = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>(
581 "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N"
582 );
583
584 REQUIRE(ob == 0xA);
585
586 REQUIRE(A == 500);
587 REQUIRE(B == 501);
588 REQUIRE(C == 502);
589 REQUIRE(D == 503);
590
591 REQUIRE(F == 0xA);
592 REQUIRE(G0 == 4);
593 REQUIRE(G1 == 0xA);
594 REQUIRE(H == 0xA);
595 REQUIRE(I == 20);
596
597 REQUIRE(J0 == 0xC);
598 REQUIRE(J1 == 24);
599
600 REQUIRE(K0 == 0xC);
601 REQUIRE(K1 == 1024);
602
603 REQUIRE(L0 == 0xA);
604 REQUIRE(L1 == 678);
605
606 REQUIRE(M0 == 0xC);
607 REQUIRE(M1 == 256);
608
609 REQUIRE(N == 13);
610
611 sol::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N)
612 = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>(
613 "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N"
614 );
615
616 REQUIRE(ob == 0xA);
617
618 REQUIRE(A == 500);
619 REQUIRE(B == 501);
620 REQUIRE(C == 502);
621 REQUIRE(D == 503);
622
623 REQUIRE(F == 0xA);
624 REQUIRE(G0 == 4);
625 REQUIRE(G1 == 0xA);
626 REQUIRE(H == 0xA);
627 REQUIRE(I == 20);
628
629 REQUIRE(J0 == 0xC);
630 REQUIRE(J1 == 24);
631
632 REQUIRE(K0 == 0xC);
633 REQUIRE(K1 == 1024);
634
635 REQUIRE(L0 == 0xA);
636 REQUIRE(L1 == 678);
637
638 REQUIRE(M0 == 0xC);
639 REQUIRE(M1 == 256);
640
641 REQUIRE(N == 13);
642
643 // Work that compiler, WORK IT!
644 lua.set("o", &test_1::bark);
645 lua.set("p", test_1::x_bark);
646 lua.set("q", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>);
647 lua.set("r", &test_2::a);
648 lua.set("s", sol::readonly(&test_2::a));
649 lua.set_function("t", sol::readonly(&test_2::a), test_2());
650 lua.set_function("u", &nested::i, nested());
651 lua.set("v", &nested::i);
652 lua.set("nested", nested());
653 lua.set("inner", inner());
654 REQUIRE_THROWS(lua.script("s(o2, 2)"));
655 REQUIRE_THROWS(lua.script("t(2)"));
656 REQUIRE_THROWS(lua.script("u(inner)"));
657 REQUIRE_THROWS(lua.script("v(nested, inner)"));
658 }
659
660 TEST_CASE("simple/call-with-parameters", "Lua function is called with a few parameters from C++") {
661 sol::state lua;
662
663 REQUIRE_NOTHROW(lua.script("function my_add(i, j, k) return i + j + k end"));
664 auto f = lua.get<sol::function>("my_add");
665 REQUIRE_NOTHROW(lua.script("function my_nothing(i, j, k) end"));
666 auto fvoid = lua.get<sol::function>("my_nothing");
667 int a;
668 REQUIRE_NOTHROW(fvoid(1, 2, 3));
669 REQUIRE_NOTHROW(a = f.call<int>(1, 2, 3));
670 REQUIRE(a == 6);
671 REQUIRE_THROWS(a = f(1, 2, "arf"));
672 }
673
674 TEST_CASE("simple/call-c++-function", "C++ function is called from lua") {
675 sol::state lua;
676
677 lua.set_function("plop_xyz", sep::plop_xyz);
678 lua.script("x = plop_xyz(2, 6, 'hello')");
679
680 REQUIRE(lua.get<int>("x") == 11);
681 }
682
683 TEST_CASE("simple/call-lambda", "A C++ lambda is exposed to lua and called") {
684 sol::state lua;
685
686 int a = 0;
687
__anone56a74e20f02null688 lua.set_function("foo", [&a] { a = 1; });
689
690 lua.script("foo()");
691
692 REQUIRE(a == 1);
693 }
694
695 TEST_CASE("advanced/get-and-call", "Checks for lambdas returning values after a get operation") {
696 const static std::string lol = "lol", str = "str";
697 const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh"));
698 sol::state lua;
699
__anone56a74e21002null700 REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; }));
701 REQUIRE(lua.get<sol::function>("a").call<int>() == 42);
702
__anone56a74e21102null703 REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; }));
704 REQUIRE(lua.get<sol::function>("b").call<unsigned int>() == 42u);
705
__anone56a74e21202null706 REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; }));
707 REQUIRE(lua.get<sol::function>("c").call<double>() == 3.14);
708
__anone56a74e21302null709 REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; }));
710 REQUIRE(lua.get<sol::function>("d").call<float>() == 6.28f);
711
__anone56a74e21402null712 REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; }));
713 REQUIRE(lua.get<sol::function>("e").call<std::string>() == lol);
714
__anone56a74e21502null715 REQUIRE_NOTHROW(lua.set_function("f", [] { return true; }));
716 REQUIRE(lua.get<sol::function>("f").call<bool>());
717
__anone56a74e21602null718 REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); }));
719 REQUIRE(lua.get<sol::function>("g").call<std::string>() == str);
720
__anone56a74e21702null721 REQUIRE_NOTHROW(lua.set_function("h", [] {}));
722 REQUIRE_NOTHROW(lua.get<sol::function>("h").call());
723
__anone56a74e21802null724 REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; }));
725 REQUIRE(lua.get<sol::function>("i").call<sol::nil_t>() == sol::nil);
__anone56a74e21902null726 REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); }));
727 REQUIRE((lua.get<sol::function>("j").call<int, float, double, std::string>() == heh_tuple));
728 }
729
730 TEST_CASE("advanced/operator[]-call", "Checks for lambdas returning values using operator[]") {
731 const static std::string lol = "lol", str = "str";
732 const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh"));
733 sol::state lua;
734
__anone56a74e21a02null735 REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; }));
736 REQUIRE(lua["a"].call<int>() == 42);
737
__anone56a74e21b02null738 REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; }));
739 REQUIRE(lua["b"].call<unsigned int>() == 42u);
740
__anone56a74e21c02null741 REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; }));
742 REQUIRE(lua["c"].call<double>() == 3.14);
743
__anone56a74e21d02null744 REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; }));
745 REQUIRE(lua["d"].call<float>() == 6.28f);
746
__anone56a74e21e02null747 REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; }));
748 REQUIRE(lua["e"].call<std::string>() == lol);
749
__anone56a74e21f02null750 REQUIRE_NOTHROW(lua.set_function("f", [] { return true; }));
751 REQUIRE(lua["f"].call<bool>());
752
__anone56a74e22002null753 REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); }));
754 REQUIRE(lua["g"].call<std::string>() == str);
755
__anone56a74e22102null756 REQUIRE_NOTHROW(lua.set_function("h", [] {}));
757 REQUIRE_NOTHROW(lua["h"].call());
758
__anone56a74e22202null759 REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; }));
760 REQUIRE(lua["i"].call<sol::nil_t>() == sol::nil);
__anone56a74e22302null761 REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); }));
762 REQUIRE((lua["j"].call<int, float, double, std::string>() == heh_tuple));
763 }
764
765 TEST_CASE("advanced/call-lambdas", "A C++ lambda is exposed to lua and called") {
766 sol::state lua;
767
768 int x = 0;
__anone56a74e22402(int new_x) 769 lua.set_function("set_x", [&](int new_x) {
770 x = new_x;
771 return 0;
772 });
773
774 lua.script("set_x(9)");
775 REQUIRE(x == 9);
776 }
777
778 TEST_CASE("advanced/call-referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") {
779 sol::state lua;
780
781 int x = 0;
__anone56a74e22502(int new_x) 782 auto objx = [&](int new_x) {
783 x = new_x;
784 return 0;
785 };
786 lua.set_function("set_x", std::ref(objx));
787
788 int y = 0;
__anone56a74e22602(int new_y) 789 auto objy = [&](int new_y) {
790 y = new_y;
791 return std::tuple<int, int>(0, 0);
792 };
793 lua.set_function("set_y", &decltype(objy)::operator(), std::ref(objy));
794
795 lua.script("set_x(9)");
796 lua.script("set_y(9)");
797 REQUIRE(x == 9);
798 REQUIRE(y == 9);
799 }
800
801 TEST_CASE("functions/tie", "make sure advanced syntax with 'tie' works") {
802 sol::state lua;
803
804 lua.script(R"(function f ()
805 return 1, 2, 3
806 end)");
807 sol::function f = lua["f"];
808
809 int a, b, c;
810 sol::tie(a, b, c) = f();
811 REQUIRE(a == 1);
812 REQUIRE(b == 2);
813 REQUIRE(c == 3);
814 }
815
816 TEST_CASE("functions/variadic_args", "Check to see we can receive multiple arguments through a variadic") {
817 struct structure {
818 int x;
819 bool b;
820 };
821
822 sol::state lua;
823 lua.open_libraries(sol::lib::base);
__anone56a74e22702(sol::this_state, sol::variadic_args va) 824 lua.set_function("v", [](sol::this_state, sol::variadic_args va) -> structure {
825 int r = 0;
826 for (auto v : va) {
827 int value = v;
828 r += value;
829 }
830 return{ r, r > 200 };
831 });
832
833 lua.script("x = v(25, 25)");
834 lua.script("x2 = v(25, 25, 100, 50, 250, 150)");
835 lua.script("x3 = v(1, 2, 3, 4, 5, 6)");
836
837 structure& lx = lua["x"];
838 structure& lx2 = lua["x2"];
839 structure& lx3 = lua["x3"];
840 REQUIRE(lx.x == 50);
841 REQUIRE(lx2.x == 600);
842 REQUIRE(lx3.x == 21);
843 REQUIRE_FALSE(lx.b);
844 REQUIRE(lx2.b);
845 REQUIRE_FALSE(lx3.b);
846 }
847
848 TEST_CASE("functions/required_and_variadic_args", "Check if a certain number of arguments can still be required even when using variadic_args") {
849 sol::state lua;
850 lua.set_function("v",
__anone56a74e22802(sol::this_state, sol::variadic_args, int, int) 851 [](sol::this_state, sol::variadic_args, int, int) {
852 }
853 );
854 REQUIRE_NOTHROW(lua.script("v(20, 25, 30)"));
855 REQUIRE_NOTHROW(lua.script("v(20, 25)"));
856 #ifndef SOL_LUAJIT
857 REQUIRE_THROWS(lua.script("v(20)"));
858 #endif // LuaJIT has problems with exceptions, as fucking usual
859 }
860
861 TEST_CASE("functions/overloading", "Check if overloading works properly for regular set function syntax") {
862 sol::state lua;
863 lua.open_libraries(sol::lib::base);
864
865 lua.set_function("func_1", func_1);
866 lua.set_function("func", sol::overload(func_2, func_3, func_1, func_1s));
867
868 const std::string string_bark = "string: bark";
869
870 REQUIRE_NOTHROW(lua.script(
871 "a = func(1)\n"
872 "b = func('bark')\n"
873 "c = func(1,2)\n"
874 "func(1,2,3)\n"
875 ));
876
877 REQUIRE((lua["a"] == 1));
878 REQUIRE((lua["b"] == string_bark));
879 REQUIRE((lua["c"] == 2));
880
881 REQUIRE_THROWS(lua.script("func(1,2,'meow')"));
882 }
883
884 TEST_CASE("overloading/c_call", "Make sure that overloading works with c_call functionality") {
885 sol::state lua;
886 lua.set("f", sol::c_call<sol::wrap<decltype(&f1), &f1>, sol::wrap<decltype(&f2), &f2>, sol::wrap<decltype(&fer::f3), &fer::f3>>);
887 lua.set("g", sol::c_call<sol::wrap<decltype(&f1), &f1>>);
888 lua.set("h", sol::c_call<decltype(&f2), &f2>);
889 lua.set("obj", fer());
890
891 lua.script("r1 = f(1)");
892 lua.script("r2 = f(1, 2)");
893 lua.script("r3 = f(obj, 1, 2)");
894 lua.script("r4 = g(1)");
895 lua.script("r5 = h(1, 2)");
896
897 int r1 = lua["r1"];
898 int r2 = lua["r2"];
899 double r3 = lua["r3"];
900 int r4 = lua["r4"];
901 int r5 = lua["r5"];
902
903 REQUIRE(r1 == 32);
904 REQUIRE(r2 == 1);
905 REQUIRE(r3 == 2.5);
906 REQUIRE(r4 == 32);
907 REQUIRE(r5 == 1);
908 }
909
910 TEST_CASE("functions/stack-protect", "make sure functions don't impede on the stack") {
911 //setup sol/lua
912 sol::state lua;
913 lua.open_libraries(sol::lib::base, sol::lib::string);
914
915 lua.script("function ErrorHandler(msg) print('Lua created error msg : ' .. msg) return msg end");
916 lua.script("function stringtest(a) if a == nil then error('fuck') end print('Lua recieved content : ' .. a) return a end");
917
918 // test normal function
919 {
920 sol::stack_guard normalsg(lua);
921 std::string str = lua["stringtest"]("normal test");
922 INFO("Back in C++, direct call result is : " << str);
923 }
924
925 //test protected_function
926 sol::protected_function Stringtest(lua["stringtest"]);
927 Stringtest.error_handler = lua["ErrorHandler"];
928 sol::stack_guard sg(lua);
929 {
930 sol::protected_function_result stringresult = Stringtest("protected test");
931 REQUIRE(stringresult.valid());
932 std::string s = stringresult;
933 INFO("Back in C++, protected result is : " << s);
934 }
935 REQUIRE(sg.check_stack());
936
937 //test optional
938 {
939 sol::stack_guard opsg(lua);
940 sol::optional<std::string> opt_result = Stringtest("optional test");
941 REQUIRE(opsg.check_stack());
942 if (opt_result)
943 {
944 std::string s = opt_result.value();
945 INFO("Back in C++, opt_result is : " << s);
946 }
947 else
948 {
949 INFO("opt_result failed");
950 }
951 }
952 REQUIRE(sg.check_stack());
953
954 {
955 sol::protected_function_result errresult = Stringtest(sol::nil);
956 REQUIRE_FALSE(errresult.valid());
957 sol::error err = errresult;
958 std::string msg = err.what();
959 INFO("error :" << msg);
960 }
961 REQUIRE(sg.check_stack());
962 }
963
964 TEST_CASE("functions/same-type-closures", "make sure destructions are per-object, not per-type, by destroying one type multiple times") {
965 static std::set<void*> last_my_closures;
966 static bool checking_closures = false;
967 static bool check_failed = false;
968
969 struct my_closure {
970 int& n;
971
my_closuremy_closure972 my_closure(int& n) : n(n) {}
~my_closuremy_closure973 ~my_closure() noexcept(false) {
974 if (!checking_closures)
975 return;
976 void* addr = static_cast<void*>(this);
977 auto f = last_my_closures.find(addr);
978 if (f != last_my_closures.cend()) {
979 check_failed = true;
980 }
981 last_my_closures.insert(f, addr);
982 }
983
operator ()my_closure984 int operator() () {
985 ++n; return n;
986 }
987 };
988
989 int n = 250;
990 my_closure a(n);
991 my_closure b(n);
992 {
993 sol::state lua;
994
995 lua.set_function("f", a);
996 lua.set_function("g", b);
997 checking_closures = true;
998 }
999 REQUIRE_FALSE(check_failed);
1000 REQUIRE(last_my_closures.size() == 2);
1001 }
1002
1003 TEST_CASE("functions/stack-multi-return", "Make sure the stack is protected after multi-returns") {
1004 sol::state lua;
1005 lua.script("function f () return 1, 2, 3, 4, 5 end");
1006
1007 {
1008 sol::stack_guard sg(lua);
1009 sol::stack::push(lua, double(256.78));
1010 {
1011 int a, b, c, d, e;
1012 sol::stack_guard sg2(lua);
1013 sol::function f = lua["f"];
1014 sol::tie(a, b, c, d, e) = f();
1015 REQUIRE(a == 1);
1016 REQUIRE(b == 2);
1017 REQUIRE(c == 3);
1018 REQUIRE(d == 4);
1019 REQUIRE(e == 5);
1020 }
1021 double f = sol::stack::pop<double>(lua);
1022 REQUIRE(f == 256.78);
1023 }
1024 }
1025
1026 TEST_CASE("functions/protected-stack-multi-return", "Make sure the stack is protected after multi-returns") {
1027 sol::state lua;
1028 lua.script("function f () return 1, 2, 3, 4, 5 end");
1029
1030 {
1031 sol::stack_guard sg(lua);
1032 sol::stack::push(lua, double(256.78));
1033 {
1034 int a, b, c, d, e;
1035 sol::stack_guard sg2(lua);
1036 sol::protected_function pf = lua["f"];
1037 sol::tie(a, b, c, d, e) = pf();
1038 REQUIRE(a == 1);
1039 REQUIRE(b == 2);
1040 REQUIRE(c == 3);
1041 REQUIRE(d == 4);
1042 REQUIRE(e == 5);
1043 }
1044 double f = sol::stack::pop<double>(lua);
1045 REQUIRE(f == 256.78);
1046 }
1047 }
1048
1049 TEST_CASE("functions/overloaded-variadic", "make sure variadics work to some degree with overloading") {
1050 sol::state lua;
1051 lua.open_libraries();
1052
1053 sol::table ssl = lua.create_named_table("ssl");
1054 ssl.set_function("test", sol::overload(&va_func<int>, &va_func<double>));
1055
1056 lua.script("a = ssl.test(1, 2, 3)");
1057 lua.script("b = ssl.test(1, 2)");
1058 lua.script("c = ssl.test(2.2)");
1059
1060 int a = lua["a"];
1061 int b = lua["b"];
1062 double c = lua["c"];
1063 REQUIRE(a == 6);
1064 REQUIRE(b == 3);
1065 REQUIRE(c == 2.2);
1066 }
1067