2018-09-28 13:27:38 +08:00
// sol3
2017-12-20 17:58:32 +08:00
// The MIT License (MIT)
2018-02-20 10:15:26 +08:00
// Copyright (c) 2013-2018 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"
2018-12-20 14:18:07 +08:00
# include "common_classes.hpp"
2016-08-24 09:42:27 +08:00
# include <catch.hpp>
# include <iterator>
# include <vector>
# include <list>
2017-08-06 07:20:28 +08:00
# include <forward_list>
2016-08-24 09:42:27 +08:00
# include <map>
2017-08-06 07:20:28 +08:00
# include <deque>
# include <array>
2016-08-24 09:42:27 +08:00
# include <unordered_map>
2016-08-27 20:45:37 +08:00
# include <set>
# include <unordered_set>
2016-08-24 09:42:27 +08:00
2017-06-24 06:07:24 +08:00
auto test_table_return_one ( ) {
return sol : : as_table ( std : : vector < int > { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } ) ;
2016-08-24 09:42:27 +08:00
}
2017-06-24 06:07:24 +08:00
auto test_table_return_two ( ) {
2017-09-17 02:18:45 +08:00
return sol : : as_table ( std : : vector < std : : pair < std : : string , int > > { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } } ) ;
2016-08-24 09:42:27 +08:00
}
2017-06-24 06:07:24 +08:00
auto test_table_return_three ( ) {
2017-09-17 02:18:45 +08:00
return sol : : as_table ( std : : map < std : : string , std : : string > { { " name " , " Rapptz " } , { " friend " , " ThePhD " } , { " project " , " sol " } } ) ;
2017-06-24 06:07:24 +08:00
}
auto test_table_return_four ( ) {
2017-09-17 02:18:45 +08:00
return sol : : as_table ( std : : array < std : : pair < std : : string , int > , 4 > { { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } , { " four " , 4 } } } ) ;
2016-08-24 09:42:27 +08:00
}
2017-09-23 06:54:33 +08:00
template < typename S , typename T >
void check_ordered_values ( S & src , T & target ) {
std : : size_t idx = 0 ;
auto b = std : : begin ( target ) ;
auto e = std : : end ( target ) ;
for ( ; b ! = e ; + + b , + + idx ) {
const auto & v = src [ idx ] ;
2017-09-23 11:17:37 +08:00
REQUIRE ( ( * b = = v ) ) ;
2017-09-23 06:54:33 +08:00
}
}
template < typename S , typename T >
void check_unordered_values ( S & src , T & target ) {
std : : size_t idx = 0 ;
auto b = std : : begin ( target ) ;
auto e = std : : end ( target ) ;
for ( ; b ! = e ; + + b , + + idx ) {
auto sb = std : : begin ( src ) ;
auto se = std : : end ( src ) ;
auto it = std : : find ( sb , se , * b ) ;
2017-09-23 11:17:37 +08:00
REQUIRE ( ( it ! = se ) ) ;
2017-09-23 06:54:33 +08:00
}
}
2016-08-24 09:42:27 +08:00
TEST_CASE ( " containers/returns " , " make sure that even references to vectors are being serialized as tables " ) {
sol : : state lua ;
std : : vector < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : vector < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-08-24 09:42:27 +08:00
sol : : object x = lua [ " x " ] ;
sol : : type xt = x . get_type ( ) ;
REQUIRE ( xt = = sol : : type : : userdata ) ;
sol : : table t = x ;
bool matching ;
matching = t [ 1 ] = = 1 ;
REQUIRE ( matching ) ;
matching = t [ 2 ] = = 2 ;
REQUIRE ( matching ) ;
matching = t [ 3 ] = = 3 ;
REQUIRE ( matching ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/vector roundtrip " , " make sure vectors can be round-tripped " ) {
2016-08-24 09:42:27 +08:00
sol : : state lua ;
std : : vector < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : vector < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-08-24 09:42:27 +08:00
std : : vector < int > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " containers/deque roundtrip " , " make sure deques can be round-tripped " ) {
sol : : state lua ;
std : : deque < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : deque < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2017-08-06 07:20:28 +08:00
std : : deque < int > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
TEST_CASE ( " containers/array roundtrip " , " make sure arrays can be round-tripped " ) {
sol : : state lua ;
2017-08-07 19:54:43 +08:00
std : : array < int , 3 > v { { 1 , 2 , 3 } } ;
2017-08-06 07:20:28 +08:00
lua . set_function ( " f " , [ & ] ( ) - > std : : array < int , 3 > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2017-08-06 07:20:28 +08:00
std : : array < int , 3 > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/list roundtrip " , " make sure lists can be round-tripped " ) {
2016-08-24 09:42:27 +08:00
sol : : state lua ;
std : : list < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : list < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2017-09-17 02:18:45 +08:00
std : : list < int > x = lua [ " x " ] ;
2016-08-24 09:42:27 +08:00
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-08-06 07:20:28 +08:00
TEST_CASE ( " containers/forward_list roundtrip " , " make sure forward_lists can be round-tripped " ) {
sol : : state lua ;
std : : forward_list < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : forward_list < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2017-09-17 02:18:45 +08:00
std : : forward_list < int > x = lua [ " x " ] ;
2017-08-06 07:20:28 +08:00
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/map roundtrip " , " make sure maps can be round-tripped " ) {
2016-08-24 09:42:27 +08:00
sol : : state lua ;
2017-09-17 02:18:45 +08:00
std : : map < std : : string , int > v { { " a " , 1 } , { " b " , 2 } , { " c " , 3 } } ;
2016-08-24 09:42:27 +08:00
lua . set_function ( " f " , [ & ] ( ) - > std : : map < std : : string , int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-08-24 09:42:27 +08:00
std : : map < std : : string , int > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/unordered_map roundtrip " , " make sure unordered_maps can be round-tripped " ) {
2016-08-24 09:42:27 +08:00
sol : : state lua ;
2017-09-17 02:18:45 +08:00
std : : unordered_map < std : : string , int > v { { " a " , 1 } , { " b " , 2 } , { " c " , 3 } } ;
2016-08-24 09:42:27 +08:00
lua . set_function ( " f " , [ & ] ( ) - > std : : unordered_map < std : : string , int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-08-24 09:42:27 +08:00
std : : unordered_map < std : : string , int > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/unordered_set roundtrip " , " make sure unordered_sets can be round-tripped " ) {
2016-08-27 20:45:37 +08:00
sol : : state lua ;
std : : unordered_set < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : unordered_set < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-08-27 20:45:37 +08:00
std : : unordered_set < int > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/set roundtrip " , " make sure sets can be round-tripped " ) {
2016-08-27 20:45:37 +08:00
sol : : state lua ;
std : : set < int > v { 1 , 2 , 3 } ;
lua . set_function ( " f " , [ & ] ( ) - > std : : set < int > & {
return v ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " x = f() " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-08-27 20:45:37 +08:00
std : : set < int > x = lua [ " x " ] ;
bool areequal = x = = v ;
REQUIRE ( areequal ) ;
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/custom usertype " , " make sure container usertype metatables can be overridden " ) {
2016-08-24 09:42:27 +08:00
typedef std : : unordered_map < int , int > bark ;
2017-09-17 02:18:45 +08:00
2016-08-24 09:42:27 +08:00
sol : : state lua ;
lua . open_libraries ( ) ;
lua . new_usertype < bark > ( " bark " ,
" something " , [ ] ( const bark & b ) {
INFO ( " It works: " < < b . at ( 24 ) ) ;
} ,
2017-09-17 02:18:45 +08:00
" size " , & bark : : size , " at " , sol : : resolve < const int & > ( & bark : : at ) , " clear " , & bark : : clear ) ;
2016-08-24 09:42:27 +08:00
bark obj { { 24 , 50 } } ;
lua . set ( " a " , & obj ) ;
2017-12-07 21:24:50 +08:00
{
auto result0 = lua . safe_script ( " assert(a:at(24) == 50) " , sol : : script_pass_on_error ) ;
REQUIRE ( result0 . valid ( ) ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " a:something() " , sol : : script_pass_on_error ) ;
2017-12-07 21:24:50 +08:00
REQUIRE ( result1 . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
lua . set ( " a " , obj ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " assert(a:at(24) == 50) " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " a:something() " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/const serialization kvp " , " make sure const keys / values are respected " ) {
2016-08-24 09:42:27 +08:00
typedef std : : map < int , const int > bark ;
sol : : state lua ;
lua . open_libraries ( ) ;
2017-12-07 21:24:50 +08:00
{
bark obj { { 24 , 50 } } ;
lua . set ( " a " , std : : ref ( obj ) ) ;
auto result0 = lua . safe_script ( " assert(a[24] == 50) " , sol : : script_pass_on_error ) ;
REQUIRE ( result0 . valid ( ) ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " a[24] = 51 " , sol : : script_pass_on_error ) ;
REQUIRE_FALSE ( result1 . valid ( ) ) ;
2017-12-07 21:24:50 +08:00
auto result2 = lua . safe_script ( " assert(a[24] == 50) " , sol : : script_pass_on_error ) ;
REQUIRE ( result2 . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/basic serialization " , " make sure containers are turned into proper userdata and have basic hooks established " ) {
2016-08-24 09:42:27 +08:00
typedef std : : vector < int > woof ;
sol : : state lua ;
lua . open_libraries ( ) ;
lua . set ( " b " , woof { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 } ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k = 1, #b do assert(k == b[k]) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
woof w { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 } ;
lua . set ( " b " , w ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k = 1, #b do assert(k == b[k]) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
lua . set ( " b " , & w ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k = 1, #b do assert(k == b[k]) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
lua . set ( " b " , std : : ref ( w ) ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k = 1, #b do assert(k == b[k]) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
}
2017-08-06 07:20:28 +08:00
#if 0 // LUL const int holders
TEST_CASE ( " containers/const serialization " , " make sure containers are turned into proper userdata and the basic hooks respect const-ness " ) {
2016-08-24 09:42:27 +08:00
typedef std : : vector < const int > woof ;
sol : : state lua ;
lua . open_libraries ( ) ;
lua . set ( " b " , woof { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 } ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k, v in pairs(b) do assert(k == v) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " b[1] = 20 " , sol : : script_pass_on_error ) ;
REQUIRE_FALSE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
}
2017-08-06 07:20:28 +08:00
# endif
2016-08-24 09:42:27 +08:00
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/table serialization " , " ensure types can be serialized as tables still " ) {
2016-08-24 09:42:27 +08:00
typedef std : : vector < int > woof ;
sol : : state lua ;
lua . open_libraries ( ) ;
lua . set ( " b " , sol : : as_table ( woof { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 } ) ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k, v in ipairs(b) do assert(k == v) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
woof w { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 } ;
lua . set ( " b " , sol : : as_table ( w ) ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k, v in ipairs(b) do assert(k == v) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
lua . set ( " b " , sol : : as_table ( & w ) ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k, v in ipairs(b) do assert(k == v) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
lua . set ( " b " , sol : : as_table ( std : : ref ( w ) ) ) ;
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " for k, v in ipairs(b) do assert(k == v) end " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/const correctness " , " usertype metatable names should reasonably ignore const attributes " ) {
2016-08-24 09:42:27 +08:00
struct Vec {
int x , y , z ;
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
lua . new_usertype < Vec > ( " Vec " , " x " , & Vec : : x , " y " , & Vec : : y , " z " , & Vec : : z ) ;
Vec vec ;
vec . x = 1 ;
vec . y = 2 ;
vec . z = - 3 ;
std : : vector < Vec > foo ;
foo . push_back ( vec ) ;
2017-09-17 02:18:45 +08:00
std : : vector < Vec const * > bar ;
2016-08-24 09:42:27 +08:00
bar . push_back ( & vec ) ;
2018-01-29 11:21:13 +08:00
auto result0 = lua . safe_script ( R " (
2016-08-24 09:42:27 +08:00
func = function ( vecs )
2016-08-24 20:31:18 +08:00
for i = 1 , # vecs do
vec = vecs [ i ]
2016-08-24 09:42:27 +08:00
print ( i , " : " , vec . x , vec . y , vec . z )
end
end
2018-01-29 11:21:13 +08:00
) " , sol::script_pass_on_error);
REQUIRE ( result0 . valid ( ) ) ;
sol : : protected_function f ( lua [ " func " ] ) ;
auto pfr1 = f ( foo ) ;
REQUIRE ( pfr1 . valid ( ) ) ;
auto pfr2 = f ( bar ) ;
REQUIRE ( pfr2 . valid ( ) ) ;
2016-08-24 09:42:27 +08:00
}
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/arbitrary creation " , " userdata and tables should be usable from standard containers " ) {
2016-08-24 09:42:27 +08:00
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 ) ;
2017-06-24 06:07:24 +08:00
lua . set_function ( " test_four " , test_table_return_four ) ;
2016-08-24 09:42:27 +08:00
2017-12-07 21:24:50 +08:00
{
auto result = lua . safe_script ( " a = test_one() " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " b = test_two() " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " c = test_three() " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " d = test_four() " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(#a == 10, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(a[3] == 3, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(b.one == 1, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(b.three == 3, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(c.name == 'Rapptz', 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(c.project == 'sol', 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(d.one == 1, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(d.three == 3, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
{
auto result = lua . safe_script ( " assert(d.four == 4, 'error') " , sol : : script_pass_on_error ) ;
REQUIRE ( result . valid ( ) ) ;
}
2016-08-24 09:42:27 +08:00
sol : : table a = lua . get < sol : : table > ( " a " ) ;
sol : : table b = lua . get < sol : : table > ( " b " ) ;
sol : : table c = lua . get < sol : : table > ( " c " ) ;
2017-06-24 06:07:24 +08:00
sol : : table d = lua [ " d " ] ;
2016-08-24 09:42:27 +08:00
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 " ) ;
2017-06-24 06:07:24 +08:00
REQUIRE ( d . get < int > ( " one " ) = = 1 ) ;
REQUIRE ( d . get < int > ( " three " ) = = 3 ) ;
REQUIRE ( d . get < int > ( " four " ) = = 4 ) ;
2016-08-24 09:42:27 +08:00
}
2016-09-29 07:05:26 +08:00
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/usertype transparency " , " Make sure containers pass their arguments through transparently and push the results as references, not new values " ) {
2016-09-29 07:05:26 +08:00
class A {
public :
int a ;
2017-09-17 02:18:45 +08:00
A ( int b = 2 )
: a ( b ) { } ;
2016-09-29 07:05:26 +08:00
2017-09-17 02:18:45 +08:00
void func ( ) {
}
2016-09-29 07:05:26 +08:00
} ;
struct B {
B ( ) {
for ( std : : size_t i = 0 ; i < 20 ; + + i ) {
a_list . emplace_back ( static_cast < int > ( i ) ) ;
}
}
std : : vector < A > a_list ;
} ;
sol : : state lua ;
lua . new_usertype < B > ( " B " ,
2017-09-17 02:18:45 +08:00
" a_list " , & B : : a_list ) ;
2016-09-29 07:05:26 +08:00
2018-01-29 11:21:13 +08:00
auto result = lua . safe_script ( R " (
2016-09-29 07:05:26 +08:00
b = B . new ( )
a_ref = b . a_list [ 2 ]
2018-01-29 11:21:13 +08:00
) " , sol::script_pass_on_error);
REQUIRE ( result . valid ( ) ) ;
2016-09-29 07:05:26 +08:00
B & b = lua [ " b " ] ;
A & a_ref = lua [ " a_ref " ] ;
REQUIRE ( & b . a_list [ 1 ] = = & a_ref ) ;
REQUIRE ( b . a_list [ 1 ] . a = = a_ref . a ) ;
}
2016-11-08 02:52:20 +08:00
struct options {
static int livingcount ;
static options * last ;
options ( ) {
+ + livingcount ;
last = this ;
INFO ( " constructor: " < < this ) ;
}
std : : string output_help ( ) {
last = this ;
INFO ( " func: " < < this ) ;
return " " ;
}
2017-09-17 02:18:45 +08:00
void begin ( ) {
}
void end ( ) {
}
2016-11-08 02:52:20 +08:00
~ options ( ) {
last = this ;
- - livingcount ;
}
} ;
options * options : : last = nullptr ;
int options : : livingcount = 0 ;
struct machine {
options opt ;
} ;
namespace sol {
template < >
struct is_container < options > : std : : false_type { } ;
2017-09-17 02:18:45 +08:00
} // namespace sol
2016-11-08 02:52:20 +08:00
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/is container " , " make sure the is_container trait behaves properly " ) {
2016-11-08 02:52:20 +08:00
sol : : state lua ;
lua . open_libraries ( ) ;
lua . new_usertype < options > ( " options_type " ,
2017-09-17 02:18:45 +08:00
" output_help " , & options : : output_help ) ;
2016-11-08 02:52:20 +08:00
lua . new_usertype < machine > ( " machine_type " ,
" new " , sol : : no_constructor ,
" opt " , [ ] ( machine & m ) { return & m . opt ; } ,
2017-09-17 02:18:45 +08:00
" copy_opt " , [ ] ( machine & m ) { return m . opt ; } ) ;
2016-11-08 02:52:20 +08:00
2017-09-17 02:18:45 +08:00
{
2016-11-08 02:52:20 +08:00
machine m ;
lua [ " machine " ] = & m ;
2018-01-29 11:21:13 +08:00
auto result0 = lua . safe_script ( R " (
machine : opt ( ) : output_help ( )
) " , sol::script_pass_on_error);
REQUIRE ( result0 . valid ( ) ) ;
2016-11-08 02:52:20 +08:00
REQUIRE ( options : : last = = & m . opt ) ;
REQUIRE ( options : : livingcount = = 1 ) ;
}
REQUIRE ( options : : livingcount = = 0 ) ;
}
2016-11-15 02:42:55 +08:00
TEST_CASE ( " containers/readonly " , " make sure readonly members are stored appropriately " ) {
sol : : state lua ;
lua . open_libraries ( ) ;
struct bar {
int x = 24 ;
} ;
struct foo {
std : : list < bar > seq ;
} ;
lua . new_usertype < foo > (
" foo " ,
2017-09-17 02:18:45 +08:00
" seq " , & foo : : seq , // this one works
" readonly_seq " , sol : : readonly ( & foo : : seq ) // this one does not work
) ;
lua [ " value " ] = std : : list < bar > { { } , { } , { } } ;
2018-01-29 11:21:13 +08:00
auto result0 = lua . safe_script ( R " (
2016-11-15 02:42:55 +08:00
a = foo . new ( )
x = a . seq
a . seq = value
y = a . readonly_seq
2018-01-29 11:21:13 +08:00
) " , sol::script_pass_on_error);
REQUIRE ( result0 . valid ( ) ) ;
2016-11-15 02:42:55 +08:00
std : : list < bar > & seqrefx = lua [ " x " ] ;
std : : list < bar > & seqrefy = lua [ " y " ] ;
REQUIRE ( & seqrefx = = & seqrefy ) ;
REQUIRE ( seqrefx . size ( ) = = 3 ) ;
2017-12-11 04:56:49 +08:00
auto result = lua . safe_script ( " a.readonly_seq = value " , sol : : script_pass_on_error ) ;
2016-11-15 02:42:55 +08:00
REQUIRE_FALSE ( result . valid ( ) ) ;
}
2016-11-27 02:58:06 +08:00
TEST_CASE ( " containers/to_args " , " Test that the to_args abstractions works " ) {
sol : : state lua ;
lua . open_libraries ( ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " function f (a, b, c, d) print(a, b, c, d) return a, b, c, d end " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
2016-11-27 02:58:06 +08:00
sol : : function f = lua [ " f " ] ;
int a , b , c , d ;
std : : vector < int > v2 { 3 , 4 } ;
sol : : tie ( a , b , c , d ) = f ( 1 , 2 , sol : : as_args ( v2 ) ) ;
REQUIRE ( a = = 1 ) ;
REQUIRE ( b = = 2 ) ;
REQUIRE ( c = = 3 ) ;
REQUIRE ( d = = 4 ) ;
std : : set < int > v4 { 7 , 6 , 8 , 5 } ;
sol : : tie ( a , b , c , d ) = f ( sol : : as_args ( v4 ) ) ;
REQUIRE ( a = = 5 ) ;
REQUIRE ( b = = 6 ) ;
REQUIRE ( c = = 7 ) ;
REQUIRE ( d = = 8 ) ;
int v3 [ ] = { 10 , 11 , 12 } ;
sol : : tie ( a , b , c , d ) = f ( 9 , sol : : as_args ( v3 ) ) ;
REQUIRE ( a = = 9 ) ;
REQUIRE ( b = = 10 ) ;
REQUIRE ( c = = 11 ) ;
REQUIRE ( d = = 12 ) ;
}
2017-03-16 22:12:17 +08:00
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/ipairs test " , " ensure that abstractions roundtrip properly " ) {
2017-03-16 22:12:17 +08:00
struct thing {
int x = 20 ;
} ;
thing t { } ;
sol : : state lua ;
lua . open_libraries ( ) ;
lua . set_function ( " f " , [ & t ] ( ) {
return std : : vector < thing * > ( 5 , & t ) ;
} ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( R " (
2017-03-16 22:12:17 +08:00
c = f ( )
2018-01-29 11:21:13 +08:00
) " , sol::script_pass_on_error);
REQUIRE ( result1 . valid ( ) ) ;
2017-03-16 22:12:17 +08:00
2018-01-29 11:21:13 +08:00
auto result2 = lua . safe_script ( R " (
2017-03-16 22:12:17 +08:00
check = { }
local i = 1
while c [ i ] do
2017-03-17 03:53:51 +08:00
check [ i ] = c [ i ]
2017-03-16 22:12:17 +08:00
i = i + 1
end
2018-01-29 11:21:13 +08:00
) " , sol::script_pass_on_error);
REQUIRE ( result2 . valid ( ) ) ;
2017-03-16 22:12:17 +08:00
sol : : table c = lua [ " check " ] ;
for ( std : : size_t i = 1 ; i < 6 ; + + i ) {
thing & ct = c [ i ] ;
REQUIRE ( & t = = & ct ) ;
REQUIRE ( ct . x = = 20 ) ;
}
}
2017-04-08 20:25:49 +08:00
2017-07-10 00:00:57 +08:00
TEST_CASE ( " containers/append idiom " , " ensure the append-idiom works as intended " ) {
2017-04-08 20:25:49 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script (
2017-09-17 02:18:45 +08:00
R " (
2017-04-08 20:25:49 +08:00
function f_fill ( vec )
print ( " #vec in lua: " . . # vec )
for k = 1 , # vec do
vec [ k ] = k
end
print ( " #vec in lua: " . . # vec )
end
function f_append ( vec )
print ( " #vec in lua: " . . # vec )
vec [ # vec ] = - 10456407
vec [ # vec + 1 ] = - 54
print ( " #vec in lua: " . . # vec )
end
) " );
2018-01-29 11:21:13 +08:00
REQUIRE ( result1 . valid ( ) ) ;
2017-04-08 20:25:49 +08:00
std : : vector < int > fill_cmp { 1 , 2 , 3 } ;
std : : vector < int > append_cmp { - 1 , - 1 , - 10456407 , - 54 } ;
std : : vector < int > vec1 { - 1 , - 1 , - 1 } ;
std : : vector < int > vec2 { - 1 , - 1 , - 1 } ;
REQUIRE ( vec1 . size ( ) = = 3 ) ;
lua [ " f_fill " ] ( vec1 ) ;
REQUIRE ( vec1 . size ( ) = = 3 ) ;
REQUIRE ( vec1 = = fill_cmp ) ;
REQUIRE ( vec2 . size ( ) = = 3 ) ;
lua [ " f_append " ] ( vec2 ) ;
REQUIRE ( vec2 . size ( ) = = 4 ) ;
REQUIRE ( vec2 = = append_cmp ) ;
}
2017-05-21 08:01:04 +08:00
TEST_CASE ( " containers/non_copyable " , " make sure non-copyable types in containers behave properly when stored as a member variable in a bound usertype " ) {
struct test {
std : : vector < non_copyable > b ;
2017-09-17 02:18:45 +08:00
test ( )
: b ( ) {
}
2017-05-21 08:01:04 +08:00
test ( test & & ) = default ;
test & operator = ( test & & ) = default ;
test ( const test & ) = delete ;
test & operator = ( const test & ) = delete ;
} ;
SECTION ( " normal " ) {
sol : : state lua ;
lua . new_usertype < test > ( " test " ,
2017-09-17 02:18:45 +08:00
" b " , sol : : readonly ( & test : : b ) ) ;
2017-05-21 08:01:04 +08:00
lua [ " v " ] = std : : vector < non_copyable > { } ;
2017-12-11 04:56:49 +08:00
auto pfr = lua . safe_script ( " t = test.new() t.b = v " , sol : : script_pass_on_error ) ;
2017-08-11 15:24:17 +08:00
REQUIRE_FALSE ( pfr . valid ( ) ) ;
2017-05-21 08:01:04 +08:00
}
}
2017-05-29 22:32:37 +08:00
2017-06-24 06:07:24 +08:00
TEST_CASE ( " containers/pairs " , " test how well pairs work with the underlying system " ) {
2017-08-11 15:24:17 +08:00
typedef std : : pair < std : : string , int > pair_arr_t [ 5 ] ;
typedef int arr_t [ 5 ] ;
2017-06-24 06:07:24 +08:00
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
2017-09-17 02:18:45 +08:00
std : : vector < std : : pair < std : : string , int > > a { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } , { " four " , 4 } , { " five " , 5 } } ;
std : : array < std : : pair < std : : string , int > , 5 > b { { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } , { " four " , 4 } , { " five " , 5 } } } ;
pair_arr_t c { { " one " , 1 } , { " two " , 2 } , { " three " , 3 } , { " four " , 4 } , { " five " , 5 } } ;
2017-08-11 15:24:17 +08:00
arr_t d = { 1 , 2 , 3 , 4 , 5 } ;
2017-06-24 06:07:24 +08:00
lua [ " a " ] = std : : ref ( a ) ;
lua [ " b " ] = & b ;
2017-08-11 15:24:17 +08:00
lua [ " c " ] = std : : ref ( c ) ;
lua [ " d " ] = & d ;
2017-06-24 06:07:24 +08:00
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( " av1, av2 = a:get(1) " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
auto result2 = lua . safe_script ( " bv1, bv2 = b:get(1) " , sol : : script_pass_on_error ) ;
REQUIRE ( result2 . valid ( ) ) ;
auto result3 = lua . safe_script ( " cv1, cv2 = c:get(1) " , sol : : script_pass_on_error ) ;
REQUIRE ( result3 . valid ( ) ) ;
auto result4 = lua . safe_script ( " dv1, dv2 = d:get(1) " , sol : : script_pass_on_error ) ;
REQUIRE ( result4 . valid ( ) ) ;
2017-06-24 06:07:24 +08:00
std : : vector < std : : pair < std : : string , int > > & la = lua [ " a " ] ;
std : : array < std : : pair < std : : string , int > , 5 > & lb = lua [ " b " ] ;
2017-08-11 15:24:17 +08:00
pair_arr_t * plc = lua [ " c " ] ;
pair_arr_t & lc = * plc ;
arr_t * pld = lua [ " d " ] ;
arr_t & ld = * pld ;
2017-06-24 06:07:24 +08:00
std : : pair < std : : string , int > & va = la [ 0 ] ;
std : : pair < std : : string , int > & vb = lb [ 0 ] ;
2017-08-11 15:24:17 +08:00
std : : pair < std : : string , int > & vc = lc [ 0 ] ;
int & vd = ld [ 0 ] ;
2017-06-24 06:07:24 +08:00
std : : string av1 = lua [ " av1 " ] ;
int av2 = lua [ " av2 " ] ;
std : : string bv1 = lua [ " bv1 " ] ;
int bv2 = lua [ " bv2 " ] ;
2017-08-11 15:24:17 +08:00
std : : string cv1 = lua [ " cv1 " ] ;
int cv2 = lua [ " cv2 " ] ;
int dv1 = lua [ " dv1 " ] ;
sol : : lua_nil_t dv2 = lua [ " dv2 " ] ;
2017-06-24 06:07:24 +08:00
REQUIRE ( va . first = = " one " ) ;
REQUIRE ( va . second = = 1 ) ;
REQUIRE ( vb . first = = " one " ) ;
REQUIRE ( vb . second = = 1 ) ;
2017-08-11 15:24:17 +08:00
REQUIRE ( vc . first = = " one " ) ;
REQUIRE ( vc . second = = 1 ) ;
REQUIRE ( vd = = 1 ) ;
2017-06-24 06:07:24 +08:00
REQUIRE ( av1 = = " one " ) ;
REQUIRE ( av2 = = 1 ) ;
REQUIRE ( bv1 = = " one " ) ;
REQUIRE ( bv2 = = 1 ) ;
2017-08-11 15:24:17 +08:00
REQUIRE ( cv1 = = " one " ) ;
REQUIRE ( cv2 = = 1 ) ;
REQUIRE ( dv1 = = 1 ) ;
REQUIRE ( dv2 = = sol : : lua_nil ) ;
}
TEST_CASE ( " containers/pointer types " , " check that containers with unique usertypes and pointers or something " ) {
struct base_t {
virtual int get ( ) const = 0 ;
} ;
struct derived_1_t : base_t {
virtual int get ( ) const override {
return 250 ;
}
} ;
struct derived_2_t : base_t {
virtual int get ( ) const override {
return 500 ;
}
} ;
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base ) ;
derived_1_t d1 ;
derived_2_t d2 ;
std : : vector < std : : unique_ptr < base_t > > v1 ;
v1 . push_back ( std : : make_unique < derived_1_t > ( ) ) ;
v1 . push_back ( std : : make_unique < derived_2_t > ( ) ) ;
std : : vector < base_t * > v2 ;
v2 . push_back ( & d1 ) ;
v2 . push_back ( & d2 ) ;
2018-01-29 11:21:13 +08:00
lua [ " c1 " ] = std : : move ( v1 ) ;
lua [ " c2 " ] = & v2 ;
auto result1 = lua . safe_script ( " b1 = c1[1] " , sol : : script_pass_on_error ) ;
REQUIRE ( result1 . valid ( ) ) ;
base_t * b1 = lua [ " b1 " ] ;
int val1 = b1 - > get ( ) ;
REQUIRE ( val1 = = 250 ) ;
auto result2 = lua . safe_script ( " b2 = c2[2] " , sol : : script_pass_on_error ) ;
REQUIRE ( result2 . valid ( ) ) ;
base_t * b2 = lua [ " b2 " ] ;
int val2 = b2 - > get ( ) ;
REQUIRE ( val2 = = 500 ) ;
2017-06-24 06:07:24 +08:00
}
2017-09-23 06:54:33 +08:00
TEST_CASE ( " containers/initializer-list " , " test initializer lists get pushed as tables directly rather than userdata " ) {
SECTION ( " array-like " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base , sol : : lib : : table ) ;
lua [ " c " ] = { 1 , 2 , 3 , 4 , 5 } ;
2018-01-29 11:21:13 +08:00
auto result1 = lua . safe_script ( R " lua(
2017-09-23 06:54:33 +08:00
for k , v in pairs ( c ) do
assert ( k = = v )
end
2018-01-29 11:21:13 +08:00
) lua " , sol::script_pass_on_error);
2017-09-23 06:54:33 +08:00
sol : : as_table_t < std : : vector < int > > t1vector = lua [ " c " ] ;
sol : : as_table_t < std : : deque < int > > t1deque = lua [ " c " ] ;
sol : : as_table_t < std : : list < int > > t1list = lua [ " c " ] ;
sol : : as_table_t < std : : forward_list < int > > t1flist = lua [ " c " ] ;
sol : : as_table_t < std : : set < int > > t1set = lua [ " c " ] ;
const int src [ 5 ] = { 1 , 2 , 3 , 4 , 5 } ;
check_ordered_values ( src , t1vector . source ) ;
check_ordered_values ( src , t1deque . source ) ;
check_ordered_values ( src , t1list . source ) ;
check_ordered_values ( src , t1flist . source ) ;
check_ordered_values ( src , t1set . source ) ;
}
SECTION ( " map-like " ) {
sol : : state lua ;
lua . open_libraries ( sol : : lib : : base , sol : : lib : : table ) ;
std : : pair < const std : : string , int > src [ 5 ] {
{ " a " , 21 } ,
{ " b " , 22 } ,
{ " c " , 23 } ,
{ " d " , 24 } ,
{ " e " , 25 }
} ;
lua [ " c " ] = std : : initializer_list < std : : pair < std : : string , int > > {
{ " a " , 21 } ,
{ " b " , 22 } ,
{ " c " , 23 } ,
{ " d " , 24 } ,
{ " e " , 25 }
} ;
sol : : as_table_t < std : : unordered_map < std : : string , int > > t1umap = lua [ " c " ] ;
sol : : as_table_t < std : : unordered_multimap < std : : string , int > > t1ummap = lua [ " c " ] ;
check_unordered_values ( src , t1umap . source ) ;
check_unordered_values ( src , t1ummap . source ) ;
}
}