# include <fmt/core.h>
# include <deque>
# include <string>
# include <fuc2/testing.hpp>
# define SOL_ALL_SAFETIES_ON 1
# include <sol/sol.hpp>
using namespace fuc2 ;
namespace sol2_tests {
void test_basic_lua_run ( ) {
sol : : state lua ;
int x = 0 ;
lua . set_function ( " beep " , [ & x ] { + + x ; } ) ;
lua . script ( " beep() " ) ;
EQUAL ( x , 1 , " Lua failed to set x " ) ;
}
struct vars {
std : : string boop = " " ;
} ;
void test_big_ass_vector ( ) {
std : : vector < vars > variables ;
for ( int i = 0 ; i < 100 ; i + + ) {
variables . emplace_back ( " hi " ) ;
}
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < vars > ( " vars " , " boop " , & vars : : boop ) ;
lua . script ( R " (
function handler ( v )
v . boop = v . boop . . " hi "
end
) " );
sol : : function handler = lua [ " handler " ] ;
for ( auto & v : variables ) {
std : : string boop_before = v . boop ;
handler ( v ) ;
CHECK ( boop_before ! = v . boop ) ;
}
}
void test_usertype_vars ( ) {
sol : : state lua ;
lua . new_usertype < vars > ( " vars " , " boop " , & vars : : boop ) ;
lua . script ( " beep = vars.new() \n "
" beep.boop = \" hi \" " ) ;
EQUAL ( lua . get < vars > ( " beep " ) . boop , " hi " ) ;
}
void test_base_libraries ( ) {
using L = sol : : lib ;
sol : : state lua ;
lua . open_libraries (
L : : base ,
L : : package ,
L : : coroutine ,
L : : string ,
L : : os ,
L : : math ,
L : : table ,
L : : debug ,
L : : bit32 ,
L : : io ,
L : : ffi ,
L : : jit ) ;
lua . script ( " print('bark bark bark!') " ) ;
fmt : : println ( " " ) ;
}
void test_sol_lua_error ( ) {
BLOWS_UP ( [ ] ( ) {
sol : : state lua ;
auto result1 = lua . safe_script ( " bad.code " ) ;
} ) ;
}
void test_variables_from_file ( ) {
sol : : state lua ;
lua . script_file ( " tests/variables.lua " ) ;
CHECK ( lua [ " config " ] [ " fullscreen " ] = = false ) ;
sol : : table config = lua [ " config " ] ;
CHECK ( config [ " fullscreen " ] = = false ) ;
}
void test_passing_args_to_scripts ( ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
const auto & my_script = R " (
local a , b , c = . . .
print ( a , b , c )
) " ;
sol : : load_result fx = lua . load ( my_script ) ;
if ( ! fx . valid ( ) ) {
sol : : error err = fx ;
throw err ;
}
fx ( " your " , " arguments " , " here " ) ;
}
void test_transfer_func ( ) {
sol : : state lua ;
sol : : state lua2 ;
lua2 . open_libraries ( sol : : lib : : base ) ;
sol : : load_result lr = lua . load ( " a = function(v) print(v) return v end " ) ;
CHECK ( lr . valid ( ) ) ;
sol : : protected_function target = lr . get < sol : : protected_function > ( ) ;
sol : : bytecode target_bc = target . dump ( ) ;
auto result2 = lua2 . safe_script ( target_bc . as_string_view ( ) , sol : : script_pass_on_error ) ;
CHECK ( result2 . valid ( ) ) ;
sol : : protected_function pf = lua2 [ " a " ] ;
int v = pf ( 25557 ) ;
CHECK ( v = = 25557 ) ;
}
void test_get_variables ( ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . set ( " number " , 24 ) ;
CHECK ( lua [ " number " ] = = 24 ) ;
lua [ " number " ] = 24.5 ;
CHECK ( lua [ " number " ] = = 24.5 ) ;
// how to compare a string?
lua [ " important_string " ] = " test " ;
std : : string a_string = " test " ;
CHECK ( lua [ " important_string " ] = = a_string ) ;
lua [ " a_function " ] = [ ] ( ) { return 100 ; } ;
auto result = lua [ " a_function " ] ( ) ;
CHECK ( result . valid ( ) ) ;
int as_int = result ;
CHECK ( as_int = = 100 ) ;
lua [ " some_table " ] = lua . create_table_with ( " value " , 24 ) ;
CHECK ( lua [ " some_table " ] [ " value " ] = = 24 ) ;
}
void test_this_has_a_bug_in_sol2 ( ) {
sol : : state lua ;
lua . script ( R " (
function handler ( message )
return " Handled this message: " . . message
end
function f ( a )
if a < 0 then
error ( " negative number detected " )
end
return a + 5
end
) " );
sol : : protected_function f = lua [ " f " ] ;
// this fails, error_handler is private
// f.error_handler = lua["handler"];
sol : : protected_function_result result = f ( - 500 ) ;
if ( result . valid ( ) ) {
// Call succeeded
int x = result ;
}
else {
// Call failed
sol : : error err = result ;
std : : string what = err . what ( ) ;
// 'what' Should read
// "Handled this message: negative number detected"
}
}
void test_multiple_returns ( ) {
sol : : state lua ;
lua . script ( " function f(a,b,c) return a, b, c end " ) ;
std : : tuple < int , int , int > result ;
result = lua [ " f " ] ( 1 , 2 , 3 ) ;
CHECK ( std : : get < 0 > ( result ) = = 1 ) ;
CHECK ( std : : get < 1 > ( result ) = = 2 ) ;
CHECK ( std : : get < 2 > ( result ) = = 3 ) ;
int a ;
int b ;
std : : string c ;
sol : : tie ( a , b , c ) = lua [ " f " ] ( 1 , 2 , " bar " ) ;
CHECK ( a = = 1 ) ;
CHECK ( b = = 2 ) ;
CHECK ( c = = " bar " ) ;
}
sol : : object fancy_func ( sol : : object a , sol : : object b , sol : : this_state s ) {
sol : : state_view lua ( s ) ;
if ( a . is < int > ( ) & & b . is < int > ( ) ) {
return sol : : make_object ( lua , a . as < int > ( ) + b . as < int > ( ) ) ;
} else if ( a . is < bool > ( ) ) {
bool do_triple = a . as < bool > ( ) ;
return sol : : make_object ( lua , b . as < double > ( ) * ( do_triple ? 3 : 1 ) ) ;
} else {
return sol : : make_object ( lua , sol : : lua_nil ) ;
}
}
void test_any_object_types ( ) {
sol : : state lua ;
lua [ " f " ] = fancy_func ;
int result = lua [ " f " ] ( 1 , 2 ) ;
CHECK ( result = = 3 ) ;
double result2 = lua [ " f " ] ( false , 2.5 ) ;
CHECK ( result2 = = 2.5 ) ;
lua . script ( " result3 = f(true, 5.5) " ) ;
double result3 = lua [ " result3 " ] ;
CHECK ( result3 = = 16.5 ) ;
}
struct player {
int bullets ;
int speed ;
player ( ) : player ( 3 , 100 ) { }
player ( int ammo ) : player ( ammo , 100 ) { }
player ( int ammo , int hitpoints ) :
bullets ( ammo ) , hp ( hitpoints ) { }
void boost ( ) { speed + = 10 ; }
bool shoot ( ) {
if ( bullets < 1 ) {
return false ;
}
- - bullets ;
return true ;
}
void set_hp ( int value ) {
hp = value ;
}
int get_hp ( ) const {
return hp ;
}
private :
int hp ;
} ;
void test_udt_operations ( ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua [ " p2 " ] = player ( 0 ) ;
sol : : usertype < player > player_type = lua . new_usertype < player > ( " player " ,
sol : : constructors <
player ( ) ,
player ( int ) ,
player ( int , int ) > ( ) ) ;
player_type [ " shoot " ] = & player : : shoot ;
player_type [ " boost " ] = & player : : boost ;
player_type [ " hp " ] = sol : : property ( & player : : get_hp , & player : : set_hp ) ;
player_type [ " speed " ] = & player : : speed ;
player_type . set ( " bullets " , sol : : readonly ( & player : : bullets ) ) ;
lua . script_file ( " tests/prelude_script.lua " ) ;
lua . script_file ( " tests/player_script.lua " ) ;
}
fuc2 : : Set TESTS {
. name = " sol2 " ,
. options = { . fail_fast = false } ,
. tests = {
TEST ( test_basic_lua_run ) ,
TEST ( test_usertype_vars ) ,
TEST ( test_base_libraries ) ,
TEST ( test_sol_lua_error ) ,
TEST ( test_variables_from_file ) ,
TEST ( test_big_ass_vector ) ,
TEST ( test_passing_args_to_scripts ) ,
TEST ( test_get_variables ) ,
TEST ( test_this_has_a_bug_in_sol2 ) ,
TEST ( test_multiple_returns ) ,
TEST ( test_any_object_types ) ,
TEST ( test_udt_operations ) ,
}
} ;
}