2013-12-11 21:32:27 +08:00
# define CATCH_CONFIG_MAIN
2015-06-18 06:33:58 +08:00
# define SOL_CHECK_ARGUMENTS
2016-03-12 00:34:44 +08:00
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>
2016-04-17 14:52:41 +08:00
# include <iostream>
2016-03-31 04:52:51 +08:00
# include "test_stack_guard.hpp"
2014-06-01 14:41:16 +08:00
2016-02-14 09:14:31 +08:00
TEST_CASE ( " table/traversal " , " ensure that we can chain requests and tunnel down into a value if we desire " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
int begintop = 0 , endtop = 0 ;
sol : : function scriptload = lua . load ( " t1 = {t2 = {t3 = 24}}; " ) ;
scriptload ( ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int traversex24 = lua . traverse_get < int > ( " t1 " , " t2 " , " t3 " ) ;
REQUIRE ( traversex24 = = 24 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x24 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x24 = = 24 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua [ " t1 " ] [ " t2 " ] [ " t3 " ] = 64 ;
int traversex64 = lua . traverse_get < int > ( " t1 " , " t2 " , " t3 " ) ;
REQUIRE ( traversex64 = = 64 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x64 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x64 = = 64 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . traverse_set ( " t1 " , " t2 " , " t3 " , 13 ) ;
int traversex13 = lua . traverse_get < int > ( " t1 " , " t2 " , " t3 " ) ;
REQUIRE ( traversex13 = = 13 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x13 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x13 = = 13 ) ;
} REQUIRE ( begintop = = endtop ) ;
2016-02-14 09:14:31 +08:00
}
2016-02-01 16:27:06 +08:00
TEST_CASE ( " simple/set " , " Check if the set works properly. " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
int begintop = 0 , endtop = 0 ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " a " , 9 ) ;
} REQUIRE ( begintop = = endtop ) ;
REQUIRE_NOTHROW ( lua . script ( " if a ~= 9 then error('wrong value') end " ) ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " d " , " hello " ) ;
} REQUIRE ( begintop = = endtop ) ;
REQUIRE_NOTHROW ( lua . script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " ) ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " e " , std : : string ( " hello " ) , " f " , true ) ;
} REQUIRE ( begintop = = endtop ) ;
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 " ) ) ;
2013-12-12 00:18:13 +08:00
}
TEST_CASE ( " simple/get " , " Tests if the get function works properly. " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
int begintop = 0 , endtop = 0 ;
lua . script ( " a = 9 " ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
auto a = lua . get < int > ( " a " ) ;
REQUIRE ( a = = 9.0 ) ;
} REQUIRE ( begintop = = endtop ) ;
lua . script ( " b = nil " ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
REQUIRE_NOTHROW ( lua . get < sol : : nil_t > ( " b " ) ) ;
} REQUIRE ( begintop = = endtop ) ;
lua . script ( " d = 'hello' " ) ;
lua . script ( " e = true " ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
std : : string d ;
bool e ;
std : : tie ( d , e ) = lua . get < std : : string , bool > ( " d " , " e " ) ;
REQUIRE ( d = = " hello " ) ;
REQUIRE ( e = = true ) ;
} REQUIRE ( begintop = = endtop ) ;
2013-12-12 00:18:13 +08:00
}
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 " ) {
2016-06-07 03:46:53 +08:00
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 ) ;
2016-02-02 00:56:44 +08:00
}
2016-03-30 13:40:40 +08:00
TEST_CASE ( " simple/get_or " , " check if table.get_or works correctly " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
2016-03-30 13:40:40 +08:00
2016-06-07 03:46:53 +08:00
auto bob_table = lua . create_table ( " bob " ) ;
bob_table . set ( " is_set " , 42 ) ;
2016-03-30 13:40:40 +08:00
2016-06-07 03:46:53 +08:00
int is_set = bob_table . get_or ( " is_set " , 3 ) ;
int is_not_set = bob_table . get_or ( " is_not_set " , 22 ) ;
2016-03-30 13:40:40 +08:00
2016-06-07 03:46:53 +08:00
REQUIRE ( is_set = = 42 ) ;
REQUIRE ( is_not_set = = 22 ) ;
2016-03-30 13:40:40 +08:00
2016-06-07 03:46:53 +08:00
lua [ " joe " ] = 55.6 ;
double bark = lua . get_or < double > ( " joe " , 60 ) ;
REQUIRE ( bark = = 55.6 ) ;
2016-03-30 13:40:40 +08:00
}
2016-04-09 12:55:12 +08:00
TEST_CASE ( " simple/proxy_get_or " , " check if proxy.get_or works correctly " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
2016-04-09 12:55:12 +08:00
2016-06-07 03:46:53 +08:00
auto bob_table = lua . create_table ( " bob " ) ;
bob_table . set ( " is_set " , 42 ) ;
2016-04-09 12:55:12 +08:00
2016-06-07 03:46:53 +08:00
int is_set = bob_table [ " is_set " ] . get_or ( 3 ) ;
int is_not_set = bob_table [ " is_not_set " ] . get_or ( 22 ) ;
2016-04-09 12:55:12 +08:00
2016-06-07 03:46:53 +08:00
REQUIRE ( is_set = = 42 ) ;
REQUIRE ( is_not_set = = 22 ) ;
2016-04-09 12:55:12 +08:00
2016-06-07 03:46:53 +08:00
lua [ " joe " ] = 55.6 ;
double bark = lua [ " joe " ] . get_or < double > ( 60 ) ;
REQUIRE ( bark = = 55.6 ) ;
2016-04-09 12:55:12 +08:00
}
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 " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
2013-12-12 00:18:13 +08:00
2016-06-07 03:46:53 +08:00
lua . set ( " b " , 0.2 ) ;
lua . script ( " c = 9 + b " ) ;
auto c = lua . get < double > ( " c " ) ;
2013-12-12 00:18:13 +08:00
2016-06-07 03:46:53 +08:00
REQUIRE ( c = = 9.2 ) ;
2013-12-12 00:18:13 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " simple/if " , " check if if statements work through lua " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
2013-12-12 00:18:13 +08:00
2016-06-07 03:46:53 +08:00
std : : string program = " if true then f = 0.1 else f = 'test' end " ;
lua . script ( program ) ;
auto f = lua . get < double > ( " f " ) ;
2013-12-12 00:18:13 +08:00
2016-06-07 03:46:53 +08:00
REQUIRE ( f = = 0.1 ) ;
REQUIRE ( ( f = = lua [ " f " ] ) ) ;
2013-12-12 00:18:13 +08:00
}
2013-12-22 08:30:30 +08:00
TEST_CASE ( " negative/basic_errors " , " Check if error handling works correctly " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
2013-12-12 00:18:13 +08:00
2016-06-07 03:46:53 +08:00
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 " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
REQUIRE_NOTHROW ( lua . open_libraries ( sol : : lib : : base , sol : : lib : : os ) ) ;
2013-12-12 07:14:12 +08:00
}
2016-04-18 09:00:24 +08:00
TEST_CASE ( " libraries2 " , " Check if we can open ALL the libraries " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
REQUIRE_NOTHROW ( lua . open_libraries ( sol : : lib : : base ,
sol : : lib : : bit32 ,
sol : : lib : : coroutine ,
sol : : lib : : debug ,
sol : : lib : : ffi ,
sol : : lib : : jit ,
sol : : lib : : math ,
sol : : lib : : os ,
sol : : lib : : package ,
sol : : lib : : string ,
sol : : lib : : table ) ) ;
2016-04-18 09:00:24 +08:00
}
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 " ) {
2016-06-07 03:46:53 +08:00
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-05-27 14:23:37 +08:00
}
2015-10-23 14:54:26 +08:00
2016-04-17 14:18:34 +08:00
TEST_CASE ( " utilities/this_state " , " Ensure this_state argument can be gotten anywhere in the function. " ) {
2016-06-07 03:46:53 +08:00
struct bark {
int with_state ( sol : : this_state l , int a , int b ) {
lua_State * L = l ;
int c = lua_gettop ( L ) ;
return a + b + ( c - c ) ;
}
static int with_state_2 ( int a , sol : : this_state l , int b ) {
std : : cout < < " inside with_state_2 " < < std : : endl ;
lua_State * L = l ;
std : : cout < < " L is " < < ( void * ) L < < std : : endl ;
int c = lua_gettop ( L ) ;
return a * b + ( c - c ) ;
}
} ;
sol : : state lua ;
std : : cout < < " created lua state " < < std : : endl ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < bark > ( " bark " ,
" with_state " , & bark : : with_state
) ;
std : : cout < < " setting b and with_state_2 " < < std : : endl ;
bark b ;
lua . set ( " b " , & b ) ;
lua . set ( " with_state_2 " , bark : : with_state_2 ) ;
std : : cout < < " finished setting " < < std : : endl ;
std : : cout < < " getting fx " < < std : : endl ;
sol : : function fx = lua [ " with_state_2 " ] ;
std : : cout < < " calling fx " < < std : : endl ;
int a = fx ( 25 , 25 ) ;
std : : cout < < " finished setting fx " < < std : : endl ;
std : : cout < < " calling a script " < < std : : endl ;
lua . script ( " a = with_state_2(25, 25) " ) ;
std : : cout < < " calling c script " < < std : : endl ;
lua . script ( " c = b:with_state(25, 25) " ) ;
std : : cout < < " getting a " < < std : : endl ;
int la = lua [ " a " ] ;
std : : cout < < " getting b " < < std : : endl ;
int lc = lua [ " c " ] ;
REQUIRE ( lc = = 50 ) ;
REQUIRE ( a = = 625 ) ;
REQUIRE ( la = = 625 ) ;
2016-04-17 14:18:34 +08:00
}
2016-05-04 02:19:30 +08:00
2016-05-13 14:48:22 +08:00
TEST_CASE ( " object/conversions " , " make sure all basic reference types can be made into objects " ) {
2016-06-07 03:46:53 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
struct d { } ;
lua . script ( " function f () print('bark') end " ) ;
lua [ " d " ] = d { } ;
lua [ " l " ] = static_cast < void * > ( nullptr ) ;
sol : : table t = lua . create_table ( ) ;
sol : : thread th = sol : : thread : : create ( lua ) ;
sol : : function f = lua [ " f " ] ;
sol : : protected_function pf = lua [ " f " ] ;
sol : : userdata ud = lua [ " d " ] ;
sol : : lightuserdata lud = lua [ " l " ] ;
sol : : object ot ( t ) ;
sol : : object ot2 = ot ;
sol : : object oth ( th ) ;
sol : : object of ( f ) ;
sol : : object opf ( pf ) ;
sol : : object od ( ud ) ;
sol : : object ol ( lud ) ;
auto oni = sol : : make_object ( lua , 50 ) ;
auto ond = sol : : make_object ( lua , 50.0 ) ;
std : : string somestring = " look at this text isn't it nice " ;
auto osl = sol : : make_object ( lua , " Bark bark bark " ) ;
auto os = sol : : make_object ( lua , somestring ) ;
auto omn = sol : : make_object ( lua , sol : : nil ) ;
REQUIRE ( ot . get_type ( ) = = sol : : type : : table ) ;
REQUIRE ( ot2 . get_type ( ) = = sol : : type : : table ) ;
REQUIRE ( oth . get_type ( ) = = sol : : type : : thread ) ;
REQUIRE ( of . get_type ( ) = = sol : : type : : function ) ;
REQUIRE ( opf . get_type ( ) = = sol : : type : : function ) ;
REQUIRE ( od . get_type ( ) = = sol : : type : : userdata ) ;
REQUIRE ( ol . get_type ( ) = = sol : : type : : lightuserdata ) ;
REQUIRE ( oni . get_type ( ) = = sol : : type : : number ) ;
REQUIRE ( ond . get_type ( ) = = sol : : type : : number ) ;
REQUIRE ( osl . get_type ( ) = = sol : : type : : string ) ;
REQUIRE ( os . get_type ( ) = = sol : : type : : string ) ;
REQUIRE ( omn . get_type ( ) = = sol : : type : : nil ) ;
2016-05-13 14:48:22 +08:00
}
2016-05-19 09:29:17 +08:00
2016-05-20 16:20:22 +08:00
TEST_CASE ( " state/require_script " , " opening strings as 'requires' clauses " ) {
2016-06-07 03:46:53 +08:00
std : : string code = " return { modfunc = function () return 221 end } " ;
sol : : state lua ;
sol : : table thingy1 = lua . require_script ( " thingy " , code ) ;
sol : : table thingy2 = lua . require_script ( " thingy " , code ) ;
int val1 = thingy1 [ " modfunc " ] ( ) ;
int val2 = thingy2 [ " modfunc " ] ( ) ;
REQUIRE ( val1 = = 221 ) ;
REQUIRE ( val2 = = 221 ) ;
// must have loaded the same table
REQUIRE ( thingy1 = = thingy2 ) ;
2016-05-20 16:20:22 +08:00
}
TEST_CASE ( " state/require " , " opening using a file " ) {
2016-06-07 03:46:53 +08:00
struct open {
static int open_func ( lua_State * L ) {
sol : : state_view lua = L ;
return sol : : stack : : push ( L , lua . create_table_with ( " modfunc " , sol : : function_args ( [ ] ( ) { return 221 ; } ) ) ) ;
}
} ;
sol : : state lua ;
sol : : table thingy1 = lua . require ( " thingy " , open : : open_func ) ;
sol : : table thingy2 = lua . require ( " thingy " , open : : open_func ) ;
int val1 = thingy1 [ " modfunc " ] ( ) ;
int val2 = thingy2 [ " modfunc " ] ( ) ;
REQUIRE ( val1 = = 221 ) ;
REQUIRE ( val2 = = 221 ) ;
// THIS IS ONLY REQUIRED IN LUA 5.3, FOR SOME REASON
// must have loaded the same table
// REQUIRE(thingy1 == thingy2);
2016-05-20 16:20:22 +08:00
}
TEST_CASE ( " state/multi-require " , " make sure that requires transfers across hand-rolled script implementation and standard requiref " ) {
2016-06-07 03:46:53 +08:00
struct open {
static int open_func ( lua_State * L ) {
sol : : state_view lua = L ;
return sol : : stack : : push ( L , lua . create_table_with ( " modfunc " , sol : : function_args ( [ ] ( ) { return 221 ; } ) ) ) ;
}
} ;
std : : string code = " return { modfunc = function () return 221 end } " ;
sol : : state lua ;
sol : : table thingy1 = lua . require ( " thingy " , open : : open_func ) ;
sol : : table thingy2 = lua . require ( " thingy " , open : : open_func ) ;
sol : : table thingy3 = lua . require_script ( " thingy " , code ) ;
int val1 = thingy1 [ " modfunc " ] ( ) ;
int val2 = thingy2 [ " modfunc " ] ( ) ;
int val3 = thingy3 [ " modfunc " ] ( ) ;
REQUIRE ( val1 = = 221 ) ;
REQUIRE ( val2 = = 221 ) ;
REQUIRE ( val3 = = 221 ) ;
// must have loaded the same table
// Lua is not obliged to give a shit. Thanks, Lua
//REQUIRE(thingy1 == thingy2);
// But we care, thankfully
//REQUIRE(thingy1 == thingy3);
REQUIRE ( thingy2 = = thingy3 ) ;
2016-05-19 09:29:17 +08:00
}