2018-10-16 09:53:16 +08:00
// sol3
2017-12-20 17:58:32 +08:00
// The MIT License (MIT)
2019-03-13 17:18:06 +08:00
// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
2017-12-20 17:58:32 +08:00
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2018-12-20 12:17:15 +08:00
# include "sol_test.hpp"
2017-02-15 18:42:44 +08:00
2017-11-10 06:41:46 +08:00
# include <catch.hpp>
2017-02-15 18:42:44 +08:00
# include <fstream>
# include <iostream>
# include <map>
# include <unordered_map>
# include <vector>
bool func_opt_ret_bool ( sol : : optional < int > i ) {
2017-09-17 02:18:45 +08:00
if ( i ) {
2017-02-15 18:42:44 +08:00
INFO ( i . value ( ) ) ;
}
2017-09-17 02:18:45 +08:00
else {
2017-02-15 18:42:44 +08:00
INFO ( " optional isn't set " ) ;
}
return true ;
}
2018-11-21 00:59:36 +08:00
struct base1 {
int a1 = 250 ;
} ;
struct base2 {
int a2 = 500 ;
} ;
struct simple : base1 {
} ;
struct complex : base1 , base2 {
} ;
SOL_BASE_CLASSES ( complex , base1 , base2 ) ;
SOL_BASE_CLASSES ( simple , base1 ) ;
SOL_DERIVED_CLASSES ( base1 , simple , complex ) ;
SOL_DERIVED_CLASSES ( base2 , complex ) ;
2017-02-15 18:42:44 +08:00
TEST_CASE ( " table/traversal " , " ensure that we can chain requests and tunnel down into a value if we desire " ) {
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 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x24 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x24 = = 24 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua [ " t1 " ] [ " t2 " ] [ " t3 " ] = 64 ;
2019-01-17 21:28:34 +08:00
}
REQUIRE ( begintop = = endtop ) ;
{
2017-02-15 18:42:44 +08:00
int traversex64 = lua . traverse_get < int > ( " t1 " , " t2 " , " t3 " ) ;
REQUIRE ( traversex64 = = 64 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x64 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x64 = = 64 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . traverse_set ( " t1 " , " t2 " , " t3 " , 13 ) ;
2019-01-17 21:28:34 +08:00
}
REQUIRE ( begintop = = endtop ) ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
2017-02-15 18:42:44 +08:00
int traversex13 = lua . traverse_get < int > ( " t1 " , " t2 " , " t3 " ) ;
REQUIRE ( traversex13 = = 13 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
int x13 = lua [ " t1 " ] [ " t2 " ] [ " t3 " ] ;
REQUIRE ( x13 = = 13 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
}
TEST_CASE ( " simple/set " , " Check if the set works properly. " ) {
sol : : state lua ;
int begintop = 0 , endtop = 0 ;
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " a " , 9 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " if a ~= 9 then error('wrong value') end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " d " , " hello " ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
lua . set ( " e " , std : : string ( " hello " ) , " f " , true ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " if d ~= 'hello' then error('expected \\ 'hello \\ ', got '.. tostring(d)) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " if f ~= true then error('wrong value') end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2017-02-15 18:42:44 +08:00
}
TEST_CASE ( " simple/get " , " Tests if the get function works properly. " ) {
sol : : state lua ;
int begintop = 0 , endtop = 0 ;
2017-08-22 03:25:43 +08:00
lua . safe_script ( " a = 9 " ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
auto a = lua . get < int > ( " a " ) ;
REQUIRE ( a = = 9.0 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
2017-08-22 03:25:43 +08:00
lua . safe_script ( " b = nil " ) ;
2017-02-15 18:42:44 +08:00
{
test_stack_guard g ( lua . lua_state ( ) , begintop , endtop ) ;
2017-09-22 23:04:46 +08:00
REQUIRE_NOTHROW ( lua . get < sol : : lua_nil_t > ( " b " ) ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
2017-08-22 03:25:43 +08:00
lua . safe_script ( " d = 'hello' " ) ;
lua . safe_script ( " e = true " ) ;
2017-02-15 18:42:44 +08:00
{
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 ) ;
2017-09-17 02:18:45 +08:00
}
REQUIRE ( begintop = = endtop ) ;
2017-02-15 18:42:44 +08:00
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " simple/set and get global integer " , " Tests if the get function works properly with global integers " ) {
2017-02-15 18:42:44 +08:00
sol : : state lua ;
lua [ 1 ] = 25.4 ;
2017-08-22 03:25:43 +08:00
lua . safe_script ( " b = 1 " ) ;
2017-02-15 18:42:44 +08:00
double a = lua . get < double > ( 1 ) ;
double b = lua . get < double > ( " b " ) ;
REQUIRE ( a = = 25.4 ) ;
REQUIRE ( b = = 1 ) ;
}
TEST_CASE ( " simple/get_or " , " check if table.get_or works correctly " ) {
sol : : state lua ;
auto bob_table = lua . create_table ( " bob " ) ;
bob_table . set ( " is_set " , 42 ) ;
int is_set = bob_table . get_or ( " is_set " , 3 ) ;
int 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 ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " simple/proxy get_or " , " check if proxy.get_or works correctly " ) {
2017-02-15 18:42:44 +08:00
sol : : state lua ;
auto bob_table = lua . create_table ( " bob " ) ;
bob_table . set ( " is_set " , 42 ) ;
int is_set = bob_table [ " is_set " ] . get_or ( 3 ) ;
int is_not_set = bob_table [ " is_not_set " ] . get_or ( 22 ) ;
REQUIRE ( is_set = = 42 ) ;
REQUIRE ( is_not_set = = 22 ) ;
lua [ " joe " ] = 55.6 ;
double bark = lua [ " joe " ] . get_or < double > ( 60 ) ;
REQUIRE ( bark = = 55.6 ) ;
}
TEST_CASE ( " simple/addition " , " check if addition works and can be gotten through lua.get and lua.set " ) {
sol : : state lua ;
lua . set ( " b " , 0.2 ) ;
2017-08-22 03:25:43 +08:00
lua . safe_script ( " c = 9 + b " ) ;
2017-02-15 18:42:44 +08:00
auto c = lua . get < double > ( " c " ) ;
REQUIRE ( c = = 9.2 ) ;
}
TEST_CASE ( " simple/if " , " check if if statements work through lua " ) {
sol : : state lua ;
std : : string program = " if true then f = 0.1 else f = 'test' end " ;
2017-08-22 03:25:43 +08:00
lua . safe_script ( program ) ;
2017-02-15 18:42:44 +08:00
auto f = lua . get < double > ( " f " ) ;
REQUIRE ( f = = 0.1 ) ;
REQUIRE ( ( f = = lua [ " f " ] ) ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " negative/basic errors " , " Check if error handling works correctly " ) {
2017-02-15 18:42:44 +08:00
sol : : state lua ;
2017-08-11 15:24:17 +08:00
auto result = lua . safe_script ( " nil[5] " , sol : : script_pass_on_error ) ;
REQUIRE_FALSE ( result . valid ( ) ) ;
2017-02-15 18:42:44 +08:00
}
TEST_CASE ( " libraries " , " Check if we can open libraries " ) {
sol : : state lua ;
REQUIRE_NOTHROW ( lua . open_libraries ( sol : : lib : : base , sol : : lib : : os ) ) ;
}
TEST_CASE ( " libraries2 " , " Check if we can open ALL the libraries " ) {
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 ) ) ;
}
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 ) {
INFO ( x ) ;
} ) ;
2017-09-17 02:18:45 +08:00
REQUIRE_NOTHROW ( lua . safe_script (
" x = lol() \n "
2017-02-15 18:42:44 +08:00
" rofl(x) \n "
" assert(x == nil) " ) ) ;
}
TEST_CASE ( " object/conversions " , " make sure all basic reference types can be made into objects " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
struct d { } ;
2017-08-22 03:25:43 +08:00
lua . safe_script ( " function f () print('bark') end " ) ;
2018-10-16 09:53:16 +08:00
lua [ " d " ] = d { } ;
2017-02-15 18:42:44 +08:00
lua [ " l " ] = static_cast < void * > ( nullptr ) ;
sol : : table t = lua . create_table ( ) ;
2017-04-03 04:10:00 +08:00
sol : : table t2 ( lua , sol : : create ) ;
2017-02-15 18:42:44 +08:00
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 " ] ;
2017-04-03 04:10:00 +08:00
sol : : environment env ( lua , sol : : create ) ;
2017-02-15 18:42:44 +08:00
sol : : object ot ( t ) ;
2017-04-03 04:10:00 +08:00
sol : : object ot2 ( t2 ) ;
sol : : object oteq = ot ;
2017-02-15 18:42:44 +08:00
sol : : object oth ( th ) ;
sol : : object of ( f ) ;
sol : : object opf ( pf ) ;
sol : : object od ( ud ) ;
sol : : object ol ( lud ) ;
2017-04-03 04:10:00 +08:00
sol : : object oenv ( env ) ;
2017-02-15 18:42:44 +08:00
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 ) ;
2017-09-22 19:30:41 +08:00
auto omn = sol : : make_object ( lua , sol : : lua_nil ) ;
2017-02-15 18:42:44 +08:00
REQUIRE ( ot . get_type ( ) = = sol : : type : : table ) ;
2017-09-14 20:45:44 +08:00
REQUIRE ( ot2 . get_type ( ) = = sol : : type : : table ) ;
REQUIRE ( oteq . 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 ) ;
2017-09-22 07:24:21 +08:00
REQUIRE ( omn . get_type ( ) = = sol : : type : : lua_nil ) ;
2017-09-14 20:45:44 +08:00
REQUIRE ( oenv . get_type ( ) = = sol : : type : : table ) ;
}
TEST_CASE ( " object/main_* conversions " , " make sure all basic reference types can be made into objects " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
struct d { } ;
lua . safe_script ( " function f () print('bark') end " ) ;
2018-10-16 09:53:16 +08:00
lua [ " d " ] = d { } ;
2017-09-14 20:45:44 +08:00
lua [ " l " ] = static_cast < void * > ( nullptr ) ;
sol : : main_table t = lua . create_table ( ) ;
sol : : main_table t2 ( lua , sol : : create ) ;
sol : : thread th = sol : : thread : : create ( lua ) ;
sol : : main_function f = lua [ " f " ] ;
sol : : main_protected_function pf = lua [ " f " ] ;
sol : : main_userdata ud = lua [ " d " ] ;
sol : : main_lightuserdata lud = lua [ " l " ] ;
sol : : main_environment env ( lua , sol : : create ) ;
sol : : main_object ot ( t ) ;
sol : : main_object ot2 ( t2 ) ;
sol : : main_object oteq = ot ;
sol : : main_object oth ( th ) ;
sol : : main_object of ( f ) ;
sol : : main_object opf ( pf ) ;
sol : : main_object od ( ud ) ;
sol : : main_object ol ( lud ) ;
sol : : main_object oenv ( env ) ;
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 ) ;
2017-09-22 19:30:41 +08:00
auto omn = sol : : make_object ( lua , sol : : lua_nil ) ;
2017-09-14 20:45:44 +08:00
REQUIRE ( ot . get_type ( ) = = sol : : type : : table ) ;
2017-02-15 18:42:44 +08:00
REQUIRE ( ot2 . get_type ( ) = = sol : : type : : table ) ;
2017-04-03 04:10:00 +08:00
REQUIRE ( oteq . get_type ( ) = = sol : : type : : table ) ;
2017-02-15 18:42:44 +08:00
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 ) ;
2017-09-22 07:24:21 +08:00
REQUIRE ( omn . get_type ( ) = = sol : : type : : lua_nil ) ;
2017-04-03 04:10:00 +08:00
REQUIRE ( oenv . get_type ( ) = = sol : : type : : table ) ;
2017-02-15 18:42:44 +08:00
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " feature/indexing overrides " , " make sure index functions can be overridden on types " ) {
2017-02-15 18:42:44 +08:00
struct PropertySet {
2017-09-17 02:18:45 +08:00
sol : : object get_property_lua ( const char * name , sol : : this_state s ) {
2017-02-15 18:42:44 +08:00
auto & var = props [ name ] ;
return sol : : make_object ( s , var ) ;
}
2017-09-17 02:18:45 +08:00
void set_property_lua ( const char * name , sol : : stack_object object ) {
2017-02-15 18:42:44 +08:00
props [ name ] = object . as < std : : string > ( ) ;
}
std : : unordered_map < std : : string , std : : string > props ;
} ;
struct DynamicObject {
PropertySet & get_dynamic_props ( ) {
return dynamic_props ;
}
PropertySet dynamic_props ;
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2018-10-16 09:53:16 +08:00
sol : : usertype < PropertySet > utps = lua . new_usertype < PropertySet > ( " PropertySet " ) ;
utps [ sol : : meta_function : : new_index ] = & PropertySet : : set_property_lua ;
utps [ sol : : meta_function : : index ] = & PropertySet : : get_property_lua ;
sol : : usertype < DynamicObject > utdo = lua . new_usertype < DynamicObject > ( " DynamicObject " ) ;
utdo [ " props " ] = sol : : property ( & DynamicObject : : get_dynamic_props ) ;
2017-02-15 18:42:44 +08:00
2018-11-21 00:59:36 +08:00
auto result = lua . safe_script ( R " __(
2017-02-15 18:42:44 +08:00
obj = DynamicObject : new ( )
obj . props . name = ' test name '
print ( ' name = ' . . obj . props . name )
2018-11-21 00:59:36 +08:00
) __ " , sol::script_pass_on_error);
REQUIRE ( result . valid ( ) ) ;
2017-02-15 18:42:44 +08:00
std : : string name = lua [ " obj " ] [ " props " ] [ " name " ] ;
REQUIRE ( name = = " test name " ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " features/indexing numbers " , " make sure indexing functions can be override on usertypes " ) {
2017-02-15 18:42:44 +08:00
class vector {
public :
double data [ 3 ] ;
2017-09-17 02:18:45 +08:00
vector ( )
2018-10-16 09:53:16 +08:00
: data { 0 , 0 , 0 } {
2017-09-17 02:18:45 +08:00
}
2017-02-15 18:42:44 +08:00
2017-09-17 02:18:45 +08:00
double & operator [ ] ( int i ) {
2017-02-15 18:42:44 +08:00
return data [ i ] ;
}
2017-09-17 02:18:45 +08:00
static double my_index ( vector & v , int i ) {
2017-02-15 18:42:44 +08:00
return v [ i ] ;
}
2017-09-17 02:18:45 +08:00
static void my_new_index ( vector & v , int i , double x ) {
2017-02-15 18:42:44 +08:00
v [ i ] = x ;
}
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < vector > ( " vector " , sol : : constructors < sol : : types < > > ( ) ,
sol : : meta_function : : index , & vector : : my_index ,
sol : : meta_function : : new_index , & vector : : my_new_index ) ;
2017-09-17 02:18:45 +08:00
lua . safe_script (
" v = vector.new() \n "
2017-02-15 18:42:44 +08:00
" print(v[1]) \n "
" v[2] = 3 \n "
2017-09-17 02:18:45 +08:00
" print(v[2]) \n " ) ;
2017-02-15 18:42:44 +08:00
vector & v = lua [ " v " ] ;
REQUIRE ( v [ 0 ] = = 0.0 ) ;
REQUIRE ( v [ 1 ] = = 0.0 ) ;
REQUIRE ( v [ 2 ] = = 3.0 ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " features/multiple inheritance " , " Ensure that multiple inheritance works as advertised " ) {
2017-02-15 18:42:44 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < base1 > ( " base1 " ,
2017-09-17 02:18:45 +08:00
" a1 " , & base1 : : a1 ) ;
2017-02-15 18:42:44 +08:00
lua . new_usertype < base2 > ( " base2 " ,
2017-09-17 02:18:45 +08:00
" a2 " , & base2 : : a2 ) ;
2017-02-15 18:42:44 +08:00
lua . new_usertype < simple > ( " simple " ,
" a1 " , & simple : : a1 ,
2017-09-17 02:18:45 +08:00
sol : : base_classes , sol : : bases < base1 > ( ) ) ;
2017-02-15 18:42:44 +08:00
lua . new_usertype < complex > ( " complex " ,
" a1 " , & complex : : a1 ,
" a2 " , & complex : : a2 ,
2017-09-17 02:18:45 +08:00
sol : : base_classes , sol : : bases < base1 , base2 > ( ) ) ;
lua . safe_script (
" c = complex.new() \n "
2017-02-15 18:42:44 +08:00
" s = simple.new() \n "
" b1 = base1.new() \n "
2017-09-17 02:18:45 +08:00
" b2 = base1.new() \n " ) ;
2017-02-15 18:42:44 +08:00
base1 * sb1 = lua [ " s " ] ;
REQUIRE ( sb1 ! = nullptr ) ;
REQUIRE ( sb1 - > a1 = = 250 ) ;
base1 * cb1 = lua [ " c " ] ;
base2 * cb2 = lua [ " c " ] ;
REQUIRE ( cb1 ! = nullptr ) ;
REQUIRE ( cb2 ! = nullptr ) ;
REQUIRE ( cb1 - > a1 = = 250 ) ;
REQUIRE ( cb2 - > a2 = = 500 ) ;
}
TEST_CASE ( " regressions/std::ref " , " Ensure that std::reference_wrapper<> isn't considered as a function by using unwrap_unqualified_t trait " ) {
struct base1 {
int a1 = 250 ;
} ;
sol : : state lua ;
base1 v ;
lua [ " vp " ] = & v ;
lua [ " vr " ] = std : : ref ( v ) ;
base1 * vp = lua [ " vp " ] ;
base1 & vr = lua [ " vr " ] ;
REQUIRE ( vp ! = nullptr ) ;
REQUIRE ( vp = = & v ) ;
REQUIRE ( vp - > a1 = = 250 ) ;
REQUIRE ( vr . a1 = = 250 ) ;
2017-09-17 02:18:45 +08:00
2017-02-15 18:42:44 +08:00
v . a1 = 568 ;
REQUIRE ( vp - > a1 = = 568 ) ;
REQUIRE ( vr . a1 = = 568 ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " optional/left out args " , " Make sure arguments can be left out of optional without tanking miserably " ) {
2017-02-15 18:42:44 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
// sol::optional needs an argument no matter what?
lua . set_function ( " func_opt_ret_bool " , func_opt_ret_bool ) ;
2017-09-17 02:18:45 +08:00
REQUIRE_NOTHROW ( [ & ] {
lua . safe_script ( R " (
2017-02-15 18:42:44 +08:00
func_opt_ret_bool ( 42 )
func_opt_ret_bool ( )
print ( ' ok ' )
) " );
2017-02-18 10:29:55 +08:00
} ( ) ) ;
2017-02-15 18:42:44 +08:00
}
2018-06-27 03:57:22 +08:00
TEST_CASE ( " optional/engaged versus unengaged " , " solidify semantics for an engaged and unengaged optional " ) {
2018-09-28 13:27:38 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set_function ( " f " , [ ] ( sol : : optional < sol : : object > optional_arg ) {
if ( optional_arg ) {
return true ;
}
return false ;
} ) ;
auto valid0 = lua . safe_script ( " assert(not f()) " , sol : : script_pass_on_error ) ;
REQUIRE ( valid0 . valid ( ) ) ;
auto valid1 = lua . safe_script ( " assert(not f(nil)) " , sol : : script_pass_on_error ) ;
REQUIRE ( valid1 . valid ( ) ) ;
auto valid2 = lua . safe_script ( " assert(f(1)) " , sol : : script_pass_on_error ) ;
REQUIRE ( valid2 . valid ( ) ) ;
2018-06-27 03:57:22 +08:00
auto valid3 = lua . safe_script ( " assert(f('hi')) " , sol : : script_pass_on_error ) ;
2018-09-28 13:27:38 +08:00
REQUIRE ( valid3 . valid ( ) ) ;
2018-06-27 03:57:22 +08:00
}
2017-02-15 18:42:44 +08:00
TEST_CASE ( " pusher/constness " , " Make sure more types can handle being const and junk " ) {
struct Foo {
2017-09-17 02:18:45 +08:00
Foo ( const sol : : function & f )
: _f ( f ) {
}
2017-02-15 18:42:44 +08:00
const sol : : function & _f ;
2017-09-17 02:18:45 +08:00
const sol : : function & f ( ) const {
return _f ;
}
2017-02-15 18:42:44 +08:00
} ;
sol : : state lua ;
lua . new_usertype < Foo > ( " Foo " ,
sol : : call_constructor , sol : : no_constructor ,
2017-09-17 02:18:45 +08:00
" f " , & Foo : : f ) ;
2017-02-15 18:42:44 +08:00
lua [ " func " ] = [ ] ( ) { return 20 ; } ;
sol : : function f = lua [ " func " ] ;
lua [ " foo " ] = Foo ( f ) ;
Foo & foo = lua [ " foo " ] ;
int x = foo . f ( ) ( ) ;
REQUIRE ( x = = 20 ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " compilation/const regression " , " make sure constness in tables is respected all the way down " ) {
2017-02-15 18:42:44 +08:00
struct State {
public :
State ( ) {
2018-11-21 00:59:36 +08:00
this - > state_ . globals ( ) [ " state " ] = this ;
2017-02-15 18:42:44 +08:00
}
sol : : state state_ ;
} ;
State state ;
2018-11-21 00:59:36 +08:00
State * s = state . state_ . globals ( ) [ " state " ] ;
2017-02-15 18:42:44 +08:00
REQUIRE ( s = = & state ) ;
}
TEST_CASE ( " numbers/integers " , " make sure integers are detectable on most platforms " ) {
sol : : state lua ;
2017-09-17 02:18:45 +08:00
lua [ " a " ] = 50 ; // int
2017-02-15 18:42:44 +08:00
lua [ " b " ] = 50.5 ; // double
sol : : object a = lua [ " a " ] ;
sol : : object b = lua [ " b " ] ;
bool a_is_int = a . is < int > ( ) ;
bool a_is_double = a . is < double > ( ) ;
bool b_is_int = b . is < int > ( ) ;
bool b_is_double = b . is < double > ( ) ;
REQUIRE ( a_is_int ) ;
REQUIRE ( a_is_double ) ;
// TODO: will this fail on certain lower Lua versions?
REQUIRE_FALSE ( b_is_int ) ;
REQUIRE ( b_is_double ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " object/is " , " test whether or not the is abstraction works properly for a user-defined type " ) {
2017-03-22 19:53:57 +08:00
struct thing { } ;
2017-09-17 02:18:45 +08:00
SECTION ( " stack_object " ) {
2017-03-22 19:53:57 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2017-09-17 02:18:45 +08:00
lua . set_function ( " is_thing " , [ ] ( sol : : stack_object obj ) { return obj . is < thing > ( ) ; } ) ;
2018-10-16 09:53:16 +08:00
lua [ " a " ] = thing { } ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " assert(is_thing(a)) " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2017-03-22 19:53:57 +08:00
}
2017-09-17 02:18:45 +08:00
SECTION ( " object " ) {
2017-03-22 19:53:57 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set_function ( " is_thing " , [ ] ( sol : : object obj ) { return obj . is < thing > ( ) ; } ) ;
2018-10-16 09:53:16 +08:00
lua [ " a " ] = thing { } ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " assert(is_thing(a)) " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2017-03-22 19:53:57 +08:00
}
}
2019-01-17 21:28:34 +08:00
TEST_CASE ( " object/base_of_things " , " make sure that object is the base of things and can be sliced / returned safely " ) {
SECTION ( " reference " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : coroutine ) ;
lua [ " ud " ] = base1 { } ;
lua [ " f1 " ] = [ ] ( sol : : object o ) - > sol : : object { return o ; } ;
lua [ " f2 " ] = [ ] ( sol : : table o ) - > sol : : object { return o ; } ;
lua [ " f3 " ] = [ ] ( sol : : thread o ) - > sol : : object { return o ; } ;
lua [ " f4 " ] = [ ] ( sol : : unsafe_function o ) - > sol : : object { return o ; } ;
lua [ " f5 " ] = [ ] ( sol : : protected_function o ) - > sol : : object { return o ; } ;
lua [ " f6 " ] = [ ] ( sol : : userdata o ) - > sol : : object { return o ; } ;
auto result1 = lua . safe_script ( " f1(2) " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
auto result2 = lua . safe_script ( " f2({}) " , sol : : script_pass_on_error ) ;
REQUIRE ( result2 . valid ( ) ) ;
auto result3 = lua . safe_script ( " f3(coroutine.create( function () end ) ) " , sol : : script_pass_on_error ) ;
REQUIRE ( result3 . valid ( ) ) ;
auto result4 = lua . safe_script ( " f4( function () end ) " , sol : : script_pass_on_error ) ;
REQUIRE ( result4 . valid ( ) ) ;
auto result5 = lua . safe_script ( " f5( function () end ) " , sol : : script_pass_on_error ) ;
REQUIRE ( result5 . valid ( ) ) ;
auto result6 = lua . safe_script ( " f6(ud) " , sol : : script_pass_on_error ) ;
REQUIRE ( result6 . valid ( ) ) ;
}
SECTION ( " stack_reference " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : coroutine ) ;
lua [ " ud " ] = base1 { } ;
lua [ " f1 " ] = [ ] ( sol : : stack_object o ) - > sol : : stack_object { return o ; } ;
2019-03-23 04:28:17 +08:00
lua [ " f2 " ] = [ ] ( sol : : stack_table o ) - > sol : : stack_object { return std : : move ( o ) ; } ;
lua [ " f3 " ] = [ ] ( sol : : stack_thread o ) - > sol : : stack_object { return std : : move ( o ) ; } ;
lua [ " f4 " ] = [ ] ( sol : : stack_unsafe_function o ) - > sol : : stack_object { return std : : move ( o ) ; } ;
lua [ " f5 " ] = [ ] ( sol : : stack_protected_function o ) - > sol : : stack_object { return std : : move ( o ) ; } ;
lua [ " f6 " ] = [ ] ( sol : : stack_userdata o ) - > sol : : stack_object { return std : : move ( o ) ; } ;
2019-01-17 21:28:34 +08:00
auto result1 = lua . safe_script ( " f1(2) " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
auto result2 = lua . safe_script ( " f2({}) " , sol : : script_pass_on_error ) ;
REQUIRE ( result2 . valid ( ) ) ;
auto result3 = lua . safe_script ( " f3(coroutine.create( function () end ) ) " , sol : : script_pass_on_error ) ;
REQUIRE ( result3 . valid ( ) ) ;
auto result4 = lua . safe_script ( " f4( function () end ) " , sol : : script_pass_on_error ) ;
REQUIRE ( result4 . valid ( ) ) ;
auto result5 = lua . safe_script ( " f5( function () end ) " , sol : : script_pass_on_error ) ;
REQUIRE ( result5 . valid ( ) ) ;
auto result6 = lua . safe_script ( " f6(ud) " , sol : : script_pass_on_error ) ;
REQUIRE ( result6 . valid ( ) ) ;
}
}