2013-12-11 21:32:27 +08:00
# define CATCH_CONFIG_MAIN
# include <catch.hpp>
2013-12-11 19:34:18 +08:00
# include <sol.hpp>
2014-06-01 14:41:16 +08:00
# include <vector>
# include <map>
2013-12-11 19:34:18 +08:00
2014-05-31 07:58:47 +08:00
void test_free_func ( std : : function < void ( ) > f ) {
f ( ) ;
2014-05-31 07:10:08 +08:00
}
2014-05-31 07:58:47 +08:00
void test_free_func2 ( std : : function < int ( int ) > f , int arg1 ) {
int val = f ( arg1 ) ;
2014-06-01 02:29:14 +08:00
if ( val ! = arg1 )
throw sol : : error ( " failed function call! " ) ;
2014-05-31 07:10:08 +08:00
}
2014-06-08 04:33:39 +08:00
std : : function < int ( ) > makefn ( ) {
2014-06-07 23:00:27 +08:00
auto fx = [ ] ( ) - > int {
return 0x1456789 ;
} ;
return fx ;
}
2014-06-08 04:33:39 +08:00
void takefn ( std : : function < int ( ) > purr ) {
2014-06-07 23:00:27 +08:00
if ( purr ( ) ! = 0x1456789 )
throw 0 ;
}
2013-12-11 21:32:27 +08:00
std : : string free_function ( ) {
std : : cout < < " free_function() " < < std : : endl ;
2013-12-11 19:34:18 +08:00
return " test " ;
}
2014-06-29 14:16:48 +08:00
int overloaded ( int x ) {
std : : cout < < x < < std : : endl ;
return 3 ;
}
int overloaded ( int x , int y ) {
std : : cout < < x < < " " < < y < < std : : endl ;
return 7 ;
}
int overloaded ( int x , int y , int z ) {
std : : cout < < x < < " " < < y < < " " < < z < < std : : endl ;
return 11 ;
}
int non_overloaded ( int x , int y , int z ) {
std : : cout < < x < < " " < < y < < " " < < z < < std : : endl ;
return 13 ;
}
2014-06-01 14:41:16 +08:00
std : : vector < int > test_table_return_one ( ) {
return { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } ;
}
std : : vector < std : : pair < std : : string , int > > test_table_return_two ( ) {
return { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } } ;
}
std : : map < std : : string , std : : string > test_table_return_three ( ) {
return { { " name " , " Rapptz " } , { " friend " , " ThePhD " } , { " project " , " sol " } } ;
}
2014-05-31 07:58:47 +08:00
struct self_test {
int bark ;
self_test ( ) : bark ( 100 ) {
}
void g ( const std : : string & str ) {
std : : cout < < str < < ' \n ' ;
bark + = 1 ;
}
void f ( const self_test & t ) {
std : : cout < < " got test " < < ' \n ' ;
2014-06-01 02:29:14 +08:00
if ( t . bark ! = bark )
throw sol : : error ( " bark values are not the same for self_test f function " ) ;
if ( & t ! = this )
throw sol : : error ( " call does not reference self for self_test f function " ) ;
2014-05-31 07:58:47 +08:00
}
} ;
2013-12-11 21:32:27 +08:00
struct object {
2013-12-11 19:34:18 +08:00
std : : string operator ( ) ( ) {
std : : cout < < " member_test() " < < std : : endl ;
return " test " ;
}
} ;
2014-04-26 07:41:03 +08:00
struct fuser {
2014-04-26 09:23:57 +08:00
int x ;
2014-04-27 13:18:54 +08:00
fuser ( ) : x ( 0 ) { }
fuser ( int x ) : x ( x ) { }
2014-04-26 09:23:57 +08:00
2014-04-27 13:18:54 +08:00
int add ( int y ) {
2014-04-26 09:23:57 +08:00
return x + y ;
}
2014-04-27 13:18:54 +08:00
int add2 ( int y ) {
2014-04-26 09:23:57 +08:00
return x + y + 2 ;
}
2014-04-26 07:41:03 +08:00
} ;
2014-04-27 06:23:56 +08:00
namespace crapola {
2014-04-27 13:18:54 +08:00
struct fuser {
int x ;
fuser ( ) : x ( 0 ) { }
fuser ( int x ) : x ( x ) { }
fuser ( int x , int x2 ) : x ( x * x2 ) { }
int add ( int y ) {
return x + y ;
}
int add2 ( int y ) {
return x + y + 2 ;
}
} ;
2014-04-27 13:29:37 +08:00
} // crapola
2014-04-27 06:23:56 +08:00
2013-12-12 00:18:13 +08:00
int plop_xyz ( int x , int y , std : : string z ) {
std : : cout < < x < < " " < < y < < " " < < z < < std : : endl ;
return 11 ;
}
2014-05-26 02:41:06 +08:00
class Base {
public :
Base ( int a_num ) : m_num ( a_num ) { }
int get_num ( ) {
return m_num ;
}
protected :
int m_num ;
} ;
class Derived : public Base {
public :
Derived ( int a_num ) : Base ( a_num ) { }
int get_num_10 ( ) {
return 10 * m_num ;
}
} ;
2014-07-28 03:56:24 +08:00
struct Vec {
float x , y , z ;
Vec ( float x , float y , float z ) : x { x } , y { y } , z { z } { }
float length ( ) {
return sqrtf ( x * x + y * y + z * z ) ;
}
Vec normalized ( ) {
float invS = 1 / length ( ) ;
return { x * invS , y * invS , z * invS } ;
}
} ;
2013-12-12 00:18:13 +08:00
TEST_CASE ( " simple/set_global " , " Check if the set_global works properly. " ) {
sol : : state lua ;
lua . set ( " a " , 9 ) ;
REQUIRE_NOTHROW ( lua . script ( " if a ~= 9 then error('wrong value') end " ) ) ;
lua . set ( " d " , " hello " ) ;
REQUIRE_NOTHROW ( lua . script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " ) ) ;
lua . set ( " e " , std : : string ( " hello " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " ) ) ;
lua . set ( " f " , true ) ;
REQUIRE_NOTHROW ( lua . script ( " if f ~= true then error('wrong value') end " ) ) ;
}
TEST_CASE ( " simple/get " , " Tests if the get function works properly. " ) {
sol : : state lua ;
lua . script ( " a = 9 " ) ;
auto a = lua . get < int > ( " a " ) ;
REQUIRE ( a = = 9.0 ) ;
lua . script ( " b = nil " ) ;
2013-12-12 00:56:34 +08:00
REQUIRE_NOTHROW ( lua . get < sol : : nil_t > ( " b " ) ) ;
2014-04-27 13:18:54 +08:00
2013-12-12 00:18:13 +08:00
lua . script ( " d = 'hello' " ) ;
auto d = lua . get < std : : string > ( " d " ) ;
REQUIRE ( d = = " hello " ) ;
lua . script ( " e = true " ) ;
auto e = lua . get < bool > ( " e " ) ;
REQUIRE ( e = = true ) ;
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " simple/addition " , " check if addition works and can be gotten through lua.get and lua.set " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
lua . set ( " b " , 0.2 ) ;
lua . script ( " c = 9 + b " ) ;
auto c = lua . get < double > ( " c " ) ;
REQUIRE ( c = = 9.2 ) ;
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " simple/if " , " check if if statements work through lua " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
std : : string program = " if true then f = 0.1 else f = 'test' end " ;
lua . script ( program ) ;
auto f = lua . get < double > ( " f " ) ;
REQUIRE ( f = = 0.1 ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( ( f = = lua [ " f " ] ) ) ;
2013-12-12 00:18:13 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " simple/call_with_parameters " , " Lua function is called with a few parameters from C++ " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
2013-12-11 21:32:27 +08:00
2013-12-12 00:18:13 +08:00
REQUIRE_NOTHROW ( lua . script ( " function my_add(i, j, k) return i + j + k end " ) ) ;
auto f = lua . get < sol : : function > ( " my_add " ) ;
2013-12-14 09:09:51 +08:00
REQUIRE_NOTHROW ( lua . script ( " function my_nothing(i, j, k) end " ) ) ;
auto fvoid = lua . get < sol : : function > ( " my_nothing " ) ;
2013-12-12 01:42:00 +08:00
int a ;
2013-12-14 09:09:51 +08:00
REQUIRE_NOTHROW ( fvoid ( 1 , 2 , 3 ) ) ;
2013-12-12 01:42:00 +08:00
REQUIRE_NOTHROW ( a = f . call < int > ( 1 , 2 , 3 ) ) ;
REQUIRE ( a = = 6 ) ;
REQUIRE_THROWS ( a = f . call < int > ( 1 , 2 , " arf " ) ) ;
2013-12-12 00:18:13 +08:00
}
2013-12-11 21:32:27 +08:00
2013-12-22 08:30:30 +08:00
TEST_CASE ( " simple/call_c++_function " , " C++ function is called from lua " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
2013-12-11 21:32:27 +08:00
2013-12-12 00:18:13 +08:00
lua . set_function ( " plop_xyz " , plop_xyz ) ;
lua . script ( " x = plop_xyz(2, 6, 'hello') " ) ;
2014-04-27 13:18:54 +08:00
2013-12-12 00:18:13 +08:00
REQUIRE ( lua . get < int > ( " x " ) = = 11 ) ;
2013-12-11 21:32:27 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " simple/call_lambda " , " A C++ lambda is exposed to lua and called " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
int x = 0 ;
2013-12-11 21:32:27 +08:00
2013-12-22 11:11:20 +08:00
lua . set_function ( " foo " , [ & x ] { x = 1 ; } ) ;
2013-12-11 21:32:27 +08:00
2013-12-12 00:18:13 +08:00
lua . script ( " foo() " ) ;
2013-12-11 21:32:27 +08:00
2013-12-12 00:18:13 +08:00
REQUIRE ( x = = 1 ) ;
2013-12-11 21:32:27 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " advanced/get_and_call " , " Checks for lambdas returning values after a get operation " ) {
2013-12-14 13:15:14 +08:00
const static std : : string lol = " lol " , str = " str " ;
const static std : : tuple < int , float , double , std : : string > heh_tuple = std : : make_tuple ( 1 , 6.28f , 3.14 , std : : string ( " heh " ) ) ;
2013-12-12 00:18:13 +08:00
sol : : state lua ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " a " , [ ] { return 42 ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " a " ) . call < int > ( ) = = 42 ) ;
2014-04-27 13:18:54 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " b " , [ ] { return 42u ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " b " ) . call < unsigned int > ( ) = = 42u ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " c " , [ ] { return 3.14 ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " c " ) . call < double > ( ) = = 3.14 ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " d " , [ ] { return 6.28f ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " d " ) . call < float > ( ) = = 6.28f ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " e " , [ ] { return " lol " ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " e " ) . call < std : : string > ( ) = = lol ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " f " , [ ] { return true ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " f " ) . call < bool > ( ) ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " g " , [ ] { return std : : string ( " str " ) ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " g " ) . call < std : : string > ( ) = = str ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " h " , [ ] { } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE_NOTHROW ( lua . get < sol : : function > ( " h " ) . call ( ) ) ;
2013-12-14 13:15:14 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " i " , [ ] { return sol : : nil ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( lua . get < sol : : function > ( " i " ) . call < sol : : nil_t > ( ) = = sol : : nil ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " j " , [ ] { return std : : make_tuple ( 1 , 6.28f , 3.14 , std : : string ( " heh " ) ) ; } ) ) ;
2013-12-17 00:07:10 +08:00
REQUIRE ( ( lua . get < sol : : function > ( " j " ) . call < int , float , double , std : : string > ( ) = = heh_tuple ) ) ;
2013-12-12 00:18:13 +08:00
}
2013-12-11 21:32:27 +08:00
2013-12-22 08:30:30 +08:00
TEST_CASE ( " advanced/operator[]_calls " , " Checks for lambdas returning values using operator[] " ) {
const static std : : string lol = " lol " , str = " str " ;
const static std : : tuple < int , float , double , std : : string > heh_tuple = std : : make_tuple ( 1 , 6.28f , 3.14 , std : : string ( " heh " ) ) ;
sol : : state lua ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " a " , [ ] { return 42 ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " a " ] . call < int > ( ) = = 42 ) ;
2014-04-27 13:18:54 +08:00
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " b " , [ ] { return 42u ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " b " ] . call < unsigned int > ( ) = = 42u ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " c " , [ ] { return 3.14 ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " c " ] . call < double > ( ) = = 3.14 ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " d " , [ ] { return 6.28f ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " d " ] . call < float > ( ) = = 6.28f ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " e " , [ ] { return " lol " ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " e " ] . call < std : : string > ( ) = = lol ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " f " , [ ] { return true ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " f " ] . call < bool > ( ) ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " g " , [ ] { return std : : string ( " str " ) ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " g " ] . call < std : : string > ( ) = = str ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " h " , [ ] { } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE_NOTHROW ( lua [ " h " ] . call ( ) ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " i " , [ ] { return sol : : nil ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lua [ " i " ] . call < sol : : nil_t > ( ) = = sol : : nil ) ;
2013-12-22 11:11:20 +08:00
REQUIRE_NOTHROW ( lua . set_function ( " j " , [ ] { return std : : make_tuple ( 1 , 6.28f , 3.14 , std : : string ( " heh " ) ) ; } ) ) ;
2013-12-22 08:30:30 +08:00
REQUIRE ( ( lua [ " j " ] . call < int , float , double , std : : string > ( ) = = heh_tuple ) ) ;
}
TEST_CASE ( " advanced/call_lambdas " , " A C++ lambda is exposed to lua and called " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
2013-12-11 21:32:27 +08:00
2013-12-12 00:18:13 +08:00
int x = 0 ;
2013-12-22 11:11:20 +08:00
lua . set_function ( " set_x " , [ & ] ( int new_x ) {
2013-12-12 00:18:13 +08:00
x = new_x ;
return 0 ;
} ) ;
lua . script ( " set_x(9) " ) ;
REQUIRE ( x = = 9 ) ;
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " negative/basic_errors " , " Check if error handling works correctly " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
REQUIRE_THROWS ( lua . script ( " nil[5] " ) ) ;
2013-12-11 21:32:27 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " libraries " , " Check if we can open libraries " ) {
2013-12-12 07:14:12 +08:00
sol : : state lua ;
REQUIRE_NOTHROW ( lua . open_libraries ( sol : : lib : : base , sol : : lib : : os ) ) ;
}
TEST_CASE ( " tables/variables " , " Check if tables and variables work as intended " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base , sol : : lib : : os ) ;
2013-12-12 00:18:13 +08:00
lua . get < sol : : table > ( " os " ) . set ( " name " , " windows " ) ;
2014-04-27 13:18:54 +08:00
REQUIRE_NOTHROW ( lua . script ( " assert(os.name == \" windows \" ) " ) ) ;
2013-12-12 07:14:12 +08:00
}
TEST_CASE ( " tables/functions_variables " , " Check if tables and function calls work as intended " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base , sol : : lib : : os ) ;
2013-12-22 11:11:20 +08:00
auto run_script = [ ] ( sol : : state & lua ) - > void {
2013-12-12 07:14:12 +08:00
lua . script ( " assert(os.fun() == \" test \" ) " ) ;
} ;
2013-12-12 00:18:13 +08:00
lua . get < sol : : table > ( " os " ) . set_function ( " fun " ,
2013-12-22 11:11:20 +08:00
[ ] ( ) {
2013-12-12 07:14:12 +08:00
std : : cout < < " stateless lambda() " < < std : : endl ;
return " test " ;
}
2014-06-29 14:16:48 +08:00
) ;
2013-12-12 07:14:12 +08:00
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
2013-12-12 00:18:13 +08:00
lua . get < sol : : table > ( " os " ) . set_function ( " fun " , & free_function ) ;
2013-12-12 07:14:12 +08:00
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
2013-12-12 00:18:13 +08:00
2014-06-29 14:16:48 +08:00
// l-value, canNOT optimise
// prefer value semantics unless wrapped with std::reference_wrapper
{
2013-12-12 00:18:13 +08:00
auto lval = object ( ) ;
lua . get < sol : : table > ( " os " ) . set_function ( " fun " , & object : : operator ( ) , lval ) ;
2014-06-29 14:16:48 +08:00
}
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
auto reflval = object ( ) ;
lua . get < sol : : table > ( " os " ) . set_function ( " fun " , & object : : operator ( ) , std : : ref ( reflval ) ) ;
2013-12-14 13:32:45 +08:00
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
2013-12-12 00:18:13 +08:00
2014-06-29 14:16:48 +08:00
2014-01-19 12:10:49 +08:00
// stateful lambda: non-convertible, cannot be optimised
2013-12-12 00:18:13 +08:00
int breakit = 50 ;
lua . get < sol : : table > ( " os " ) . set_function ( " fun " ,
2013-12-22 11:11:20 +08:00
[ & breakit ] ( ) {
2014-06-29 14:16:48 +08:00
std : : cout < < " stateful lambda() " < < std : : endl ;
return " test " ;
}
) ;
2013-12-12 07:14:12 +08:00
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
2013-12-12 00:18:13 +08:00
2014-01-19 12:10:49 +08:00
// r-value, cannot optimise
2013-12-12 00:18:13 +08:00
lua . get < sol : : table > ( " os " ) . set_function ( " fun " , & object : : operator ( ) , object ( ) ) ;
2013-12-12 07:14:12 +08:00
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
2013-12-12 00:18:13 +08:00
2014-01-19 12:10:49 +08:00
// r-value, cannot optimise
2013-12-12 00:18:13 +08:00
auto rval = object ( ) ;
lua . get < sol : : table > ( " os " ) . set_function ( " fun " , & object : : operator ( ) , std : : move ( rval ) ) ;
2013-12-12 07:14:12 +08:00
REQUIRE_NOTHROW ( run_script ( lua ) ) ;
2013-12-13 09:20:11 +08:00
}
2014-06-29 14:16:48 +08:00
TEST_CASE ( " functions/overloaded " , " Check if overloaded function resolution templates compile/work " ) {
sol : : state lua ;
2014-07-02 10:18:03 +08:00
lua . open_libraries ( sol : : lib : : base ) ;
2014-06-29 14:16:48 +08:00
lua . set_function ( " non_overloaded " , non_overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " x = non_overloaded(1) \n print(x) " ) ) ;
lua . set_function < int > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1)) " ) ) ;
lua . set_function < int , int > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1, 2)) " ) ) ;
lua . set_function < int ( int , int ) > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1, 2)) " ) ) ;
lua . set_function < int , int , int > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1, 2, 3)) " ) ) ;
}
2013-12-22 11:11:20 +08:00
TEST_CASE ( " functions/return_order_and_multi_get " , " Check if return order is in the same reading order specified in Lua " ) {
2013-12-16 05:27:20 +08:00
const static std : : tuple < int , int , int > triple = std : : make_tuple ( 10 , 11 , 12 ) ;
sol : : state lua ;
2014-04-27 13:18:54 +08:00
lua . set_function ( " f " , [ ] {
return std : : make_tuple ( 10 , 11 , 12 ) ;
2013-12-22 11:11:20 +08:00
} ) ;
2013-12-16 11:09:06 +08:00
lua . script ( " function g() return 10, 11, 12 end \n x,y,z = g() " ) ;
auto tcpp = lua . get < sol : : function > ( " f " ) . call < int , int , int > ( ) ;
auto tlua = lua . get < sol : : function > ( " g " ) . call < int , int , int > ( ) ;
auto tluaget = lua . get < int , int , int > ( " x " , " y " , " z " ) ;
std : : cout < < " cpp: " < < std : : get < 0 > ( tcpp ) < < ' , ' < < std : : get < 1 > ( tcpp ) < < ' , ' < < std : : get < 2 > ( tcpp ) < < std : : endl ;
std : : cout < < " lua: " < < std : : get < 0 > ( tlua ) < < ' , ' < < std : : get < 1 > ( tlua ) < < ' , ' < < std : : get < 2 > ( tlua ) < < std : : endl ;
std : : cout < < " lua.xyz: " < < lua . get < int > ( " x " ) < < ' , ' < < lua . get < int > ( " y " ) < < ' , ' < < lua . get < int > ( " z " ) < < std : : endl ;
REQUIRE ( tcpp = = triple ) ;
REQUIRE ( tlua = = triple ) ;
REQUIRE ( tluaget = = triple ) ;
2013-12-22 08:30:30 +08:00
}
2014-05-31 07:58:47 +08:00
TEST_CASE ( " functions/sol::function to std::function " , " check if conversion to std::function works properly and calls with correct arguments " ) {
2014-05-31 07:10:08 +08:00
sol : : state lua ;
2014-05-31 07:58:47 +08:00
lua . open_libraries ( sol : : lib : : base ) ;
2014-05-31 07:10:08 +08:00
2014-05-31 07:58:47 +08:00
lua . set_function ( " testFunc " , test_free_func ) ;
lua . set_function ( " testFunc2 " , test_free_func2 ) ;
2014-05-31 07:10:08 +08:00
lua . script (
" testFunc(function() print( \" hello std::function \" ) end) "
2014-06-08 04:33:39 +08:00
) ;
2014-05-31 07:10:08 +08:00
lua . script (
" function m(a) \n "
" print( \" hello std::function with arg \" , a) \n "
" return a \n "
" end \n "
" \n "
" testFunc2(m, 1) "
2014-06-08 04:33:39 +08:00
) ;
2014-05-31 07:10:08 +08:00
}
2014-06-07 23:00:27 +08:00
TEST_CASE ( " functions/returning functions from C++ and getting in lua " , " check to see if returning a functor and getting a functor from lua is possible " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2014-06-08 04:33:39 +08:00
lua . set_function ( " makefn " , makefn ) ;
lua . set_function ( " takefn " , takefn ) ;
lua . script ( " afx = makefn() \n "
2014-06-07 23:00:27 +08:00
" print(afx()) \n "
2014-06-08 04:33:39 +08:00
" takefn(afx) \n " ) ;
2014-06-07 23:00:27 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " tables/operator[] " , " Check if operator[] retrieval and setting works properly " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . script ( " foo = 20 \n bar = \" hello world \" " ) ;
2014-04-27 13:18:54 +08:00
// basic retrieval
2013-12-22 08:30:30 +08:00
std : : string bar = lua [ " bar " ] ;
int foo = lua [ " foo " ] ;
REQUIRE ( bar = = " hello world " ) ;
REQUIRE ( foo = = 20 ) ;
// test operator= for stringification
2013-12-22 11:00:28 +08:00
// errors due to ambiguous operators
2013-12-22 08:30:30 +08:00
bar = lua [ " bar " ] ;
// basic setting
lua [ " bar " ] = 20.4 ;
lua [ " foo " ] = " goodbye " ;
// doesn't modify the actual values obviously.
REQUIRE ( bar = = " hello world " ) ;
REQUIRE ( foo = = 20 ) ;
// function setting
lua [ " test " ] = plop_xyz ;
REQUIRE_NOTHROW ( lua . script ( " assert(test(10, 11, \" hello \" ) == 11) " ) ) ;
// function retrieval
2013-12-22 11:11:20 +08:00
sol : : function test = lua [ " test " ] ;
2013-12-22 08:30:30 +08:00
REQUIRE ( test . call < int > ( 10 , 11 , " hello " ) = = 11 ) ;
// setting a lambda
lua [ " lamb " ] = [ ] ( int x ) {
return x * 2 ;
} ;
REQUIRE_NOTHROW ( lua . script ( " assert(lamb(220) == 440) " ) ) ;
// function retrieval of a lambda
2013-12-22 11:11:20 +08:00
sol : : function lamb = lua [ " lamb " ] ;
2013-12-22 08:30:30 +08:00
REQUIRE ( lamb . call < int > ( 220 ) = = 440 ) ;
// test const table retrieval
auto assert1 = [ ] ( const sol : : table & t ) {
std : : string a = t [ " foo " ] ;
2013-12-22 11:11:20 +08:00
int b = t [ " bar " ] ;
2013-12-22 08:30:30 +08:00
std : : cout < < a < < ' , ' < < b < < ' \n ' ;
} ;
REQUIRE_NOTHROW ( assert1 ( lua . global_table ( ) ) ) ;
2013-12-22 11:00:28 +08:00
}
2014-04-26 07:41:03 +08:00
2014-04-26 09:23:57 +08:00
TEST_CASE ( " tables/userdata " , " Show that we can create classes from userdata and use them " ) {
sol : : state lua ;
2014-04-27 14:35:11 +08:00
sol : : userdata < fuser > lc { " add " , & fuser : : add , " add2 " , & fuser : : add2 } ;
2014-04-27 16:11:30 +08:00
lua . set_userdata ( lc ) ;
2014-04-26 09:23:57 +08:00
lua . script ( " a = fuser:new() \n "
2014-04-27 13:18:54 +08:00
" b = a:add(1) \n "
" c = a:add2(1) \n " ) ;
2014-04-26 09:23:57 +08:00
sol : : object a = lua . get < sol : : object > ( " a " ) ;
sol : : object b = lua . get < sol : : object > ( " b " ) ;
sol : : object c = lua . get < sol : : object > ( " c " ) ;
2014-04-27 06:23:56 +08:00
REQUIRE ( ( a . is < sol : : userdata_t > ( ) ) ) ;
2014-04-26 09:23:57 +08:00
auto atype = a . get_type ( ) ;
auto btype = b . get_type ( ) ;
auto ctype = c . get_type ( ) ;
2014-04-27 06:23:56 +08:00
REQUIRE ( ( atype = = sol : : type : : userdata ) ) ;
2014-04-26 09:23:57 +08:00
REQUIRE ( ( btype = = sol : : type : : number ) ) ;
REQUIRE ( ( ctype = = sol : : type : : number ) ) ;
int bresult = b . as < int > ( ) ;
int cresult = c . as < int > ( ) ;
REQUIRE ( bresult = = 1 ) ;
REQUIRE ( cresult = = 3 ) ;
2014-04-27 06:23:56 +08:00
}
TEST_CASE ( " tables/userdata constructors " , " Show that we can create classes from userdata and use them with multiple destructors " ) {
sol : : state lua ;
sol : : constructors < sol : : types < > , sol : : types < int > , sol : : types < int , int > > con ;
2014-04-27 14:35:11 +08:00
sol : : userdata < crapola : : fuser > lc ( " crapola_fuser " , con , " add " , & crapola : : fuser : : add , " add2 " , & crapola : : fuser : : add2 ) ;
2014-04-27 16:11:30 +08:00
lua . set_userdata ( lc ) ;
2014-04-27 06:23:56 +08:00
lua . script (
2014-04-27 13:18:54 +08:00
" a = crapola_fuser.new(2) \n "
" u = a:add(1) \n "
" v = a:add2(1) \n "
" b = crapola_fuser:new() \n "
" w = b:add(1) \n "
" x = b:add2(1) \n "
" c = crapola_fuser.new(2, 3) \n "
" y = c:add(1) \n "
" z = c:add2(1) \n " ) ;
2014-04-27 06:23:56 +08:00
sol : : object a = lua . get < sol : : object > ( " a " ) ;
auto atype = a . get_type ( ) ;
REQUIRE ( ( atype = = sol : : type : : userdata ) ) ;
sol : : object u = lua . get < sol : : object > ( " u " ) ;
sol : : object v = lua . get < sol : : object > ( " v " ) ;
REQUIRE ( ( u . as < int > ( ) = = 3 ) ) ;
REQUIRE ( ( v . as < int > ( ) = = 5 ) ) ;
2014-04-27 13:18:54 +08:00
2014-04-27 06:23:56 +08:00
sol : : object b = lua . get < sol : : object > ( " b " ) ;
auto btype = b . get_type ( ) ;
REQUIRE ( ( btype = = sol : : type : : userdata ) ) ;
sol : : object w = lua . get < sol : : object > ( " w " ) ;
sol : : object x = lua . get < sol : : object > ( " x " ) ;
REQUIRE ( ( w . as < int > ( ) = = 1 ) ) ;
REQUIRE ( ( x . as < int > ( ) = = 3 ) ) ;
2014-04-27 13:18:54 +08:00
2014-04-27 06:23:56 +08:00
sol : : object c = lua . get < sol : : object > ( " c " ) ;
auto ctype = c . get_type ( ) ;
REQUIRE ( ( ctype = = sol : : type : : userdata ) ) ;
sol : : object y = lua . get < sol : : object > ( " y " ) ;
sol : : object z = lua . get < sol : : object > ( " z " ) ;
REQUIRE ( ( y . as < int > ( ) = = 7 ) ) ;
REQUIRE ( ( z . as < int > ( ) = = 9 ) ) ;
2014-04-27 17:09:28 +08:00
}
TEST_CASE ( " tables/userdata utility " , " Show internal management of classes registered through new_userdata " ) {
sol : : state lua ;
lua . new_userdata < fuser > ( " fuser " , " add " , & fuser : : add , " add2 " , & fuser : : add2 ) ;
lua . script ( " a = fuser.new() \n "
2014-05-26 02:41:06 +08:00
" b = a:add(1) \n "
" c = a:add2(1) \n " ) ;
2014-04-27 17:09:28 +08:00
sol : : object a = lua . get < sol : : object > ( " a " ) ;
sol : : object b = lua . get < sol : : object > ( " b " ) ;
sol : : object c = lua . get < sol : : object > ( " c " ) ;
REQUIRE ( ( a . is < sol : : userdata_t > ( ) ) ) ;
auto atype = a . get_type ( ) ;
auto btype = b . get_type ( ) ;
auto ctype = c . get_type ( ) ;
REQUIRE ( ( atype = = sol : : type : : userdata ) ) ;
REQUIRE ( ( btype = = sol : : type : : number ) ) ;
REQUIRE ( ( ctype = = sol : : type : : number ) ) ;
int bresult = b . as < int > ( ) ;
int cresult = c . as < int > ( ) ;
REQUIRE ( bresult = = 1 ) ;
REQUIRE ( cresult = = 3 ) ;
}
2014-05-26 02:41:06 +08:00
TEST_CASE ( " tables/userdata utility derived " , " userdata classes must play nice when a derived class does not overload a publically visible base function " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
sol : : constructors < sol : : types < int > > basector ;
sol : : userdata < Base > baseuserdata ( " Base " , basector , " get_num " , & Base : : get_num ) ;
lua . set_userdata ( baseuserdata ) ;
lua . script ( " base = Base.new(5) " ) ;
lua . script ( " print(base:get_num()) " ) ;
sol : : constructors < sol : : types < int > > derivedctor ;
sol : : userdata < Derived > deriveduserdata ( " Derived " , derivedctor , " get_num " , & Derived : : get_num , " get_num_10 " , & Derived : : get_num_10 ) ;
lua . set_userdata ( deriveduserdata ) ;
lua . script ( " derived = Derived.new(7) " ) ;
lua . script ( " dgn10 = derived:get_num_10() \n print(dgn10) " ) ;
lua . script ( " dgn = derived:get_num() \n print(dgn) " ) ;
REQUIRE ( ( lua . get < int > ( " dgn10 " ) = = 70 ) ) ;
REQUIRE ( ( lua . get < int > ( " dgn " ) = = 7 ) ) ;
}
2014-05-31 07:58:47 +08:00
TEST_CASE ( " tables/self-referential userdata " , " userdata classes must play nice when C++ object types are requested for C++ code " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_userdata < self_test > ( " test " , " g " , & self_test : : g , " f " , & self_test : : f ) ;
lua . script (
" local a = test.new() \n "
" a:g( \" woof \" ) \n "
" a:f(a) \n "
2014-06-08 04:33:39 +08:00
) ;
2014-05-31 07:58:47 +08:00
}
2014-06-01 14:41:16 +08:00
TEST_CASE ( " tables/arbitrary-creation " , " tables should be created from standard containers " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set_function ( " test_one " , test_table_return_one ) ;
lua . set_function ( " test_two " , test_table_return_two ) ;
lua . set_function ( " test_three " , test_table_return_three ) ;
REQUIRE_NOTHROW ( lua . script ( " a = test_one() " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " b = test_two() " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " c = test_three() " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(#a == 10, 'error') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(a[3] == 3, 'error') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(b.one == 1, 'error') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(b.three == 3, 'error') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(c.name == 'Rapptz', 'error') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(c.project == 'sol', 'error') " ) ) ;
auto & & a = lua . get < sol : : table > ( " a " ) ;
auto & & b = lua . get < sol : : table > ( " b " ) ;
auto & & c = lua . get < sol : : table > ( " c " ) ;
REQUIRE ( a . size ( ) = = 10ULL ) ;
REQUIRE ( a . get < int > ( 3 ) = = 3 ) ;
REQUIRE ( b . get < int > ( " one " ) = = 1 ) ;
REQUIRE ( b . get < int > ( " three " ) = = 3 ) ;
REQUIRE ( c . get < std : : string > ( " name " ) = = " Rapptz " ) ;
REQUIRE ( c . get < std : : string > ( " project " ) = = " sol " ) ;
}
2014-06-09 21:18:29 +08:00
TEST_CASE ( " tables/issue-number-twenty-five " , " Using pointers and references from C++ classes in Lua " ) {
struct test {
int x = 0 ;
test & set ( ) {
x = 10 ;
return * this ;
}
int get ( ) {
return x ;
}
2014-06-27 16:40:51 +08:00
test * pget ( ) {
2014-06-09 21:18:29 +08:00
return this ;
}
2014-06-27 16:40:51 +08:00
test create_get ( ) {
2014-06-27 16:25:57 +08:00
return * this ;
}
2014-06-09 21:18:29 +08:00
int fun ( int x ) {
return x * 10 ;
}
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2014-06-27 16:25:57 +08:00
lua . new_userdata < test > ( " test " , " set " , & test : : set , " get " , & test : : get , " pointer_get " , & test : : pget , " fun " , & test : : fun , " create_get " , & test : : create_get ) ;
2014-06-09 21:18:29 +08:00
REQUIRE_NOTHROW ( lua . script ( " x = test.new() \n "
" x:set():get() " ) ) ;
2014-06-27 16:25:57 +08:00
REQUIRE_NOTHROW ( lua . script ( " y = x:pointer_get() " ) ) ;
2014-06-09 21:18:29 +08:00
REQUIRE_NOTHROW ( lua . script ( " y:set():get() " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " y:fun(10) " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " x:fun(10) " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(y:fun(10) == x:fun(10), '...') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(y:fun(10) == 100, '...') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(y:set():get() == y:set():get(), '...') " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(y:set():get() == 10, '...') " ) ) ;
}
2014-06-27 16:25:57 +08:00
TEST_CASE ( " userdata/issue-number-thirty-five " , " using value types created from lua-called C++ code, fixing user-defined types with constructors " ) {
2014-06-27 16:40:51 +08:00
struct Line {
Vec p1 , p2 ;
Line ( ) : p1 { 0 , 0 , 0 } , p2 { 0 , 0 , 0 } { }
Line ( float x ) : p1 { x , x , x } , p2 { x , x , x } { }
Line ( const Vec & p1 ) : p1 { p1 } , p2 { p1 } { }
Line ( Vec p1 , Vec p2 ) : p1 { p1 } , p2 { p2 } { }
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
sol : : constructors < sol : : types < > , sol : : types < Vec > , sol : : types < Vec , Vec > > lctor ;
sol : : userdata < Line > ludata ( " Line " , lctor ) ;
lua . set_userdata ( ludata ) ;
sol : : constructors < sol : : types < float , float , float > > ctor ;
sol : : userdata < Vec > udata ( " Vec " , ctor , " normalized " , & Vec : : normalized , " length " , & Vec : : length ) ;
lua . set_userdata ( udata ) ;
REQUIRE_NOTHROW ( lua . script ( " v = Vec.new(1, 2, 3) \n "
" print(v:length()) " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " v = Vec.new(1, 2, 3) \n "
" print(v:normalized():length()) " ) ) ;
2014-06-27 16:25:57 +08:00
}
2014-06-28 12:34:18 +08:00
TEST_CASE ( " userdata/lua-stored-userdata " , " ensure userdata values can be stored without keeping userdata object alive " ) {
sol : : state lua ;
2014-07-02 10:18:03 +08:00
lua . open_libraries ( sol : : lib : : base ) ;
2014-06-28 12:34:18 +08:00
{
sol : : constructors < sol : : types < float , float , float > > ctor ;
sol : : userdata < Vec > udata ( " Vec " , ctor ,
" normalized " , & Vec : : normalized ,
" length " , & Vec : : length ) ;
lua . set_userdata ( udata ) ;
// userdata dies, but still usable in lua!
}
2014-07-02 10:18:03 +08:00
REQUIRE_NOTHROW ( lua . script ( " collectgarbage() \n "
2014-06-28 12:34:18 +08:00
" v = Vec.new(1, 2, 3) \n "
2014-06-29 14:16:48 +08:00
" print(v:length()) " ) ) ;
2014-06-28 12:34:18 +08:00
2014-07-02 10:18:03 +08:00
REQUIRE_NOTHROW ( lua . script ( " v = Vec.new(1, 2, 3) \n "
2014-06-29 14:16:48 +08:00
" print(v:normalized():length()) " ) ) ;
2014-06-28 12:34:18 +08:00
}
2014-07-28 03:56:24 +08:00
TEST_CASE ( " userdata/member-variables " , " allow table-like accessors to behave as member variables for userdata " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
sol : : constructors < sol : : types < float , float , float > > ctor ;
sol : : userdata < Vec > udata ( " Vec " , ctor ,
" x " , & Vec : : x ,
" y " , & Vec : : y ,
" z " , & Vec : : z ,
" normalized " , & Vec : : normalized ,
" length " , & Vec : : length ) ;
lua . set_userdata ( udata ) ;
REQUIRE_NOTHROW ( lua . script ( " v = Vec.new(1, 2, 3) \n "
" v2 = Vec.new(0, 1, 0) \n "
" print(v:length()) \n "
" v.x = 2 \n "
" v2.y = 2 \n "
" print(v.x, v.y, v.z) \n "
" print(v2.x, v2.y, v2.z) \n "
" assert(v.x == 2) \n "
" assert(v2.x == 0) \n "
" assert(v2.y == 2) \n "
" v.x = 3 \n "
" local x = v.x \n "
" assert(x == 3) \n "
) ) ;
}