2013-12-11 21:32:27 +08:00
# define CATCH_CONFIG_MAIN
2015-06-18 06:33:58 +08:00
# define SOL_CHECK_ARGUMENTS
2013-12-11 21:32:27 +08:00
# 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
}
} ;
2016-02-11 01:12:09 +08:00
int func_1 ( int ) {
2016-02-11 00:36:00 +08:00
return 1 ;
}
std : : string func_1s ( std : : string a ) {
return " string: " + a ;
}
2016-02-11 01:12:09 +08:00
int func_2 ( int , int ) {
2016-02-11 00:36:00 +08:00
return 2 ;
}
2016-02-11 01:12:09 +08:00
void func_3 ( int , int , int ) {
2016-02-11 00:36:00 +08:00
}
2014-09-18 12:23:46 +08:00
struct vars {
vars ( ) {
}
int boop = 0 ;
~ vars ( ) {
}
} ;
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 } ;
}
} ;
2014-08-09 19:54:58 +08:00
struct giver {
int a = 0 ;
giver ( ) {
}
void gief ( ) {
a = 1 ;
}
static void stuff ( ) {
}
static void gief_stuff ( giver & t , int a ) {
t . a = a ;
}
~ giver ( ) {
}
} ;
2016-02-01 16:27:06 +08:00
TEST_CASE ( " simple/set " , " Check if the set works properly. " ) {
2013-12-12 00:18:13 +08:00
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 " ) ) ;
2016-02-01 16:27:06 +08:00
lua . set ( " e " , std : : string ( " hello " ) , " f " , true ) ;
2013-12-12 00:18:13 +08:00
REQUIRE_NOTHROW ( lua . script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " ) ) ;
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' " ) ;
lua . script ( " e = true " ) ;
2016-02-01 16:27:06 +08:00
std : : string d ;
bool e ;
std : : tie ( d , e ) = lua . get < std : : string , bool > ( " d " , " e " ) ;
REQUIRE ( d = = " hello " ) ;
2013-12-12 00:18:13 +08:00
REQUIRE ( e = = true ) ;
}
2016-02-02 00:56:44 +08:00
TEST_CASE ( " simple/set-get-global-integer " , " Tests if the get function works properly with global integers " ) {
sol : : state lua ;
lua [ 1 ] = 25.4 ;
lua . script ( " b = 1 " ) ;
double a = lua . get < double > ( 1 ) ;
double b = lua . get < double > ( " b " ) ;
REQUIRE ( a = = 25.4 ) ;
REQUIRE ( b = = 1 ) ;
}
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 ) ;
2016-02-01 16:27:06 +08:00
REQUIRE_THROWS ( a = f ( 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 ) ;
2015-05-25 09:29:21 +08:00
REQUIRE_NOTHROW ( lua . script ( " x = non_overloaded(1, 2, 3) \n print(x) " ) ) ;
2014-06-29 14:16:48 +08:00
2014-08-06 00:07:29 +08:00
/*
// Cannot reasonably support: clang++ refuses to try enough
// deductions to make this work
2014-06-29 14:16:48 +08:00
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)) " ) ) ;
2014-08-06 00:07:29 +08:00
lua . set_function < int , int , int > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1, 2, 3)) " ) ) ;
*/
lua . set_function < int ( int ) > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1)) " ) ) ;
2014-06-29 14:16:48 +08:00
lua . set_function < int ( int , int ) > ( " overloaded " , overloaded ) ;
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1, 2)) " ) ) ;
2014-08-06 00:07:29 +08:00
lua . set_function < int ( int , int , int ) > ( " overloaded " , overloaded ) ;
2015-05-25 09:29:21 +08:00
REQUIRE_NOTHROW ( lua . script ( " print(overloaded(1, 2, 3)) " ) ) ;
2014-06-29 14:16:48 +08:00
}
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 ) ;
2015-10-25 19:44:17 +08:00
const static std : : tuple < int , float > paired = std : : make_tuple ( 10 , 10.f ) ;
2013-12-16 05:27:20 +08:00
sol : : state lua ;
2014-04-27 13:18:54 +08:00
lua . set_function ( " f " , [ ] {
return std : : make_tuple ( 10 , 11 , 12 ) ;
2015-10-25 19:44:17 +08:00
} ) ;
int a = 0 ;
lua . set_function ( " h " , [ ] ( ) {
return std : : make_tuple ( 10 , 10.0f ) ;
} ) ;
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 > ( ) ;
2015-10-25 19:44:17 +08:00
auto tlua = lua . get < sol : : function > ( " g " ) . call < int , int , int > ( ) ;
auto tcpp2 = lua . get < sol : : function > ( " h " ) . call < int , float > ( ) ;
auto tluaget = lua . get < int , int , int > ( " x " , " y " , " z " ) ;
2013-12-16 11:09:06 +08:00
REQUIRE ( tcpp = = triple ) ;
REQUIRE ( tlua = = triple ) ;
REQUIRE ( tluaget = = triple ) ;
2015-10-25 19:44:17 +08:00
REQUIRE ( tcpp2 = = paired ) ;
2013-12-22 08:30:30 +08:00
}
2015-07-22 14:54:43 +08:00
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 " ) {
const static std : : tuple < int , int , int > triple = std : : make_tuple ( 10 , 11 , 12 ) ;
sol : : state lua ;
lua . set_function ( " f_string " , [ ] ( ) { return " this is a string! " ; } ) ;
sol : : function f_string = lua [ " f_string " ] ;
// Make sure there are no overload collisions / compiler errors for automatic string conversions
std : : string f_string_result = f_string ( ) ;
REQUIRE ( f_string_result = = " this is a string! " ) ;
f_string_result = f_string ( ) ;
REQUIRE ( f_string_result = = " this is a string! " ) ;
lua . set_function ( " f " , [ ] {
return std : : make_tuple ( 10 , 11 , 12 ) ;
} ) ;
lua . script ( " function g() return 10, 11, 12 end \n x,y,z = g() " ) ;
std : : tuple < int , int , int > tcpp = lua . get < sol : : function > ( " f " ) ( ) ;
std : : tuple < int , int , int > tlua = lua . get < sol : : function > ( " g " ) ( ) ;
std : : tuple < int , int , int > 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 ) ;
}
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 ' ;
} ;
2016-01-09 05:16:06 +08:00
REQUIRE_NOTHROW ( assert1 ( lua . global ( ) ) ) ;
2013-12-22 11:00:28 +08:00
}
2014-04-26 07:41:03 +08:00
2014-09-19 20:22:21 +08:00
TEST_CASE ( " tables/usertype " , " Show that we can create classes from usertype and use them " ) {
2014-04-26 09:23:57 +08:00
sol : : state lua ;
2014-09-19 20:22:21 +08:00
sol : : usertype < fuser > lc { " add " , & fuser : : add , " add2 " , & fuser : : add2 } ;
lua . set_usertype ( 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 " ) ;
2015-03-02 10:14:42 +08:00
REQUIRE ( ( a . is < sol : : userdata > ( ) ) ) ;
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
}
2016-02-01 16:27:06 +08:00
TEST_CASE ( " tables/usertype constructors " , " Show that we can create classes from usertype and use them with multiple constructors " ) {
2014-04-27 06:23:56 +08:00
sol : : state lua ;
sol : : constructors < sol : : types < > , sol : : types < int > , sol : : types < int , int > > con ;
2014-09-19 20:22:21 +08:00
sol : : usertype < crapola : : fuser > lc ( con , " add " , & crapola : : fuser : : add , " add2 " , & crapola : : fuser : : add2 ) ;
lua . set_usertype ( 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
}
2014-09-19 20:22:21 +08:00
TEST_CASE ( " tables/usertype utility " , " Show internal management of classes registered through new_usertype " ) {
2014-04-27 17:09:28 +08:00
sol : : state lua ;
2014-09-19 20:22:21 +08:00
lua . new_usertype < fuser > ( " fuser " , " add " , & fuser : : add , " add2 " , & fuser : : add2 ) ;
2014-04-27 17:09:28 +08:00
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 " ) ;
2015-03-02 10:14:42 +08:00
REQUIRE ( ( a . is < sol : : userdata > ( ) ) ) ;
2014-04-27 17:09:28 +08:00
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
2014-09-19 20:22:21 +08:00
TEST_CASE ( " tables/usertype utility derived " , " usertype classes must play nice when a derived class does not overload a publically visible base function " ) {
2014-05-26 02:41:06 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
sol : : constructors < sol : : types < int > > basector ;
2014-09-19 20:22:21 +08:00
sol : : usertype < Base > baseusertype ( basector , " get_num " , & Base : : get_num ) ;
2014-05-26 02:41:06 +08:00
2014-09-19 20:22:21 +08:00
lua . set_usertype ( baseusertype ) ;
2014-05-26 02:41:06 +08:00
lua . script ( " base = Base.new(5) " ) ;
2016-02-01 16:27:06 +08:00
REQUIRE_NOTHROW ( lua . script ( " print(base:get_num()) " ) ) ;
2014-05-26 02:41:06 +08:00
2016-02-02 00:56:44 +08:00
sol : : constructors < sol : : types < int > > derivedctor ;
2016-02-01 16:27:06 +08:00
sol : : usertype < Derived > derivedusertype ( derivedctor ,
" get_num_10 " , & Derived : : get_num_10 ,
" get_num " , & Derived : : get_num
) ;
2014-05-26 02:41:06 +08:00
2014-09-19 20:22:21 +08:00
lua . set_usertype ( derivedusertype ) ;
2014-05-26 02:41:06 +08:00
lua . script ( " derived = Derived.new(7) " ) ;
2016-02-01 16:27:06 +08:00
Derived & derived = lua [ " derived " ] ;
lua . script ( " dgn = derived:get_num() \n "
" print(dgn) " ) ;
lua . script ( " dgn10 = derived:get_num_10() \n "
" print(dgn10) " ) ;
2014-05-26 02:41:06 +08:00
REQUIRE ( ( lua . get < int > ( " dgn10 " ) = = 70 ) ) ;
2016-02-02 00:56:44 +08:00
REQUIRE ( ( lua . get < int > ( " dgn " ) = = 7 ) ) ;
2014-05-26 02:41:06 +08:00
}
2014-05-31 07:58:47 +08:00
2014-09-19 20:22:21 +08:00
TEST_CASE ( " tables/self-referential usertype " , " usertype classes must play nice when C++ object types are requested for C++ code " ) {
2014-05-31 07:58:47 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2014-09-19 20:22:21 +08:00
lua . new_usertype < self_test > ( " test " , " g " , & self_test : : g , " f " , & self_test : : f ) ;
2014-05-31 07:58:47 +08:00
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
2015-05-16 10:26:18 +08:00
TEST_CASE ( " tables/for_each " , " Testing the use of for_each to get values from a lua table " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . script ( " arr = { \n "
" [0] = \" Hi \" , \n "
" [1] = 123.45, \n "
" [2] = \" String value \" , \n "
// Does nothing
//"[3] = nil,\n"
//"[nil] = 3,\n"
" [ \" WOOF \" ] = 123, \n "
" } " ) ;
sol : : table tbl = lua [ " arr " ] ;
std : : size_t tablesize = 4 ;
std : : size_t iterations = 0 ;
tbl . for_each (
[ & iterations ] ( sol : : object key , sol : : object value ) {
+ + iterations ;
sol : : type keytype = key . get_type ( ) ;
switch ( keytype ) {
case sol : : type : : number :
switch ( key . as < int > ( ) ) {
case 0 :
REQUIRE ( ( value . as < std : : string > ( ) = = " Hi " ) ) ;
break ;
case 1 :
REQUIRE ( ( value . as < double > ( ) = = 123.45 ) ) ;
break ;
case 2 :
REQUIRE ( ( value . as < std : : string > ( ) = = " String value " ) ) ;
break ;
case 3 :
REQUIRE ( ( value . is < sol : : nil_t > ( ) ) ) ;
break ;
}
break ;
case sol : : type : : string :
if ( key . as < std : : string > ( ) = = " WOOF " ) {
REQUIRE ( ( value . as < double > ( ) = = 123 ) ) ;
}
break ;
case sol : : type : : nil :
REQUIRE ( ( value . as < double > ( ) = = 3 ) ) ;
break ;
default :
break ;
}
}
) ;
REQUIRE ( iterations = = tablesize ) ;
}
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 ;
}
2015-03-02 10:14:42 +08:00
int fun ( int xa ) {
return xa * 10 ;
2014-06-09 21:18:29 +08:00
}
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2014-09-19 20:22:21 +08:00
lua . new_usertype < test > ( " test " , " set " , & test : : set , " get " , & test : : get , " pointer_get " , & test : : pget , " fun " , & test : : fun , " create_get " , & test : : create_get ) ;
2015-03-02 10:14:42 +08:00
REQUIRE_NOTHROW ( lua . script ( " x = test.new() " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(x:set():get() == 10) " ) ) ;
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
2014-09-19 20:22:21 +08:00
TEST_CASE ( " usertype/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
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
sol : : constructors < sol : : types < float , float , float > > ctor ;
2014-09-19 20:22:21 +08:00
sol : : usertype < Vec > udata ( ctor , " normalized " , & Vec : : normalized , " length " , & Vec : : length ) ;
lua . set_usertype ( udata ) ;
2014-06-27 16:40:51 +08:00
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
2014-09-19 20:22:21 +08:00
TEST_CASE ( " usertype/lua-stored-usertype " , " ensure usertype values can be stored without keeping usertype object alive " ) {
2014-06-28 12:34:18 +08:00
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 ;
2014-09-19 20:22:21 +08:00
sol : : usertype < Vec > udata ( ctor ,
2014-06-28 12:34:18 +08:00
" normalized " , & Vec : : normalized ,
" length " , & Vec : : length ) ;
2014-09-19 20:22:21 +08:00
lua . set_usertype ( udata ) ;
// usertype dies, but still usable in lua!
2014-06-28 12:34:18 +08:00
}
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
2014-09-19 20:22:21 +08:00
TEST_CASE ( " usertype/member-variables " , " allow table-like accessors to behave as member variables for usertype " ) {
2014-07-28 03:56:24 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
sol : : constructors < sol : : types < float , float , float > > ctor ;
2014-09-19 20:22:21 +08:00
sol : : usertype < Vec > udata ( ctor ,
2014-07-28 03:56:24 +08:00
" x " , & Vec : : x ,
" y " , & Vec : : y ,
" z " , & Vec : : z ,
" normalized " , & Vec : : normalized ,
" length " , & Vec : : length ) ;
2014-09-19 20:22:21 +08:00
lua . set_usertype ( udata ) ;
2014-07-28 03:56:24 +08:00
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 "
) ) ;
}
2014-08-09 19:54:58 +08:00
2014-09-19 20:22:21 +08:00
TEST_CASE ( " usertype/nonmember functions implement functionality " , " let users set non-member functions that take unqualified T as first parameter to usertype " ) {
2014-08-09 19:54:58 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2014-09-19 20:22:21 +08:00
lua . new_usertype < giver > ( " giver " ,
" gief_stuff " , giver : : gief_stuff ,
" gief " , & giver : : gief ,
" __tostring " , [ ] ( const giver & t ) {
return std : : to_string ( t . a ) + " : giving value " ;
}
2014-08-09 19:54:58 +08:00
) . get < sol : : table > ( " giver " )
. set_function ( " stuff " , giver : : stuff ) ;
REQUIRE_NOTHROW ( lua . script ( " giver.stuff() " ) ) ;
REQUIRE_NOTHROW ( lua . script ( " t = giver.new() \n "
" print(tostring(t)) \n "
" t:gief() \n "
" t:gief_stuff(20) \n " ) ) ;
REQUIRE ( ( lua . get < giver > ( " t " ) . a = = 20 ) ) ;
}
2014-09-06 04:06:48 +08:00
TEST_CASE ( " regressions/one " , " issue number 48 " ) {
sol : : state lua ;
2014-09-19 20:22:21 +08:00
lua . new_usertype < vars > ( " vars " ,
" boop " , & vars : : boop ) ;
2014-09-07 13:06:08 +08:00
REQUIRE_NOTHROW ( lua . script ( " beep = vars.new() \n "
2014-09-06 04:06:48 +08:00
" beep.boop = 1 " ) ) ;
// test for segfault
auto my_var = lua . get < vars > ( " beep " ) ;
REQUIRE ( my_var . boop = = 1 ) ;
auto * ptr = & my_var ;
REQUIRE ( ptr - > boop = = 1 ) ;
}
2014-09-18 12:23:46 +08:00
TEST_CASE ( " references/get-set " , " properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type... " ) {
sol : : state lua ;
2014-09-19 20:22:21 +08:00
lua . new_usertype < vars > ( " vars " ,
2014-09-18 12:23:46 +08:00
" boop " , & vars : : boop ) ;
vars var { } ;
vars rvar { } ;
lua . set ( " beep " , var ) ;
lua . set ( " rbeep " , std : : ref ( rvar ) ) ;
auto & my_var = lua . get < vars > ( " beep " ) ;
2016-02-01 16:27:06 +08:00
auto & ref_var = lua . get < std : : reference_wrapper < vars > > ( " rbeep " ) ;
vars & proxy_my_var = lua [ " beep " ] ;
std : : reference_wrapper < vars > proxy_ref_var = lua [ " rbeep " ] ;
2014-09-18 12:23:46 +08:00
var . boop = 2 ;
rvar . boop = 5 ;
2016-02-01 16:27:06 +08:00
// Was return as a value: var must be diferent from "beep"
REQUIRE_FALSE ( std : : addressof ( var ) = = std : : addressof ( my_var ) ) ;
REQUIRE_FALSE ( std : : addressof ( proxy_my_var ) = = std : : addressof ( var ) ) ;
2014-09-18 12:23:46 +08:00
REQUIRE ( ( my_var . boop = = 0 ) ) ;
REQUIRE ( var . boop ! = my_var . boop ) ;
2016-02-01 16:27:06 +08:00
REQUIRE ( std : : addressof ( ref_var ) = = std : : addressof ( rvar ) ) ;
2016-02-11 01:12:09 +08:00
REQUIRE ( std : : addressof ( proxy_ref_var . get ( ) ) = = std : : addressof ( rvar ) ) ;
2016-02-01 16:27:06 +08:00
REQUIRE ( rvar . boop = = 5 ) ;
2014-09-18 12:23:46 +08:00
REQUIRE ( rvar . boop = = ref_var . boop ) ;
}
2015-05-27 14:23:37 +08:00
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 " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set_function ( " lol " , [ ] ( ) - > int * {
return nullptr ;
} ) ;
lua . set_function ( " rofl " , [ ] ( int * x ) {
std : : cout < < x < < std : : endl ;
} ) ;
REQUIRE_NOTHROW ( lua . script ( " x = lol() \n "
" rofl(x) \n "
" assert(x == nil) " ) ) ;
}
2015-10-23 14:54:26 +08:00
2016-02-01 16:27:06 +08:00
TEST_CASE ( " functions/function_result-protected_function " , " Function result should be the beefy return type for sol::function that allows for error checking and error handlers " ) {
2015-10-23 14:54:26 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base , sol : : lib : : debug ) ;
static const char errormessage1 [ ] = " true error message " ;
static const char errormessage2 [ ] = " doodle " ;
// Some function; just using a lambda to be cheap
auto doom = [ ] ( ) {
// Bypasses handler function: puts information directly into lua error
2015-10-25 18:48:19 +08:00
throw std : : runtime_error ( errormessage1 ) ;
2015-10-23 14:54:26 +08:00
} ;
auto luadoom = [ & lua ] ( ) {
// Does not bypass error function, will call it
luaL_error ( lua . lua_state ( ) , " BIG ERROR MESSAGES! " ) ;
} ;
2016-02-11 01:12:09 +08:00
auto specialhandler = [ ] ( std : : string ) {
2015-10-23 14:54:26 +08:00
return errormessage2 ;
} ;
lua . set_function ( " doom " , doom ) ;
lua . set_function ( " luadoom " , luadoom ) ;
lua . set_function ( " cpphandler " , specialhandler ) ;
lua . script (
std : : string ( " function handler ( message ) " )
+ " return ' " + errormessage2 + " ' "
+ " end "
) ;
2016-02-01 16:27:06 +08:00
sol : : protected_function func = lua [ " doom " ] ;
sol : : protected_function luafunc = lua [ " luadoom " ] ;
2015-10-23 14:54:26 +08:00
sol : : function luahandler = lua [ " handler " ] ;
sol : : function cpphandler = lua [ " cpphandler " ] ;
func . error_handler = luahandler ;
luafunc . error_handler = cpphandler ;
sol : : function_result result1 = func ( ) ;
int test = lua_gettop ( lua . lua_state ( ) ) ;
REQUIRE ( ! result1 . valid ( ) ) ;
std : : string errorstring = result1 ;
REQUIRE ( errorstring = = errormessage1 ) ;
sol : : function_result result2 = luafunc ( ) ;
REQUIRE ( ! result2 . valid ( ) ) ;
errorstring = result2 ;
REQUIRE ( errorstring = = errormessage2 ) ;
2016-02-01 16:27:06 +08:00
}
TEST_CASE ( " functions/destructor-tests " , " Show that proper copies / destruction happens " ) {
static int created = 0 ;
static int destroyed = 0 ;
static void * last_call = nullptr ;
static void * static_call = reinterpret_cast < void * > ( 0x01 ) ;
typedef void ( * fptr ) ( ) ;
struct x {
x ( ) { + + created ; }
x ( const x & ) { + + created ; }
x ( x & & ) { + + created ; }
2016-02-02 00:56:44 +08:00
x & operator = ( const x & ) { return * this ; }
x & operator = ( x & & ) { return * this ; }
2016-02-01 16:27:06 +08:00
void func ( ) { last_call = static_cast < void * > ( this ) ; } ;
2016-02-02 00:56:44 +08:00
~ x ( ) { + + destroyed ; }
2016-02-01 16:27:06 +08:00
} ;
struct y {
y ( ) { + + created ; }
y ( const x & ) { + + created ; }
y ( x & & ) { + + created ; }
y & operator = ( const x & ) { return * this ; }
y & operator = ( x & & ) { return * this ; }
static void func ( ) { last_call = static_call ; } ;
2016-02-02 00:56:44 +08:00
void operator ( ) ( ) { func ( ) ; }
operator fptr ( ) { return func ; }
2016-02-01 16:27:06 +08:00
~ y ( ) { + + destroyed ; }
} ;
// stateful functors/member functions should always copy unless specified
{
created = 0 ;
destroyed = 0 ;
last_call = nullptr ;
{
sol : : state lua ;
x x1 ;
lua . set_function ( " x1copy " , & x : : func , x1 ) ;
lua . script ( " x1copy() " ) ;
REQUIRE ( created = = 2 ) ;
REQUIRE ( destroyed = = 0 ) ;
REQUIRE_FALSE ( last_call = = & x1 ) ;
lua . set_function ( " x1ref " , & x : : func , std : : ref ( x1 ) ) ;
lua . script ( " x1ref() " ) ;
REQUIRE ( created = = 2 ) ;
REQUIRE ( destroyed = = 0 ) ;
REQUIRE ( last_call = = & x1 ) ;
}
REQUIRE ( created = = 2 ) ;
REQUIRE ( destroyed = = 2 ) ;
REQUIRE ( created = = destroyed ) ;
}
// things convertible to a static function should _never_ be forced to make copies
// therefore, pass through untouched
{
created = 0 ;
destroyed = 0 ;
last_call = nullptr ;
{
sol : : state lua ;
y y1 ;
lua . set_function ( " y1copy " , y1 ) ;
lua . script ( " y1copy() " ) ;
REQUIRE ( created = = 1 ) ;
REQUIRE ( destroyed = = 0 ) ;
REQUIRE ( last_call = = static_call ) ;
last_call = nullptr ;
lua . set_function ( " y1ref " , std : : ref ( y1 ) ) ;
lua . script ( " y1ref() " ) ;
REQUIRE ( created = = 1 ) ;
REQUIRE ( destroyed = = 0 ) ;
REQUIRE ( last_call = = static_call ) ;
}
REQUIRE ( created = = 1 ) ;
REQUIRE ( destroyed = = 1 ) ;
REQUIRE ( created = = destroyed ) ;
}
}
2015-10-23 14:54:26 +08:00
2016-02-01 16:27:06 +08:00
TEST_CASE ( " usertype/destructor-tests " , " Show that proper copies / destruction happens " ) {
static int created = 0 ;
static int destroyed = 0 ;
static void * last_call = nullptr ;
struct x {
x ( ) { + + created ; }
2016-02-02 00:56:44 +08:00
x ( const x & ) { + + created ; }
x ( x & & ) { + + created ; }
x & operator = ( const x & ) { return * this ; }
x & operator = ( x & & ) { return * this ; }
2016-02-01 16:27:06 +08:00
~ x ( ) { + + destroyed ; }
} ;
{
sol : : state lua ;
2016-02-02 00:56:44 +08:00
lua . new_usertype < x > ( " x " ) ;
2016-02-01 16:27:06 +08:00
x x1 ;
x x2 ;
lua . set ( " x1copy " , x1 , " x2copy " , x2 , " x1ref " , std : : ref ( x1 ) ) ;
x & x1copyref = lua [ " x1copy " ] ;
x & x2copyref = lua [ " x2copy " ] ;
x & x1ref = lua [ " x1ref " ] ;
REQUIRE ( created = = 4 ) ;
REQUIRE ( destroyed = = 0 ) ;
REQUIRE ( std : : addressof ( x1 ) = = std : : addressof ( x1ref ) ) ;
}
REQUIRE ( created = = 4 ) ;
REQUIRE ( destroyed = = 4 ) ;
REQUIRE ( created = = destroyed ) ;
2015-10-23 14:54:26 +08:00
}
2016-02-11 00:36:00 +08:00
TEST_CASE ( " functions/overloading " , " Check if overloading works properly for regular set function syntax " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set_function ( " func_1 " , func_1 ) ;
lua . set_function ( " func " , sol : : overload ( func_1 , func_1s , func_2 , func_3 ) ) ;
const std : : string string_bark = " string: bark " ;
REQUIRE_NOTHROW ( lua . script ( R " (
a = func ( 1 )
b = func ( " bark " )
c = func ( 1 , 2 )
func ( 1 , 2 , 3 )
) " ));
REQUIRE ( ( lua [ " a " ] = = 1 ) ) ;
REQUIRE ( ( lua [ " b " ] = = string_bark ) ) ;
REQUIRE ( ( lua [ " c " ] = = 2 ) ) ;
REQUIRE_THROWS ( lua . script ( " func(1,2,'meow') " ) ) ;
}
TEST_CASE ( " usertype/overloading " , " Check if overloading works properly for usertypes " ) {
struct woof {
int var ;
int func ( int x ) {
return var + x ;
}
double func2 ( int x , int y ) {
return var + x + y + 0.5 ;
}
std : : string func2s ( int x , std : : string y ) {
return y + " " + std : : to_string ( x ) ;
}
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < woof > ( " woof " ,
" var " , & woof : : var ,
" func " , sol : : overload ( & woof : : func , & woof : : func2 , & woof : : func2s )
) ;
const std : : string bark_58 = " bark 58 " ;
REQUIRE_NOTHROW ( lua . script ( R " (
r = woof : new ( )
a = r : func ( 1 )
b = r : func ( 1 , 2 )
c = r : func ( 58 , " bark " )
) " ));
REQUIRE ( ( lua [ " a " ] = = 1 ) ) ;
REQUIRE ( ( lua [ " b " ] = = 3.5 ) ) ;
REQUIRE ( ( lua [ " c " ] = = bark_58 ) ) ;
REQUIRE_THROWS ( lua . script ( " r:func(1,2,'meow') " ) ) ;
}