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-03-31 04:52:51 +08:00
# include "test_stack_guard.hpp"
2014-06-01 14:41:16 +08:00
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 ( ) {
}
} ;
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
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-22 08:26:58 +08:00
struct factory_test {
private :
factory_test ( ) { a = true_a ; }
~ factory_test ( ) { a = 0 ; }
public :
static int num_saved ;
static int num_killed ;
struct deleter {
void operator ( ) ( factory_test * f ) {
f - > ~ factory_test ( ) ;
}
} ;
2016-02-25 02:59:17 +08:00
static const int true_a ;
2016-02-22 08:26:58 +08:00
int a ;
static std : : unique_ptr < factory_test , deleter > make ( ) {
return std : : unique_ptr < factory_test , deleter > ( new factory_test ( ) , deleter ( ) ) ;
}
static void save ( factory_test & f ) {
new ( & f ) factory_test ( ) ;
+ + num_saved ;
}
static void kill ( factory_test & f ) {
f . ~ factory_test ( ) ;
+ + num_killed ;
}
} ;
int factory_test : : num_saved = 0 ;
int factory_test : : num_killed = 0 ;
2016-02-25 02:59:17 +08:00
const int factory_test : : true_a = 156 ;
2016-02-22 08:26:58 +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-02-22 08:26:58 +08:00
sol : : state lua ;
int begintop = 0 , endtop = 0 ;
lua . script ( " t1 = {t2 = {t3 = 24}}; " ) ;
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int traversex24 = lua . traverse_get < int > ( " t1 " , " t2 " , " t3 " ) ;
REQUIRE ( traversex24 = = 24 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x24 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x24 = = 24 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
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 ) ;
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x64 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x64 = = 64 ) ;
} REQUIRE ( begintop = = endtop ) ;
{
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 ) ;
{
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. " ) {
2013-12-12 00:18:13 +08:00
sol : : state lua ;
2016-02-14 09:14:31 +08:00
int begintop = 0 , endtop = 0 ;
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " a " , 9 ) ;
} REQUIRE ( begintop = = endtop ) ;
2013-12-12 00:18:13 +08:00
REQUIRE_NOTHROW ( lua . script ( " if a ~= 9 then error('wrong value') end " ) ) ;
2016-02-14 09:14:31 +08:00
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " d " , " hello " ) ;
} REQUIRE ( begintop = = endtop ) ;
2013-12-12 00:18:13 +08:00
REQUIRE_NOTHROW ( lua . script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " ) ) ;
2016-02-14 09:14:31 +08:00
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " e " , std : : string ( " hello " ) , " f " , true ) ;
} REQUIRE ( begintop = = endtop ) ;
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 ;
2016-02-14 09:14:31 +08:00
int begintop = 0 , endtop = 0 ;
2013-12-12 00:18:13 +08:00
lua . script ( " a = 9 " ) ;
2016-02-14 09:14:31 +08:00
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
auto a = lua . get < int > ( " a " ) ;
REQUIRE ( a = = 9.0 ) ;
} REQUIRE ( begintop = = endtop ) ;
2013-12-12 00:18:13 +08:00
lua . script ( " b = nil " ) ;
2016-02-14 09:14:31 +08:00
{
stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
REQUIRE_NOTHROW ( lua . get < sol : : nil_t > ( " b " ) ) ;
} REQUIRE ( begintop = = endtop ) ;
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-14 09:14:31 +08:00
{
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 " ) {
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-03-30 13:40:40 +08:00
TEST_CASE ( " simple/get_or " , " check if table.get_or works correctly " ) {
sol : : state lua ;
auto bob_table = lua . create_table ( " bob " ) ;
int is_set = 0 ;
int is_not_set = 0 ;
bob_table . set ( " is_set " , 42 ) ;
is_set = bob_table . get_or ( " is_set " , 3 ) ;
is_not_set = bob_table . get_or ( " is_not_set " , 22 ) ;
REQUIRE ( is_set = = 42 ) ;
REQUIRE ( is_not_set = = 22 ) ;
lua [ " joe " ] = 55.6 ;
double bark = lua . get_or < double > ( " joe " , 60 ) ;
REQUIRE ( bark = = 55.6 ) ;
}
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 ( " 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 ) ) ;
}
2016-03-31 04:52:51 +08:00
TEST_CASE ( " usertype/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 " ) ;
2016-03-12 00:34:44 +08:00
REQUIRE ( ( a . is < sol : : userdata_value > ( ) ) ) ;
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-03-31 04:52:51 +08:00
TEST_CASE ( " usertype/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
}
2016-03-31 04:52:51 +08:00
TEST_CASE ( " usertype/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 " ) ;
2016-03-12 00:34:44 +08:00
REQUIRE ( ( a . is < sol : : userdata_value > ( ) ) ) ;
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
2016-03-31 04:52:51 +08:00
TEST_CASE ( " usertype/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
2016-03-31 04:52:51 +08:00
TEST_CASE ( " usertype/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
2016-03-31 04:52:51 +08:00
TEST_CASE ( " usertype/issue-number-twenty-five " , " Using pointers and references from C++ classes in Lua " ) {
2014-06-09 21:18:29 +08:00
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 "
2016-02-19 11:17:52 +08:00
) ) ;
REQUIRE_NOTHROW ( lua . script ( " v.x = 2 \n "
2014-07-28 03:56:24 +08:00
" v2.y = 2 \n "
" print(v.x, v.y, v.z) \n "
" print(v2.x, v2.y, v2.z) \n "
2016-02-19 11:17:52 +08:00
) ) ;
REQUIRE_NOTHROW ( lua . script ( " assert(v.x == 2) \n "
2014-07-28 03:56:24 +08:00
" assert(v2.x == 0) \n "
" assert(v2.y == 2) \n "
2016-02-19 11:17:52 +08:00
) ) ;
REQUIRE_NOTHROW ( lua . script ( " v.x = 3 \n "
2014-07-28 03:56:24 +08:00
" local x = v.x \n "
" assert(x == 3) \n "
) ) ;
}
2014-08-09 19:54:58 +08:00
2016-02-27 15:43:53 +08:00
TEST_CASE ( " usertype/nonmember-functions " , " 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
2016-03-13 20:30:14 +08:00
TEST_CASE ( " usertype/unique-shared-ptr " , " manage the conversion and use of unique and shared pointers ('unique usertypes') " ) {
const int64_t unique_value = 0x7125679355635963 ;
auto uniqueint = std : : make_unique < int64_t > ( unique_value ) ;
auto sharedint = std : : make_shared < int64_t > ( unique_value ) ;
long preusecount = sharedint . use_count ( ) ;
{ sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set ( " uniqueint " , std : : move ( uniqueint ) ) ;
lua . set ( " sharedint " , sharedint ) ;
std : : unique_ptr < int64_t > & uniqueintref = lua [ " uniqueint " ] ;
std : : shared_ptr < int64_t > & sharedintref = lua [ " sharedint " ] ;
int siusecount = sharedintref . use_count ( ) ;
REQUIRE ( uniqueintref ! = nullptr ) ;
REQUIRE ( sharedintref ! = nullptr ) ;
REQUIRE ( unique_value = = * uniqueintref . get ( ) ) ;
REQUIRE ( unique_value = = * sharedintref . get ( ) ) ;
REQUIRE ( siusecount = = sharedint . use_count ( ) ) ;
std : : shared_ptr < int64_t > moreref = sharedint ;
REQUIRE ( unique_value = = * moreref . get ( ) ) ;
REQUIRE ( moreref . use_count ( ) = = sharedint . use_count ( ) ) ;
REQUIRE ( moreref . use_count ( ) = = sharedintref . use_count ( ) ) ;
}
REQUIRE ( preusecount = = sharedint . use_count ( ) ) ;
}
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
2016-03-15 18:36:25 +08:00
TEST_CASE ( " usertype/get-set-references " , " properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type... " ) {
2014-09-18 12:23:46 +08:00
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 ( " 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 ) ;
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 " ;
2016-02-25 16:51:29 +08:00
REQUIRE_NOTHROW ( lua . script (
" a = func(1) \n "
" b = func('bark') \n "
" c = func(1,2) \n "
" func(1,2,3) \n "
) ) ;
2016-02-11 00:36:00 +08:00
REQUIRE ( ( lua [ " a " ] = = 1 ) ) ;
REQUIRE ( ( lua [ " b " ] = = string_bark ) ) ;
REQUIRE ( ( lua [ " c " ] = = 2 ) ) ;
REQUIRE_THROWS ( lua . script ( " func(1,2,'meow') " ) ) ;
}
2016-02-27 15:43:53 +08:00
TEST_CASE ( " usertype/private-constructible " , " Check to make sure special snowflake types from Enterprise thingamahjongs work properly. " ) {
2016-02-22 08:26:58 +08:00
int numsaved = factory_test : : num_saved ;
int numkilled = factory_test : : num_killed ;
{
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < factory_test > ( " factory_test " ,
2016-03-12 00:34:44 +08:00
" new " , sol : : initializers ( factory_test : : save ) ,
2016-02-22 08:26:58 +08:00
" __gc " , sol : : destructor ( factory_test : : kill ) ,
" a " , & factory_test : : a
) ;
std : : unique_ptr < factory_test , factory_test : : deleter > f = factory_test : : make ( ) ;
lua . set ( " true_a " , factory_test : : true_a , " f " , f . get ( ) ) ;
2016-02-25 16:51:29 +08:00
REQUIRE_NOTHROW ( lua . script ( " assert(f.a == true_a) " ) ) ;
REQUIRE_NOTHROW ( lua . script (
" local fresh_f = factory_test:new() \n "
" assert(fresh_f.a == true_a) \n " ) ) ;
2016-02-22 08:26:58 +08:00
}
int expectednumsaved = numsaved + 1 ;
int expectednumkilled = numkilled + 1 ;
REQUIRE ( expectednumsaved = = factory_test : : num_saved ) ;
REQUIRE ( expectednumkilled = = factory_test : : num_killed ) ;
}
2016-02-11 00:36:00 +08:00
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 " ;
2016-02-25 16:51:29 +08:00
REQUIRE_NOTHROW ( lua . script (
" r = woof:new() \n "
" a = r:func(1) \n "
" b = r:func(1, 2) \n "
" c = r:func(58, 'bark') \n "
) ) ;
2016-02-11 00:36:00 +08:00
REQUIRE ( ( lua [ " a " ] = = 1 ) ) ;
REQUIRE ( ( lua [ " b " ] = = 3.5 ) ) ;
REQUIRE ( ( lua [ " c " ] = = bark_58 ) ) ;
REQUIRE_THROWS ( lua . script ( " r:func(1,2,'meow') " ) ) ;
}