test new compat mode (we only test text, but I don't really generate binary files, and it seems to play ball both ways, so...)

This commit is contained in:
ThePhD 2017-09-16 14:18:45 -04:00
parent 2aecb11e97
commit 76d7195e64
26 changed files with 1133 additions and 841 deletions

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2017-09-14 12:49:46.096117 UTC // Generated 2017-09-16 18:18:13.277753 UTC
// This header was generated with sol v2.18.3 (revision 1fc0027) // This header was generated with sol v2.18.3 (revision 2aecb11)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -1604,6 +1604,7 @@ extern "C" {
} }
#endif #endif
#undef COMPAT53_INCLUDE_SOURCE
#if defined(COMPAT53_PREFIX) #if defined(COMPAT53_PREFIX)
/* - change the symbol names of functions to avoid linker conflicts /* - change the symbol names of functions to avoid linker conflicts
* - compat-5.3.c needs to be compiled (and linked) separately * - compat-5.3.c needs to be compiled (and linked) separately
@ -1611,7 +1612,6 @@ extern "C" {
# if !defined(COMPAT53_API) # if !defined(COMPAT53_API)
# define COMPAT53_API extern # define COMPAT53_API extern
# endif # endif
# undef COMPAT53_INCLUDE_SOURCE
#else /* COMPAT53_PREFIX */ #else /* COMPAT53_PREFIX */
/* - make all functions static and include the source. /* - make all functions static and include the source.
* - compat-5.3.c doesn't need to be compiled (and linked) separately * - compat-5.3.c doesn't need to be compiled (and linked) separately
@ -1674,12 +1674,12 @@ extern "C" {
# define LUA_OPLE 2 # define LUA_OPLE 2
#endif #endif
/* LuaJIT/Lua 5.1 does not have the updated /* LuaJIT/Lua 5.1 does not have the updated
* error codes for thread status/function returns (but some patched versions do) * error codes for thread status/function returns (but some patched versions do)
* define it only if it's not found * define it only if it's not found
*/ */
#if !defined(LUA_ERRGCMM) #if !defined(LUA_ERRGCMM)
/* Use + 2 because in some versions of Lua (Lua 5.1) /* Use + 2 because in some versions of Lua (Lua 5.1)
* LUA_ERRFILE is defined as (LUA_ERRERR+1) * LUA_ERRFILE is defined as (LUA_ERRERR+1)
* so we need to avoid it (LuaJIT might have something at this * so we need to avoid it (LuaJIT might have something at this
* integer value too) * integer value too)
@ -1698,6 +1698,14 @@ typedef struct luaL_Buffer_53 {
} luaL_Buffer_53; } luaL_Buffer_53;
#define luaL_Buffer luaL_Buffer_53 #define luaL_Buffer luaL_Buffer_53
/* In PUC-Rio 5.1, userdata is a simple FILE*
* In LuaJIT, it's a struct where the first member is a FILE*
* We can't support the `closef` member
*/
typedef struct luaL_Stream {
FILE *f;
} luaL_Stream;
#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
COMPAT53_API int lua_absindex (lua_State *L, int i); COMPAT53_API int lua_absindex (lua_State *L, int i);
@ -1753,6 +1761,9 @@ COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum);
#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
COMPAT53_API void luaL_checkversion (lua_State *L); COMPAT53_API void luaL_checkversion (lua_State *L);
#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode);
@ -2003,12 +2014,15 @@ COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK
#include <share.h> #include <share.h>
#endif // VC++ _fsopen for share-allowed file read #endif /* VC++ _fsopen for share-allowed file read */
#ifndef COMPAT53_HAVE_STRERROR_R #ifndef COMPAT53_HAVE_STRERROR_R
# if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) # if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \
(!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6))
# define COMPAT53_HAVE_STRERROR_R 1 # define COMPAT53_HAVE_STRERROR_R 1
# if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || (defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE) # if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
(defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && \
(!defined(_GNU_SOURCE) || !_GNU_SOURCE)
# ifndef COMPAT53_HAVE_STRERROR_R_XSI # ifndef COMPAT53_HAVE_STRERROR_R_XSI
# define COMPAT53_HAVE_STRERROR_R_XSI 1 # define COMPAT53_HAVE_STRERROR_R_XSI 1
# endif /* XSI-Compliant strerror_r */ # endif /* XSI-Compliant strerror_r */
@ -2035,7 +2049,8 @@ COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
#endif /* strerror_r */ #endif /* strerror_r */
#ifndef COMPAT53_HAVE_STRERROR_S #ifndef COMPAT53_HAVE_STRERROR_S
# if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
(defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__)
# define COMPAT53_HAVE_STRERROR_S 1 # define COMPAT53_HAVE_STRERROR_S 1
# else /* not VC++ or C11 */ # else /* not VC++ or C11 */
# define COMPAT53_HAVE_STRERROR_S 0 # define COMPAT53_HAVE_STRERROR_S 0
@ -2046,7 +2061,7 @@ COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
#define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 #define COMPAT53_LUA_FILE_BUFFER_SIZE 4096
#endif /* Lua File Buffer Size */ #endif /* Lua File Buffer Size */
static char* compat53_strerror(int en, char* buff, size_t sz) { static char* compat53_strerror (int en, char* buff, size_t sz) {
#if COMPAT53_HAVE_STRERROR_R #if COMPAT53_HAVE_STRERROR_R
/* use strerror_r here, because it's available on these specific platforms */ /* use strerror_r here, because it's available on these specific platforms */
#if COMPAT53_HAVE_STRERROR_R_XSI #if COMPAT53_HAVE_STRERROR_R_XSI
@ -2401,13 +2416,48 @@ COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) {
if (mode && strchr(mode, modename[0]) == NULL) { if (mode && strchr(mode, modename[0]) == NULL) {
lua_pushfstring(L, "attempt to load a %s chunk when 'mode' is '%s'", modename, mode); lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode);
return err; return err;
} }
return LUA_OK; return LUA_OK;
} }
typedef struct compat53_LoadF { typedef struct {
lua_Reader reader;
void *ud;
int has_peeked_data;
const char *peeked_data;
size_t peeked_data_size;
} compat53_reader_data;
static const char *compat53_reader (lua_State *L, void *ud, size_t *size) {
compat53_reader_data *data = (compat53_reader_data *)ud;
if (data->has_peeked_data) {
data->has_peeked_data = 0;
*size = data->peeked_data_size;
return data->peeked_data;
} else
return data->reader(L, data->ud, size);
}
COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) {
int status = LUA_OK;
compat53_reader_data compat53_data = { reader, data, 1, 0, 0 };
compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size));
if (compat53_data.peeked_data && compat53_data.peeked_data_size &&
compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */
status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
else
status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
if (status != LUA_OK)
return status;
/* we need to call the original 5.1 version of lua_load! */
#undef lua_load
return lua_load(L, compat53_reader, &compat53_data, source);
#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
}
typedef struct {
int n; /* number of pre-read characters */ int n; /* number of pre-read characters */
FILE *f; /* file being read */ FILE *f; /* file being read */
char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */
@ -2472,7 +2522,6 @@ static int compat53_skipcomment (compat53_LoadF *lf, int *cp) {
} }
COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) {
static const char lua_signature[] = "\x1bLua";
compat53_LoadF lf; compat53_LoadF lf;
int status, readstatus; int status, readstatus;
int c; int c;
@ -2484,24 +2533,25 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char
else { else {
lua_pushfstring(L, "@%s", filename); lua_pushfstring(L, "@%s", filename);
#if defined(_MSC_VER) #if defined(_MSC_VER)
/* a quick check shows that fopen_s this goes back to VS 2005, /* This code is here to stop a deprecation error that stops builds
* and _fsopen goes back to VS 2003 .NET, possibly even before that * if a certain macro is defined. While normally not caring would
* so we don't need to do any version number checks, * be best, some header-only libraries and builds can't afford to
* since this has been there since forever * dictate this to the user. A quick check shows that fopen_s this
* goes back to VS 2005, and _fsopen goes back to VS 2003 .NET,
* possibly even before that so we don't need to do any version
* number checks, since this has been there since forever.
*/ */
/* TO USER: if you want the behavior of typical fopen_s/fopen, /* TO USER: if you want the behavior of typical fopen_s/fopen,
* which does lock the file on VC++, define the macro used below * which does lock the file on VC++, define the macro used below to 0
*/ */
#if COMPAT53_FOPEN_NO_LOCK #if COMPAT53_FOPEN_NO_LOCK
lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */
if (lf.f == NULL) { if (lf.f == NULL)
return compat53_errfile(L, "open", fnameindex); return compat53_errfile(L, "open", fnameindex);
}
#else /* use default locking version */ #else /* use default locking version */
if (fopen_s(&lf.f, filename, "r") != 0) { if (fopen_s(&lf.f, filename, "r") != 0)
return compat53_errfile(L, "open", fnameindex); return compat53_errfile(L, "open", fnameindex);
}
#endif /* Locking vs. No-locking fopen variants */ #endif /* Locking vs. No-locking fopen variants */
#else #else
lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */
@ -2510,30 +2560,19 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char
} }
if (compat53_skipcomment(&lf, &c)) /* read initial portion */ if (compat53_skipcomment(&lf, &c)) /* read initial portion */
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
if (c == lua_signature[0]) { /* binary file? */ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
status = compat53_checkmode(L, mode, "binary", LUA_ERRFILE);
if (status != LUA_OK) {
fclose(lf.f);
return compat53_errfile(L, "improper mode", fnameindex);
}
#if defined(_MSC_VER) #if defined(_MSC_VER)
if (freopen_s(&lf.f, filename, "r", lf.f) != 0) return compat53_errfile(L, "open", fnameindex); if (freopen_s(&lf.f, filename, "rb", lf.f) != 0)
return compat53_errfile(L, "reopen", fnameindex);
#else #else
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex);
#endif #endif
compat53_skipcomment(&lf, &c); /* re-read initial portion */ compat53_skipcomment(&lf, &c); /* re-read initial portion */
} }
else { /* text file */
status = compat53_checkmode(L, mode, "text", LUA_ERRFILE);
if (status != LUA_OK) {
fclose(lf.f);
return compat53_errfile(L, "improper mode", fnameindex);
}
}
if (c != EOF) if (c != EOF)
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1)); status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode);
readstatus = ferror(lf.f); readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (filename) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) { if (readstatus) {
@ -2546,7 +2585,7 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char
COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) {
int status = LUA_OK; int status = LUA_OK;
if (sz > 0 && buff[0] == '\x1b') { if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) {
status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
} }
else { else {
@ -18486,12 +18525,7 @@ namespace sol {
load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {}; detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
#if SOL_LUA_VERSION > 501
load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())); load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
#else
(void)mode;
load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget));
#endif
return load_result(L, absolute_index(L, -1), 1, 1, x); return load_result(L, absolute_index(L, -1), 1, 1, x);
} }

View File

@ -25,12 +25,15 @@
#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK
#include <share.h> #include <share.h>
#endif // VC++ _fsopen for share-allowed file read #endif /* VC++ _fsopen for share-allowed file read */
#ifndef COMPAT53_HAVE_STRERROR_R #ifndef COMPAT53_HAVE_STRERROR_R
# if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) # if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \
(!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6))
# define COMPAT53_HAVE_STRERROR_R 1 # define COMPAT53_HAVE_STRERROR_R 1
# if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || (defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && (!defined(_GNU_SOURCE) || !_GNU_SOURCE) # if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
(defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && \
(!defined(_GNU_SOURCE) || !_GNU_SOURCE)
# ifndef COMPAT53_HAVE_STRERROR_R_XSI # ifndef COMPAT53_HAVE_STRERROR_R_XSI
# define COMPAT53_HAVE_STRERROR_R_XSI 1 # define COMPAT53_HAVE_STRERROR_R_XSI 1
# endif /* XSI-Compliant strerror_r */ # endif /* XSI-Compliant strerror_r */
@ -57,7 +60,8 @@
#endif /* strerror_r */ #endif /* strerror_r */
#ifndef COMPAT53_HAVE_STRERROR_S #ifndef COMPAT53_HAVE_STRERROR_S
# if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \
(defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__)
# define COMPAT53_HAVE_STRERROR_S 1 # define COMPAT53_HAVE_STRERROR_S 1
# else /* not VC++ or C11 */ # else /* not VC++ or C11 */
# define COMPAT53_HAVE_STRERROR_S 0 # define COMPAT53_HAVE_STRERROR_S 0
@ -68,7 +72,8 @@
#define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 #define COMPAT53_LUA_FILE_BUFFER_SIZE 4096
#endif /* Lua File Buffer Size */ #endif /* Lua File Buffer Size */
static char* compat53_strerror(int en, char* buff, size_t sz) {
static char* compat53_strerror (int en, char* buff, size_t sz) {
#if COMPAT53_HAVE_STRERROR_R #if COMPAT53_HAVE_STRERROR_R
/* use strerror_r here, because it's available on these specific platforms */ /* use strerror_r here, because it's available on these specific platforms */
#if COMPAT53_HAVE_STRERROR_R_XSI #if COMPAT53_HAVE_STRERROR_R_XSI
@ -98,6 +103,7 @@ static char* compat53_strerror(int en, char* buff, size_t sz) {
#endif #endif
} }
COMPAT53_API int lua_absindex (lua_State *L, int i) { COMPAT53_API int lua_absindex (lua_State *L, int i) {
if (i < 0 && i > LUA_REGISTRYINDEX) if (i < 0 && i > LUA_REGISTRYINDEX)
i += lua_gettop(L) + 1; i += lua_gettop(L) + 1;
@ -441,14 +447,52 @@ COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) {
if (mode && strchr(mode, modename[0]) == NULL) { if (mode && strchr(mode, modename[0]) == NULL) {
lua_pushfstring(L, "attempt to load a %s chunk when 'mode' is '%s'", modename, mode); lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode);
return err; return err;
} }
return LUA_OK; return LUA_OK;
} }
typedef struct compat53_LoadF { typedef struct {
lua_Reader reader;
void *ud;
int has_peeked_data;
const char *peeked_data;
size_t peeked_data_size;
} compat53_reader_data;
static const char *compat53_reader (lua_State *L, void *ud, size_t *size) {
compat53_reader_data *data = (compat53_reader_data *)ud;
if (data->has_peeked_data) {
data->has_peeked_data = 0;
*size = data->peeked_data_size;
return data->peeked_data;
} else
return data->reader(L, data->ud, size);
}
COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) {
int status = LUA_OK;
compat53_reader_data compat53_data = { reader, data, 1, 0, 0 };
compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size));
if (compat53_data.peeked_data && compat53_data.peeked_data_size &&
compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */
status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
else
status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
if (status != LUA_OK)
return status;
/* we need to call the original 5.1 version of lua_load! */
#undef lua_load
return lua_load(L, compat53_reader, &compat53_data, source);
#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
}
typedef struct {
int n; /* number of pre-read characters */ int n; /* number of pre-read characters */
FILE *f; /* file being read */ FILE *f; /* file being read */
char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */
@ -518,7 +562,6 @@ static int compat53_skipcomment (compat53_LoadF *lf, int *cp) {
COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) {
static const char lua_signature[] = "\x1bLua";
compat53_LoadF lf; compat53_LoadF lf;
int status, readstatus; int status, readstatus;
int c; int c;
@ -530,24 +573,25 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char
else { else {
lua_pushfstring(L, "@%s", filename); lua_pushfstring(L, "@%s", filename);
#if defined(_MSC_VER) #if defined(_MSC_VER)
/* a quick check shows that fopen_s this goes back to VS 2005, /* This code is here to stop a deprecation error that stops builds
* and _fsopen goes back to VS 2003 .NET, possibly even before that * if a certain macro is defined. While normally not caring would
* so we don't need to do any version number checks, * be best, some header-only libraries and builds can't afford to
* since this has been there since forever * dictate this to the user. A quick check shows that fopen_s this
* goes back to VS 2005, and _fsopen goes back to VS 2003 .NET,
* possibly even before that so we don't need to do any version
* number checks, since this has been there since forever.
*/ */
/* TO USER: if you want the behavior of typical fopen_s/fopen, /* TO USER: if you want the behavior of typical fopen_s/fopen,
* which does lock the file on VC++, define the macro used below * which does lock the file on VC++, define the macro used below to 0
*/ */
#if COMPAT53_FOPEN_NO_LOCK #if COMPAT53_FOPEN_NO_LOCK
lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */
if (lf.f == NULL) { if (lf.f == NULL)
return compat53_errfile(L, "open", fnameindex); return compat53_errfile(L, "open", fnameindex);
}
#else /* use default locking version */ #else /* use default locking version */
if (fopen_s(&lf.f, filename, "r") != 0) { if (fopen_s(&lf.f, filename, "r") != 0)
return compat53_errfile(L, "open", fnameindex); return compat53_errfile(L, "open", fnameindex);
}
#endif /* Locking vs. No-locking fopen variants */ #endif /* Locking vs. No-locking fopen variants */
#else #else
lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */
@ -556,30 +600,19 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char
} }
if (compat53_skipcomment(&lf, &c)) /* read initial portion */ if (compat53_skipcomment(&lf, &c)) /* read initial portion */
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
if (c == lua_signature[0]) { /* binary file? */ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
status = compat53_checkmode(L, mode, "binary", LUA_ERRFILE);
if (status != LUA_OK) {
fclose(lf.f);
return compat53_errfile(L, "improper mode", fnameindex);
}
#if defined(_MSC_VER) #if defined(_MSC_VER)
if (freopen_s(&lf.f, filename, "r", lf.f) != 0) return compat53_errfile(L, "open", fnameindex); if (freopen_s(&lf.f, filename, "rb", lf.f) != 0)
return compat53_errfile(L, "reopen", fnameindex);
#else #else
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex);
#endif #endif
compat53_skipcomment(&lf, &c); /* re-read initial portion */ compat53_skipcomment(&lf, &c); /* re-read initial portion */
} }
else { /* text file */
status = compat53_checkmode(L, mode, "text", LUA_ERRFILE);
if (status != LUA_OK) {
fclose(lf.f);
return compat53_errfile(L, "improper mode", fnameindex);
}
}
if (c != EOF) if (c != EOF)
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1)); status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode);
readstatus = ferror(lf.f); readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (filename) fclose(lf.f); /* close file (even in case of errors) */
if (readstatus) { if (readstatus) {
@ -593,7 +626,7 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char
COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) {
int status = LUA_OK; int status = LUA_OK;
if (sz > 0 && buff[0] == '\x1b') { if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) {
status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
} }
else { else {
@ -604,6 +637,7 @@ COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, co
return luaL_loadbuffer(L, buff, sz, name); return luaL_loadbuffer(L, buff, sz, name);
} }
#if !defined(l_inspectstat) && \ #if !defined(l_inspectstat) && \
(defined(unix) || defined(__unix) || defined(__unix__) || \ (defined(unix) || defined(__unix) || defined(__unix__) || \
defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \

View File

@ -9,11 +9,13 @@ extern "C" {
#endif #endif
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
#include <lualib.h>
#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
} }
#endif #endif
#undef COMPAT53_INCLUDE_SOURCE
#if defined(COMPAT53_PREFIX) #if defined(COMPAT53_PREFIX)
/* - change the symbol names of functions to avoid linker conflicts /* - change the symbol names of functions to avoid linker conflicts
* - compat-5.3.c needs to be compiled (and linked) separately * - compat-5.3.c needs to be compiled (and linked) separately
@ -21,7 +23,6 @@ extern "C" {
# if !defined(COMPAT53_API) # if !defined(COMPAT53_API)
# define COMPAT53_API extern # define COMPAT53_API extern
# endif # endif
# undef COMPAT53_INCLUDE_SOURCE
#else /* COMPAT53_PREFIX */ #else /* COMPAT53_PREFIX */
/* - make all functions static and include the source. /* - make all functions static and include the source.
* - compat-5.3.c doesn't need to be compiled (and linked) separately * - compat-5.3.c doesn't need to be compiled (and linked) separately
@ -86,12 +87,12 @@ extern "C" {
# define LUA_OPLE 2 # define LUA_OPLE 2
#endif #endif
/* LuaJIT/Lua 5.1 does not have the updated /* LuaJIT/Lua 5.1 does not have the updated
* error codes for thread status/function returns (but some patched versions do) * error codes for thread status/function returns (but some patched versions do)
* define it only if it's not found * define it only if it's not found
*/ */
#if !defined(LUA_ERRGCMM) #if !defined(LUA_ERRGCMM)
/* Use + 2 because in some versions of Lua (Lua 5.1) /* Use + 2 because in some versions of Lua (Lua 5.1)
* LUA_ERRFILE is defined as (LUA_ERRERR+1) * LUA_ERRFILE is defined as (LUA_ERRERR+1)
* so we need to avoid it (LuaJIT might have something at this * so we need to avoid it (LuaJIT might have something at this
* integer value too) * integer value too)
@ -110,6 +111,14 @@ typedef struct luaL_Buffer_53 {
} luaL_Buffer_53; } luaL_Buffer_53;
#define luaL_Buffer luaL_Buffer_53 #define luaL_Buffer luaL_Buffer_53
/* In PUC-Rio 5.1, userdata is a simple FILE*
* In LuaJIT, it's a struct where the first member is a FILE*
* We can't support the `closef` member
*/
typedef struct luaL_Stream {
FILE *f;
} luaL_Stream;
#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
COMPAT53_API int lua_absindex (lua_State *L, int i); COMPAT53_API int lua_absindex (lua_State *L, int i);
@ -165,6 +174,9 @@ COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum);
#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
COMPAT53_API void luaL_checkversion (lua_State *L); COMPAT53_API void luaL_checkversion (lua_State *L);
#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode);

View File

@ -488,12 +488,7 @@ namespace sol {
load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
detail::typical_chunk_name_t basechunkname = {}; detail::typical_chunk_name_t basechunkname = {};
const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname);
#if SOL_LUA_VERSION > 501
load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())); load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
#else
(void)mode;
load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget));
#endif
return load_result(L, absolute_index(L, -1), 1, 1, x); return load_result(L, absolute_index(L, -1), 1, 1, x);
} }

View File

@ -22,12 +22,13 @@ private:
public: public:
static const void* last_printed; static const void* last_printed;
my_object(int sz) : mdata() { my_object(int sz)
: mdata() {
mdata.resize(sz); mdata.resize(sz);
std::iota(mdata.begin(), mdata.end(), 1); std::iota(mdata.begin(), mdata.end(), 1);
} }
void operator() (std::size_t count, int value) { void operator()(std::size_t count, int value) {
for (; count > 0; --count) { for (; count > 0; --count) {
mdata.push_back(value); mdata.push_back(value);
} }
@ -42,19 +43,45 @@ public: // Container requirements, as per the C++ standard
using difference_type = decltype(mdata)::difference_type; using difference_type = decltype(mdata)::difference_type;
using size_type = decltype(mdata)::size_type; using size_type = decltype(mdata)::size_type;
iterator begin() { return iterator(mdata.begin()); } iterator begin() {
iterator end() { return iterator(mdata.end()); } return iterator(mdata.begin());
const_iterator begin() const { return const_iterator(mdata.begin()); } }
const_iterator end() const { return const_iterator(mdata.end()); } iterator end() {
const_iterator cbegin() const { return begin(); } return iterator(mdata.end());
const_iterator cend() const { return end(); } }
size_type size() const noexcept { return mdata.size(); } const_iterator begin() const {
size_type max_size() const noexcept { return mdata.max_size(); } return const_iterator(mdata.begin());
void push_back(const value_type& v) { mdata.push_back(v); } }
void insert(const_iterator where, const value_type& v) { mdata.insert(where, v); } const_iterator end() const {
bool empty() const noexcept { return mdata.empty(); } return const_iterator(mdata.end());
bool operator== (const my_object& right) const { return mdata == right.mdata; } }
bool operator!=(const my_object& right) const noexcept { return mdata != right.mdata; } const_iterator cbegin() const {
return begin();
}
const_iterator cend() const {
return end();
}
size_type size() const noexcept {
return mdata.size();
}
size_type max_size() const noexcept {
return mdata.max_size();
}
void push_back(const value_type& v) {
mdata.push_back(v);
}
void insert(const_iterator where, const value_type& v) {
mdata.insert(where, v);
}
bool empty() const noexcept {
return mdata.empty();
}
bool operator==(const my_object& right) const {
return mdata == right.mdata;
}
bool operator!=(const my_object& right) const noexcept {
return mdata != right.mdata;
}
std::vector<int>& data() { std::vector<int>& data() {
return mdata; return mdata;
@ -63,12 +90,11 @@ public: // Container requirements, as per the C++ standard
const std::vector<int>& data() const { const std::vector<int>& data() const {
return mdata; return mdata;
} }
}; };
const void* my_object::last_printed = nullptr; const void* my_object::last_printed = nullptr;
std::ostream& operator<< (std::ostream& ostr, const my_object& mo) { std::ostream& operator<<(std::ostream& ostr, const my_object& mo) {
my_object::last_printed = static_cast<const void*>(&mo); my_object::last_printed = static_cast<const void*>(&mo);
ostr << "{ "; ostr << "{ ";
const auto& v = mo.data(); const auto& v = mo.data();
@ -89,7 +115,7 @@ std::ostream& operator<< (std::ostream& ostr, const my_object& mo) {
namespace sol { namespace sol {
template <> template <>
struct is_container<my_object> : std::false_type {}; struct is_container<my_object> : std::false_type {};
} } // namespace sol
template <typename T> template <typename T>
void sequence_container_check(sol::state& lua, T& items) { void sequence_container_check(sol::state& lua, T& items) {
@ -99,7 +125,8 @@ for i=1,#c do
v = c[i] v = c[i]
assert(v == (i + 10)) assert(v == (i + 10))
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE(r1.valid()); REQUIRE(r1.valid());
} }
{ {
@ -208,7 +235,8 @@ for i=1,#c do
v = c[(i + 10)] v = c[(i + 10)]
assert(v == (i + 10)) assert(v == (i + 10))
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE(r1.valid()); REQUIRE(r1.valid());
} }
{ {
@ -403,7 +431,8 @@ for i=1,#c do
v = c[(i + 10)] v = c[(i + 10)]
assert(v == (i + 20)) assert(v == (i + 20))
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE(r1.valid()); REQUIRE(r1.valid());
} }
{ {
@ -617,7 +646,8 @@ for i=1,#c do
v = c[i] v = c[i]
assert(v == (i + 10)) assert(v == (i + 10))
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE(r1.valid()); REQUIRE(r1.valid());
} }
{ {
@ -730,7 +760,7 @@ TEST_CASE("containers/sequence containers", "check all of the functinos for ever
SECTION("list") { SECTION("list") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
std::list<int> items{ 11, 12, 13, 14, 15 }; std::list<int> items{ 11, 12, 13, 14, 15 };
lua["c"] = &items; lua["c"] = &items;
sequence_container_check(lua, items); sequence_container_check(lua, items);
@ -911,18 +941,18 @@ end
)"); )");
// Have the function we // Have the function we
// just defined in Lua // just defined in Lua
sol::function g = lua["g"]; sol::function g = lua["g"];
sol::function h = lua["h"]; sol::function h = lua["h"];
sol::function i = lua["i"]; sol::function i = lua["i"];
sol::function sf = lua["sf"]; sol::function sf = lua["sf"];
// Set a global variable called // Set a global variable called
// "arr" to be a vector of 5 lements // "arr" to be a vector of 5 lements
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } }; lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 }; lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 };
lua["map"] = std::map<int, int>{ { 1 , 2 },{ 2, 4 },{ 3, 6 },{ 4, 8 },{ 5, 10 } }; lua["map"] = std::map<int, int>{ { 1, 2 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 10 } };
lua["set"] = std::set<int>{ 2, 4, 6, 8, 10 }; lua["set"] = std::set<int>{ 2, 4, 6, 8, 10 };
std::array<int, 5>& c_arr = lua["c_arr"]; std::array<int, 5>& c_arr = lua["c_arr"];
std::vector<int>& arr = lua["arr"]; std::vector<int>& arr = lua["arr"];
@ -1002,8 +1032,7 @@ TEST_CASE("containers/as_container reference", "test that we can force a contain
"size", &my_object::size, "size", &my_object::size,
"iterable", [](my_object& mo) { "iterable", [](my_object& mo) {
return sol::as_container(mo); return sol::as_container(mo);
} });
);
#if SOL_LUA_VERSION > 501 #if SOL_LUA_VERSION > 501
REQUIRE_NOTHROW([&]() { REQUIRE_NOTHROW([&]() {

View File

@ -19,15 +19,15 @@ auto test_table_return_one() {
} }
auto test_table_return_two() { auto test_table_return_two() {
return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 },{ "two", 2 },{ "three", 3 } }); return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 }, { "two", 2 }, { "three", 3 } });
} }
auto test_table_return_three() { auto test_table_return_three() {
return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } }); return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" }, { "friend", "ThePhD" }, { "project", "sol" } });
} }
auto test_table_return_four() { auto test_table_return_four() {
return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 },{ "two", 2 },{ "three", 3 },{ "four", 4 } } }); return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } } });
} }
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") { TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
@ -55,11 +55,11 @@ TEST_CASE("containers/table conversion", "test table conversions with as_table a
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.set_function("bark", []() { lua.set_function("bark", []() {
return sol::as_nested(std::vector<std::string>{"bark", "woof"}); return sol::as_nested(std::vector<std::string>{ "bark", "woof" });
}); });
lua.set_function("woof", []() { lua.set_function("woof", []() {
return sol::as_nested(std::vector<std::string>{"bark", "woof"}); return sol::as_nested(std::vector<std::string>{ "bark", "woof" });
}); });
lua.safe_script("v1 = bark()"); lua.safe_script("v1 = bark()");
@ -68,7 +68,7 @@ TEST_CASE("containers/table conversion", "test table conversions with as_table a
sol::as_table_t<std::vector<std::string>> as_table_strings = lua["v1"]; sol::as_table_t<std::vector<std::string>> as_table_strings = lua["v1"];
sol::nested<std::vector<std::string>> nested_strings = lua["v2"]; sol::nested<std::vector<std::string>> nested_strings = lua["v2"];
std::vector<std::string> expected_values{"bark", "woof"}; std::vector<std::string> expected_values{ "bark", "woof" };
REQUIRE(as_table_strings.source == expected_values); REQUIRE(as_table_strings.source == expected_values);
REQUIRE(nested_strings.source == expected_values); REQUIRE(nested_strings.source == expected_values);
} }
@ -116,7 +116,7 @@ TEST_CASE("containers/list roundtrip", "make sure lists can be round-tripped") {
return v; return v;
}); });
lua.safe_script("x = f()"); lua.safe_script("x = f()");
std::list <int> x = lua["x"]; std::list<int> x = lua["x"];
bool areequal = x == v; bool areequal = x == v;
REQUIRE(areequal); REQUIRE(areequal);
} }
@ -128,14 +128,14 @@ TEST_CASE("containers/forward_list roundtrip", "make sure forward_lists can be r
return v; return v;
}); });
lua.safe_script("x = f()"); lua.safe_script("x = f()");
std::forward_list <int> x = lua["x"]; std::forward_list<int> x = lua["x"];
bool areequal = x == v; bool areequal = x == v;
REQUIRE(areequal); REQUIRE(areequal);
} }
TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") { TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") {
sol::state lua; sol::state lua;
std::map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; std::map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() -> std::map<std::string, int>& { lua.set_function("f", [&]() -> std::map<std::string, int>& {
return v; return v;
}); });
@ -147,7 +147,7 @@ TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") {
TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be round-tripped") { TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be round-tripped") {
sol::state lua; sol::state lua;
std::unordered_map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; std::unordered_map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& { lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& {
return v; return v;
}); });
@ -224,7 +224,7 @@ TEST_CASE("containers/list table roundtrip", "make sure lists can be round-tripp
return sol::as_table(v); return sol::as_table(v);
}); });
lua.safe_script("x = f()"); lua.safe_script("x = f()");
sol::as_table_t<std::list <int>> x = lua["x"]; sol::as_table_t<std::list<int>> x = lua["x"];
bool areequal = x.source == v; bool areequal = x.source == v;
REQUIRE(areequal); REQUIRE(areequal);
} }
@ -243,7 +243,7 @@ TEST_CASE("containers/forward_list table roundtrip", "make sure forward_lists ca
TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped") { TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped") {
sol::state lua; sol::state lua;
std::map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; std::map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() { lua.set_function("f", [&]() {
return sol::as_table(v); return sol::as_table(v);
}); });
@ -255,7 +255,7 @@ TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped
TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps can be round-tripped") { TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps can be round-tripped") {
sol::state lua; sol::state lua;
std::unordered_map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; std::unordered_map<std::string, int> v{ { "a", 1 }, { "b", 2 }, { "c", 3 } };
lua.set_function("f", [&]() { lua.set_function("f", [&]() {
return sol::as_table(v); return sol::as_table(v);
}); });
@ -291,17 +291,14 @@ TEST_CASE("containers/set table roundtrip", "make sure sets can be round-tripped
TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") { TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") {
typedef std::unordered_map<int, int> bark; typedef std::unordered_map<int, int> bark;
sol::state lua; sol::state lua;
lua.open_libraries(); lua.open_libraries();
lua.new_usertype<bark>("bark", lua.new_usertype<bark>("bark",
"something", [](const bark& b) { "something", [](const bark& b) {
INFO("It works: " << b.at(24)); INFO("It works: " << b.at(24));
}, },
"size", &bark::size, "size", &bark::size, "at", sol::resolve<const int&>(&bark::at), "clear", &bark::clear);
"at", sol::resolve<const int&>(&bark::at),
"clear", &bark::clear
);
bark obj{ { 24, 50 } }; bark obj{ { 24, 50 } };
lua.set("a", &obj); lua.set("a", &obj);
REQUIRE_NOTHROW(lua.safe_script("assert(a:at(24) == 50)")); REQUIRE_NOTHROW(lua.safe_script("assert(a:at(24) == 50)"));
@ -330,21 +327,17 @@ TEST_CASE("containers/basic serialization", "make sure containers are turned int
lua.open_libraries(); 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 }); 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 });
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k = 1, #b do assert(k == b[k]) end") lua.safe_script("for k = 1, #b do assert(k == b[k]) end"));
);
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 }; 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); lua.set("b", w);
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k = 1, #b do assert(k == b[k]) end") lua.safe_script("for k = 1, #b do assert(k == b[k]) end"));
);
lua.set("b", &w); lua.set("b", &w);
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k = 1, #b do assert(k == b[k]) end") lua.safe_script("for k = 1, #b do assert(k == b[k]) end"));
);
lua.set("b", std::ref(w)); lua.set("b", std::ref(w));
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k = 1, #b do assert(k == b[k]) end") lua.safe_script("for k = 1, #b do assert(k == b[k]) end"));
);
} }
#if 0 // LUL const int holders #if 0 // LUL const int holders
@ -367,21 +360,17 @@ TEST_CASE("containers/table serialization", "ensure types can be serialized as t
lua.open_libraries(); 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 })); 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 }));
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k, v in ipairs(b) do assert(k == v) end") lua.safe_script("for k, v in ipairs(b) do assert(k == v) end"));
);
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 }; 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)); lua.set("b", sol::as_table(w));
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k, v in ipairs(b) do assert(k == v) end") lua.safe_script("for k, v in ipairs(b) do assert(k == v) end"));
);
lua.set("b", sol::as_table(&w)); lua.set("b", sol::as_table(&w));
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k, v in ipairs(b) do assert(k == v) end") lua.safe_script("for k, v in ipairs(b) do assert(k == v) end"));
);
lua.set("b", sol::as_table(std::ref(w))); lua.set("b", sol::as_table(std::ref(w)));
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script("for k, v in ipairs(b) do assert(k == v) end") lua.safe_script("for k, v in ipairs(b) do assert(k == v) end"));
);
} }
TEST_CASE("containers/const correctness", "usertype metatable names should reasonably ignore const attributes") { TEST_CASE("containers/const correctness", "usertype metatable names should reasonably ignore const attributes") {
@ -401,7 +390,7 @@ TEST_CASE("containers/const correctness", "usertype metatable names should reaso
std::vector<Vec> foo; std::vector<Vec> foo;
foo.push_back(vec); foo.push_back(vec);
std::vector<Vec const *> bar; std::vector<Vec const*> bar;
bar.push_back(&vec); bar.push_back(&vec);
lua.safe_script(R"( lua.safe_script(R"(
@ -413,7 +402,7 @@ func = function(vecs)
end end
)"); )");
REQUIRE_NOTHROW([&]{ REQUIRE_NOTHROW([&] {
lua["func"](foo); lua["func"](foo);
lua["func"](bar); lua["func"](bar);
}()); }());
@ -462,9 +451,11 @@ TEST_CASE("containers/usertype transparency", "Make sure containers pass their a
class A { class A {
public: public:
int a; int a;
A(int b = 2) : a(b) {}; A(int b = 2)
: a(b){};
void func() { } void func() {
}
}; };
struct B { struct B {
@ -480,8 +471,7 @@ TEST_CASE("containers/usertype transparency", "Make sure containers pass their a
sol::state lua; sol::state lua;
lua.new_usertype<B>("B", lua.new_usertype<B>("B",
"a_list", &B::a_list "a_list", &B::a_list);
);
lua.safe_script(R"( lua.safe_script(R"(
b = B.new() b = B.new()
@ -509,8 +499,10 @@ struct options {
return ""; return "";
} }
void begin() {} void begin() {
void end() {} }
void end() {
}
~options() { ~options() {
last = this; last = this;
@ -528,23 +520,21 @@ struct machine {
namespace sol { namespace sol {
template <> template <>
struct is_container<options> : std::false_type {}; struct is_container<options> : std::false_type {};
} } // namespace sol
TEST_CASE("containers/is container", "make sure the is_container trait behaves properly") { TEST_CASE("containers/is container", "make sure the is_container trait behaves properly") {
sol::state lua; sol::state lua;
lua.open_libraries(); lua.open_libraries();
lua.new_usertype<options>("options_type", lua.new_usertype<options>("options_type",
"output_help", &options::output_help "output_help", &options::output_help);
);
lua.new_usertype<machine>("machine_type", lua.new_usertype<machine>("machine_type",
"new", sol::no_constructor, "new", sol::no_constructor,
"opt", [](machine& m) { return &m.opt; }, "opt", [](machine& m) { return &m.opt; },
"copy_opt", [](machine& m) { return m.opt; } "copy_opt", [](machine& m) { return m.opt; });
);
{ {
machine m; machine m;
lua["machine"] = &m; lua["machine"] = &m;
@ -572,11 +562,11 @@ TEST_CASE("containers/readonly", "make sure readonly members are stored appropri
lua.new_usertype<foo>( lua.new_usertype<foo>(
"foo", "foo",
"seq", &foo::seq, // this one works "seq", &foo::seq, // this one works
"readonly_seq", sol::readonly(&foo::seq) // this one does not work "readonly_seq", sol::readonly(&foo::seq) // this one does not work
); );
lua["value"] = std::list<bar>{ {},{},{} }; lua["value"] = std::list<bar>{ {}, {}, {} };
lua.safe_script(R"( lua.safe_script(R"(
a = foo.new() a = foo.new()
x = a.seq x = a.seq
@ -622,7 +612,6 @@ TEST_CASE("containers/to_args", "Test that the to_args abstractions works") {
REQUIRE(b == 10); REQUIRE(b == 10);
REQUIRE(c == 11); REQUIRE(c == 11);
REQUIRE(d == 12); REQUIRE(d == 12);
} }
TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly") { TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly") {
@ -661,7 +650,7 @@ TEST_CASE("containers/append idiom", "ensure the append-idiom works as intended"
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.safe_script( lua.safe_script(
R"( R"(
function f_fill(vec) function f_fill(vec)
print("#vec in lua: " .. #vec) print("#vec in lua: " .. #vec)
for k = 1, #vec do for k = 1, #vec do
@ -703,7 +692,9 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
struct test { struct test {
std::vector<non_copyable> b; std::vector<non_copyable> b;
test() : b() {} test()
: b() {
}
test(test&&) = default; test(test&&) = default;
test& operator=(test&&) = default; test& operator=(test&&) = default;
test(const test&) = delete; test(const test&) = delete;
@ -713,8 +704,7 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
SECTION("normal") { SECTION("normal") {
sol::state lua; sol::state lua;
lua.new_usertype<test>("test", lua.new_usertype<test>("test",
"b", sol::readonly(&test::b) "b", sol::readonly(&test::b));
);
lua["v"] = std::vector<non_copyable>{}; lua["v"] = std::vector<non_copyable>{};
@ -724,9 +714,8 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
SECTION("simple") { SECTION("simple") {
sol::state lua; sol::state lua;
lua.new_simple_usertype<test>("test", lua.new_simple_usertype<test>("test",
"b", sol::readonly(&test::b) "b", sol::readonly(&test::b));
);
lua["v"] = std::vector<non_copyable>{}; lua["v"] = std::vector<non_copyable>{};
auto pfr = lua.safe_script("t = test.new()\nt.b = v", sol::script_pass_on_error); auto pfr = lua.safe_script("t = test.new()\nt.b = v", sol::script_pass_on_error);
@ -734,15 +723,18 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers
} }
} }
TEST_CASE("containers/input iterators", "test shitty input iterators that are all kinds of B L E H") { TEST_CASE("containers/input iterators", "test shitty input iterators that are all kinds of B L E H") {
class int_shim { class int_shim {
public: public:
int_shim() = default; int_shim() = default;
int_shim(int x) : x_(x) {} int_shim(int x)
: x_(x) {
}
int val() const { return x_; } int val() const {
return x_;
}
private: private:
int x_ = -1; int x_ = -1;
@ -752,7 +744,8 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al
public: public:
input_it() = default; input_it() = default;
input_it(int n, int m) : n_(n), m_(m), value_(n_) { input_it(int n, int m)
: n_(n), m_(m), value_(n_) {
assert(n_ >= 0); assert(n_ >= 0);
assert(m_ >= 0); assert(m_ >= 0);
assert(n_ <= m_); assert(n_ <= m_);
@ -764,11 +757,15 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al
} }
} }
const int_shim &operator*() const { return value_; } const int_shim& operator*() const {
return value_;
}
const int_shim *operator->() const { return &value_; } const int_shim* operator->() const {
return &value_;
}
input_it &operator++() { input_it& operator++() {
assert(n_ >= 0); assert(n_ >= 0);
assert(m_ >= 0); assert(m_ >= 0);
if (n_ == m_ - 1) { if (n_ == m_ - 1) {
@ -781,9 +778,13 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al
return *this; return *this;
} }
bool operator==(const input_it &i) const { return n_ == i.n_ && m_ == i.m_; } bool operator==(const input_it& i) const {
return n_ == i.n_ && m_ == i.m_;
}
bool operator!=(const input_it &i) const { return !(*this == i); } bool operator!=(const input_it& i) const {
return !(*this == i);
}
private: private:
int n_ = -1; int n_ = -1;
@ -797,21 +798,27 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al
using iterator = input_it; using iterator = input_it;
using const_iterator = input_it; using const_iterator = input_it;
const_iterator begin() const { return iterator(0, 100); } const_iterator begin() const {
return iterator(0, 100);
}
const_iterator end() const { return iterator(); } const_iterator end() const {
return iterator();
}
value_type gcc_warning_block() { value_type gcc_warning_block() {
return int_shim(); return int_shim();
} }
std::size_t size() const { return 100; } std::size_t size() const {
return 100;
}
}; };
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::package); lua.open_libraries(sol::lib::base, sol::lib::package);
lua.new_usertype<int_shim>("int_shim", lua.new_usertype<int_shim>("int_shim",
"new", sol::no_constructor, "new", sol::no_constructor,
"val", &int_shim::val); "val", &int_shim::val);
not_really_a_container c; not_really_a_container c;
@ -839,9 +846,9 @@ TEST_CASE("containers/pairs", "test how well pairs work with the underlying syst
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
std::vector<std::pair<std::string, int>> a{ { "one", 1 },{ "two", 2 },{ "three", 3 },{ "four", 4 },{ "five", 5 } }; 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 } } }; 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 } }; pair_arr_t c{ { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 }, { "five", 5 } };
arr_t d = { 1, 2, 3, 4, 5 }; arr_t d = { 1, 2, 3, 4, 5 };
lua["a"] = std::ref(a); lua["a"] = std::ref(a);

View File

@ -144,8 +144,8 @@ co = nil
std::string identifier; std::string identifier;
sol::reference obj; sol::reference obj;
co_test(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) { co_test(sol::this_state L, std::string id)
: identifier(id), obj(L, sol::lua_nil) {
} }
void store(sol::table ref) { void store(sol::table ref) {
@ -163,7 +163,6 @@ co = nil
} }
~co_test() { ~co_test() {
} }
}; };
@ -174,9 +173,7 @@ co = nil
sol::constructors<co_test(sol::this_state, std::string)>(), sol::constructors<co_test(sol::this_state, std::string)>(),
"store", &co_test::store, "store", &co_test::store,
"copy_store", &co_test::copy_store, "copy_store", &co_test::copy_store,
"get", &co_test::get "get", &co_test::get);
);
auto r = lua.safe_script(code); auto r = lua.safe_script(code);
REQUIRE(r.valid()); REQUIRE(r.valid());
@ -231,8 +228,8 @@ co = nil
std::string identifier; std::string identifier;
sol::reference obj; sol::reference obj;
co_test_implicit(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) { co_test_implicit(sol::this_state L, std::string id)
: identifier(id), obj(L, sol::lua_nil) {
} }
void store(sol::table ref) { void store(sol::table ref) {
@ -250,7 +247,6 @@ co = nil
} }
~co_test_implicit() { ~co_test_implicit() {
} }
}; };
@ -261,9 +257,7 @@ co = nil
sol::constructors<co_test_implicit(sol::this_state, std::string)>(), sol::constructors<co_test_implicit(sol::this_state, std::string)>(),
"store", &co_test_implicit::store, "store", &co_test_implicit::store,
"copy_store", &co_test_implicit::copy_store, "copy_store", &co_test_implicit::copy_store,
"get", &co_test_implicit::get "get", &co_test_implicit::get);
);
auto r = lua.safe_script(code); auto r = lua.safe_script(code);
REQUIRE(r.valid()); REQUIRE(r.valid());
@ -317,8 +311,8 @@ collectgarbage()
std::string identifier; std::string identifier;
sol::main_reference obj; sol::main_reference obj;
co_test_implicit(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) { co_test_implicit(sol::this_state L, std::string id)
: identifier(id), obj(L, sol::lua_nil) {
} }
void store(sol::table ref) { void store(sol::table ref) {
@ -340,7 +334,6 @@ collectgarbage()
} }
~co_test_implicit() { ~co_test_implicit() {
} }
}; };
@ -351,9 +344,7 @@ collectgarbage()
sol::constructors<co_test_implicit(sol::this_state, std::string)>(), sol::constructors<co_test_implicit(sol::this_state, std::string)>(),
"store", &co_test_implicit::store, "store", &co_test_implicit::store,
"copy_store", &co_test_implicit::copy_store, "copy_store", &co_test_implicit::copy_store,
"get", &co_test_implicit::get "get", &co_test_implicit::get);
);
auto r = lua.safe_script(code); auto r = lua.safe_script(code);
REQUIRE(r.valid()); REQUIRE(r.valid());

View File

@ -42,7 +42,7 @@ namespace sol {
static two_things get(lua_State* L, int index, record& tracking) { static two_things get(lua_State* L, int index, record& tracking) {
// Get the first element // Get the first element
int a = stack::get<int>(L, index); int a = stack::get<int>(L, index);
// Get the second element, // Get the second element,
// in the +1 position from the first // in the +1 position from the first
bool b = stack::get<bool>(L, index + 1); bool b = stack::get<bool>(L, index + 1);
// we use 2 slots, each of the previous takes 1 // we use 2 slots, each of the previous takes 1
@ -61,8 +61,8 @@ namespace sol {
} }
}; };
} } // namespace stack
} } // namespace sol
TEST_CASE("customization/split struct", "using the newly documented customization points to handle different kinds of classes") { TEST_CASE("customization/split struct", "using the newly documented customization points to handle different kinds of classes") {
sol::state lua; sol::state lua;
@ -80,7 +80,7 @@ TEST_CASE("customization/split struct", "using the newly documented customizatio
two_things thingsf = f(two_things{ 24, true }, 1); two_things thingsf = f(two_things{ 24, true }, 1);
two_things thingsg; two_things thingsg;
double d; double d;
sol::tie( thingsg, d ) = g(two_things{ 25, false }, 2, 34.0); sol::tie(thingsg, d) = g(two_things{ 25, false }, 2, 34.0);
REQUIRE(thingsf.a == 25); REQUIRE(thingsf.a == 25);
REQUIRE(thingsf.b); REQUIRE(thingsf.b);

View File

@ -6,7 +6,6 @@
#include <iostream> #include <iostream>
#include "test_stack_guard.hpp" #include "test_stack_guard.hpp"
TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") { TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") {
sol::state lua; sol::state lua;
sol::stack_guard luasg(lua); sol::stack_guard luasg(lua);
@ -28,11 +27,10 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f
env_g.set_on(g); env_g.set_on(g);
g(); g();
int test = env_g["test"]; int test = env_g["test"];
REQUIRE(test == 5); REQUIRE(test == 5);
sol::object global_test = lua["test"]; sol::object global_test = lua["test"];
REQUIRE(!global_test.valid()); REQUIRE(!global_test.valid());
@ -40,32 +38,29 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f
lua.set_function("check_f_env", lua.set_function("check_f_env",
[&lua, &env_f](sol::object target) { [&lua, &env_f](sol::object target) {
sol::stack_guard sg(lua); sol::stack_guard sg(lua);
sol::environment target_env(sol::env_key, target); sol::environment target_env(sol::env_key, target);
int test_env_f = env_f["test"]; int test_env_f = env_f["test"];
int test_target_env = target_env["test"]; int test_target_env = target_env["test"];
REQUIRE(test_env_f == test_target_env); REQUIRE(test_env_f == test_target_env);
REQUIRE(test_env_f == 31); REQUIRE(test_env_f == 31);
REQUIRE(env_f == target_env); REQUIRE(env_f == target_env);
} });
);
lua.set_function("check_g_env", lua.set_function("check_g_env",
[&lua, &env_g](sol::function target) { [&lua, &env_g](sol::function target) {
sol::stack_guard sg(lua); sol::stack_guard sg(lua);
sol::environment target_env = sol::get_environment(target); sol::environment target_env = sol::get_environment(target);
int test_env_g = env_g["test"]; int test_env_g = env_g["test"];
int test_target_env = target_env["test"]; int test_target_env = target_env["test"];
REQUIRE(test_env_g == test_target_env); REQUIRE(test_env_g == test_target_env);
REQUIRE(test_env_g == 5); REQUIRE(test_env_g == 5);
REQUIRE(env_g == target_env); REQUIRE(env_g == target_env);
} });
);
lua.set_function("check_h_env", lua.set_function("check_h_env",
[&lua](sol::function target) { [&lua](sol::function target) {
sol::stack_guard sg(lua); sol::stack_guard sg(lua);
sol::environment target_env = sol::get_environment(target); sol::environment target_env = sol::get_environment(target);
} });
);
REQUIRE_NOTHROW([&lua]() { REQUIRE_NOTHROW([&lua]() {
lua.safe_script("check_f_env(f)"); lua.safe_script("check_f_env(f)");
@ -86,7 +81,7 @@ TEST_CASE("environments/shadowing", "Environments can properly shadow and fallba
sol::optional<int> maybe_global_a = lua["a"]; sol::optional<int> maybe_global_a = lua["a"];
sol::optional<int> maybe_env_b = plain_env["b"]; sol::optional<int> maybe_env_b = plain_env["b"];
sol::optional<int> maybe_global_b = lua["b"]; sol::optional<int> maybe_global_b = lua["b"];
REQUIRE(maybe_env_a != sol::nullopt); REQUIRE(maybe_env_a != sol::nullopt);
REQUIRE(maybe_env_a.value() == 24); REQUIRE(maybe_env_a.value() == 24);
REQUIRE(maybe_env_b == sol::nullopt); REQUIRE(maybe_env_b == sol::nullopt);
@ -205,7 +200,7 @@ TEST_CASE("environments/functions", "see if environments on functions are workin
TEST_CASE("environments/this_environment", "test various situations of pulling out an environment") { TEST_CASE("environments/this_environment", "test various situations of pulling out an environment") {
static std::string code = "return (f(10))"; static std::string code = "return (f(10))";
sol::state lua; sol::state lua;
lua["f"] = [](sol::this_environment te, int x, sol::this_state ts) { lua["f"] = [](sol::this_environment te, int x, sol::this_state ts) {
@ -216,7 +211,7 @@ TEST_CASE("environments/this_environment", "test various situations of pulling o
sol::state_view lua = ts; sol::state_view lua = ts;
return x + static_cast<int>(lua["x"]); return x + static_cast<int>(lua["x"]);
}; };
sol::environment e(lua, sol::create, lua.globals()); sol::environment e(lua, sol::create, lua.globals());
lua["x"] = 5; lua["x"] = 5;
e["x"] = 20; e["x"] = 20;

View File

@ -33,8 +33,7 @@ TEST_CASE("filters/self", "ensure we return a direct reference to the lua userda
lua.new_usertype<vec2>("vec2", lua.new_usertype<vec2>("vec2",
"x", &vec2::x, "x", &vec2::x,
"y", &vec2::y, "y", &vec2::y,
"normalize", sol::filters(&vec2::normalize, sol::returns_self()) "normalize", sol::filters(&vec2::normalize, sol::returns_self()));
);
REQUIRE_NOTHROW([&]() { REQUIRE_NOTHROW([&]() {
lua.safe_script(R"( lua.safe_script(R"(
v1 = vec2.new() v1 = vec2.new()
@ -47,7 +46,7 @@ assert(rawequal(v1, v2))
v1 = nil v1 = nil
collectgarbage() collectgarbage()
print(v2) -- v2 points to same, is not destroyed print(v2) -- v2 points to same, is not destroyed
)"); )");
}()); }());
} }
@ -60,7 +59,8 @@ TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance ali
struct dep { struct dep {
int value = 20; int value = 20;
~dep() { ~dep() {
std::cout << "\t" << "[C++] ~dep" << std::endl; std::cout << "\t"
<< "[C++] ~dep" << std::endl;
value = std::numeric_limits<int>::max(); value = std::numeric_limits<int>::max();
deps_destroyed.push_back(this); deps_destroyed.push_back(this);
} }
@ -71,7 +71,8 @@ TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance ali
dep d; dep d;
~gc_test() { ~gc_test() {
std::cout << "\t" << "[C++] ~gc_test" << std::endl; std::cout << "\t"
<< "[C++] ~gc_test" << std::endl;
gc_tests_destroyed.push_back(this); gc_tests_destroyed.push_back(this);
} }
}; };
@ -82,15 +83,13 @@ TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance ali
lua.new_usertype<dep>("dep", lua.new_usertype<dep>("dep",
"value", &dep::value, "value", &dep::value,
sol::meta_function::to_string, [](dep& d) { sol::meta_function::to_string, [](dep& d) {
return "{ " + std::to_string(d.value) + " }"; return "{ " + std::to_string(d.value) + " }";
} });
);
lua.new_usertype<gc_test>("gc_test", lua.new_usertype<gc_test>("gc_test",
"d", sol::filters(&gc_test::d, sol::self_dependency()), "d", sol::filters(&gc_test::d, sol::self_dependency()),
sol::meta_function::to_string, [](gc_test& g) { sol::meta_function::to_string, [](gc_test& g) {
return "{ d: { " + std::to_string(g.d.value) + " } }"; return "{ d: { " + std::to_string(g.d.value) + " } }";
} });
);
lua.safe_script(R"( lua.safe_script(R"(
g = gc_test.new() g = gc_test.new()
@ -157,7 +156,9 @@ TEST_CASE("filters/stack_dependencies", "ensure we can take dependencies even to
std::reference_wrapper<holder> href; std::reference_wrapper<holder> href;
composition_related comp; composition_related comp;
depends_on_reference(holder& h) : href(h) {} depends_on_reference(holder& h)
: href(h) {
}
~depends_on_reference() { ~depends_on_reference() {
std::cout << "[C++] ~depends_on_reference" << std::endl; std::cout << "[C++] ~depends_on_reference" << std::endl;
@ -169,12 +170,10 @@ TEST_CASE("filters/stack_dependencies", "ensure we can take dependencies even to
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<holder>("holder", lua.new_usertype<holder>("holder",
"value", &holder::value "value", &holder::value);
);
lua.new_usertype<depends_on_reference>("depends_on_reference", lua.new_usertype<depends_on_reference>("depends_on_reference",
"new", sol::filters(sol::constructors<depends_on_reference(holder&)>(), sol::stack_dependencies(-1, 1)), "new", sol::filters(sol::constructors<depends_on_reference(holder&)>(), sol::stack_dependencies(-1, 1)),
"comp", &depends_on_reference::comp "comp", &depends_on_reference::comp);
);
lua.safe_script(R"( lua.safe_script(R"(
h = holder.new() h = holder.new()

View File

@ -33,7 +33,10 @@ void takefn(std::function<int()> purr) {
} }
struct A { struct A {
int a = 0xA; int bark() { return 1; } int a = 0xA;
int bark() {
return 1;
}
}; };
std::tuple<int, int> bark(int num_value, A* a) { std::tuple<int, int> bark(int num_value, A* a) {
@ -75,7 +78,7 @@ namespace sep {
INFO(x << " " << y << " " << z); INFO(x << " " << y << " " << z);
return 11; return 11;
} }
} } // namespace sep
int func_1(int) { int func_1(int) {
return 1; return 1;
@ -90,11 +93,14 @@ int func_2(int, int) {
} }
void func_3(int, int, int) { void func_3(int, int, int) {
} }
int f1(int) { return 32; } int f1(int) {
int f2(int, int) { return 1; } return 32;
}
int f2(int, int) {
return 1;
}
struct fer { struct fer {
double f3(int, int) { double f3(int, int) {
return 2.5; return 2.5;
@ -262,16 +268,14 @@ TEST_CASE("functions/sol::function to std::function", "check if conversion to st
lua.set_function("testFunc", test_free_func); lua.set_function("testFunc", test_free_func);
lua.set_function("testFunc2", test_free_func2); lua.set_function("testFunc2", test_free_func2);
lua.safe_script( lua.safe_script(
"testFunc(function() print(\"hello std::function\") end)" "testFunc(function() print(\"hello std::function\") end)");
);
REQUIRE_NOTHROW(lua.safe_script( REQUIRE_NOTHROW(lua.safe_script(
"function m(a)\n" "function m(a)\n"
" print(\"hello std::function with arg \", a)\n" " print(\"hello std::function with arg \", a)\n"
" return a\n" " return a\n"
"end\n" "end\n"
"\n" "\n"
"testFunc2(m, 1)" "testFunc2(m, 1)"));
));
} }
TEST_CASE("functions/returning functions from C++", "check to see if returning a functor and getting a functor from lua is possible") { TEST_CASE("functions/returning functions from C++", "check to see if returning a functor and getting a functor from lua is possible") {
@ -280,7 +284,8 @@ TEST_CASE("functions/returning functions from C++", "check to see if returning a
lua.set_function("makefn", makefn); lua.set_function("makefn", makefn);
lua.set_function("takefn", takefn); lua.set_function("takefn", takefn);
lua.safe_script("afx = makefn()\n" lua.safe_script(
"afx = makefn()\n"
"print(afx())\n" "print(afx())\n"
"takefn(afx)\n"); "takefn(afx)\n");
} }
@ -314,8 +319,7 @@ TEST_CASE("functions/function_result and protected_function_result", "Function r
std::string("function luahandler ( message )") std::string("function luahandler ( message )")
+ " print('lua handler called with: ' .. message)" + " print('lua handler called with: ' .. message)"
+ " return '" + handlederrormessage + "'" + " return '" + handlederrormessage + "'"
+ "end" + "end");
);
auto nontrampolinefx = [](lua_State*) -> int { throw "x"; }; auto nontrampolinefx = [](lua_State*) -> int { throw "x"; };
lua_CFunction c_nontrampolinefx = nontrampolinefx; lua_CFunction c_nontrampolinefx = nontrampolinefx;
lua.set("nontrampoline", c_nontrampolinefx); lua.set("nontrampoline", c_nontrampolinefx);
@ -433,11 +437,9 @@ TEST_CASE("functions/all kinds", "Register all kinds of functions, make sure the
auto d = []() { return 503; }; auto d = []() { return 503; };
lua.new_usertype<test_1>("test_1", lua.new_usertype<test_1>("test_1",
"bark", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem> "bark", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>);
);
lua.new_usertype<test_2>("test_2", lua.new_usertype<test_2>("test_2",
"bark", sol::c_call<decltype(&test_2::bark), &test_2::bark> "bark", sol::c_call<decltype(&test_2::bark), &test_2::bark>);
);
test_2 t2; test_2 t2;
lua.set_function("a", a); lua.set_function("a", a);
@ -473,7 +475,6 @@ I = i(o1)
I = i(o1) I = i(o1)
)"); )");
lua.safe_script(R"( lua.safe_script(R"(
J0 = j() J0 = j()
j(24) j(24)
@ -492,7 +493,6 @@ l(o1, 678)
L1 = l(o1) L1 = l(o1)
)"); )");
lua.safe_script(R"( lua.safe_script(R"(
M0 = m() M0 = m()
m(256) m(256)
@ -505,8 +505,7 @@ N = n(1, 2, 3)
int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N; int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N;
std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N)
= lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>( = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>(
"ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N");
);
REQUIRE(ob == 0xA); REQUIRE(ob == 0xA);
@ -537,8 +536,7 @@ N = n(1, 2, 3)
sol::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) sol::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N)
= lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>( = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>(
"ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N");
);
REQUIRE(ob == 0xA); REQUIRE(ob == 0xA);
@ -593,10 +591,9 @@ N = n(1, 2, 3)
{ {
auto result = lua.safe_script("v(nested, inner)", sol::script_pass_on_error); auto result = lua.safe_script("v(nested, inner)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
} }
TEST_CASE("simple/call with parameters", "Lua function is called with a few parameters from C++") { TEST_CASE("simple/call with parameters", "Lua function is called with a few parameters from C++") {
sol::state lua; sol::state lua;
@ -773,8 +770,7 @@ TEST_CASE("functions/overloading", "Check if overloading works properly for regu
"a = func(1)\n" "a = func(1)\n"
"b = func('bark')\n" "b = func('bark')\n"
"c = func(1,2)\n" "c = func(1,2)\n"
"func(1,2,3)\n" "func(1,2,3)\n"));
));
REQUIRE((lua["a"] == 1)); REQUIRE((lua["a"] == 1));
REQUIRE((lua["b"] == string_bark)); REQUIRE((lua["b"] == string_bark));
@ -842,13 +838,11 @@ TEST_CASE("functions/stack atomic", "make sure functions don't impede on the sta
sol::stack_guard opsg(lua); sol::stack_guard opsg(lua);
sol::optional<std::string> opt_result = Stringtest("optional test"); sol::optional<std::string> opt_result = Stringtest("optional test");
REQUIRE(opsg.check_stack()); REQUIRE(opsg.check_stack());
if (opt_result) if (opt_result) {
{
std::string s = opt_result.value(); std::string s = opt_result.value();
INFO("Back in C++, opt_result is : " << s); INFO("Back in C++, opt_result is : " << s);
} }
else else {
{
INFO("opt_result failed"); INFO("opt_result failed");
} }
} }
@ -1017,7 +1011,7 @@ TEST_CASE("functions/set_function already wrapped", "setting a function returned
sol::function fn = lua.safe_script("return function() return 5 end"); sol::function fn = lua.safe_script("return function() return 5 end");
sol::protected_function pfn = fn; sol::protected_function pfn = fn;
std::function<int()> sfn = fn; std::function<int()> sfn = fn;
lua.set_function("test", fn); lua.set_function("test", fn);
lua.set_function("test2", pfn); lua.set_function("test2", pfn);
lua.set_function("test3", sfn); lua.set_function("test3", sfn);
@ -1054,7 +1048,6 @@ TEST_CASE("functions/set_function already wrapped", "setting a function returned
REQUIRE_NOTHROW(lua.safe_script("assert(type(test) == 'function')")); REQUIRE_NOTHROW(lua.safe_script("assert(type(test) == 'function')"));
REQUIRE_NOTHROW(lua.safe_script("assert(test() ~= nil)")); REQUIRE_NOTHROW(lua.safe_script("assert(test() ~= nil)"));
REQUIRE_NOTHROW(lua.safe_script("assert(test() == 5)")); REQUIRE_NOTHROW(lua.safe_script("assert(test() == 5)"));
} }
SECTION("does the function actually get executed?") { SECTION("does the function actually get executed?") {
@ -1094,7 +1087,7 @@ TEST_CASE("functions/pointer nullptr + nil", "ensure specific semantics for hand
REQUIRE(p == nullptr); REQUIRE(p == nullptr);
} }
}; };
std::shared_ptr<nil_test> sptr; std::shared_ptr<nil_test> sptr;
std::unique_ptr<nil_test> uptr; std::unique_ptr<nil_test> uptr;
std::unique_ptr<nil_test> ruptr; std::unique_ptr<nil_test> ruptr;
@ -1256,10 +1249,14 @@ TEST_CASE("functions/pointer nullptr + nil", "ensure specific semantics for hand
} }
TEST_CASE("functions/unique_usertype overloading", "make sure overloading can work with ptr vs. specifically asking for a unique_usertype") { TEST_CASE("functions/unique_usertype overloading", "make sure overloading can work with ptr vs. specifically asking for a unique_usertype") {
struct test { struct test {
int special_value = 17; int special_value = 17;
test() : special_value(17) {} test()
test(int special_value) : special_value(special_value) {} : special_value(17) {
}
test(int special_value)
: special_value(special_value) {
}
}; };
auto print_up_test = [](std::unique_ptr<test>& x) { auto print_up_test = [](std::unique_ptr<test>& x) {
REQUIRE(x->special_value == 21); REQUIRE(x->special_value == 21);
@ -1281,17 +1278,13 @@ TEST_CASE("functions/unique_usertype overloading", "make sure overloading can wo
}; };
using f_t = void(test&); using f_t = void(test&);
f_t* fptr = print_ref_test; f_t* fptr = print_ref_test;
std::unique_ptr<test> ut = std::make_unique<test>(17); std::unique_ptr<test> ut = std::make_unique<test>(17);
SECTION("working") { SECTION("working") {
sol::state lua; sol::state lua;
lua.set_function("f", print_up_test); lua.set_function("f", print_up_test);
lua.set_function("g", sol::overload( lua.set_function("g", sol::overload(std::move(print_sp_test), print_up_test, std::ref(print_ptr_test)));
std::move(print_sp_test),
print_up_test,
std::ref(print_ptr_test)
));
lua.set_function("h", std::ref(fptr)); lua.set_function("h", std::ref(fptr));
lua.set_function("i", std::move(print_up_2_test)); lua.set_function("i", std::move(print_up_2_test));
@ -1350,15 +1343,15 @@ TEST_CASE("functions/noexcept", "allow noexcept functions to be serialized prope
return 0x61; return 0x61;
} }
int noexcept_method() noexcept { int noexcept_method() noexcept {
return 0x62; return 0x62;
} }
} t; } t;
lua_CFunction ccall = sol::c_call<decltype(&raw_noexcept_function), &raw_noexcept_function>; lua_CFunction ccall = sol::c_call<decltype(&raw_noexcept_function), &raw_noexcept_function>;
sol::state lua; sol::state lua;
lua.set_function("f", &T::noexcept_function); lua.set_function("f", &T::noexcept_function);
lua.set_function("g", &T::noexcept_method); lua.set_function("g", &T::noexcept_method);
lua.set_function("h", &T::noexcept_method, T()); lua.set_function("h", &T::noexcept_method, T());

View File

@ -70,12 +70,18 @@ TEST_CASE("gc/virtual destructors", "ensure types with virtual destructions beha
class A { class A {
public: public:
virtual ~A() { as.push_back(this); std::cout << "~A" << std::endl; } virtual ~A() {
as.push_back(this);
std::cout << "~A" << std::endl;
}
}; };
class B : public A { class B : public A {
public: public:
virtual ~B() { bs.push_back(this); std::cout << "~B" << std::endl; } virtual ~B() {
bs.push_back(this);
std::cout << "~B" << std::endl;
}
}; };
{ {
@ -99,7 +105,9 @@ TEST_CASE("gc/function argument storage", "ensure functions take references on t
class gc_entity { class gc_entity {
public: public:
~gc_entity() { entities.push_back(this); } ~gc_entity() {
entities.push_back(this);
}
}; };
SECTION("plain") { SECTION("plain") {
entities.clear(); entities.clear();
@ -115,18 +123,17 @@ end
gc_entity e; gc_entity e;
target = &e; target = &e;
{ {
f(e); // same with std::ref(e)! f(e); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
{ {
f(&e); // same with std::ref(e)! f(&e); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
{ {
f(std::ref(e)); // same with std::ref(e)! f(std::ref(e)); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
} }
REQUIRE(entities.size() == 1); REQUIRE(entities.size() == 1);
REQUIRE(entities.back() == target); REQUIRE(entities.back() == target);
@ -146,18 +153,17 @@ end
gc_entity e; gc_entity e;
target = &e; target = &e;
{ {
f(e); // same with std::ref(e)! f(e); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
{ {
f(&e); // same with std::ref(e)! f(&e); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
{ {
f(std::ref(e)); // same with std::ref(e)! f(std::ref(e)); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
} }
REQUIRE(entities.size() == 1); REQUIRE(entities.size() == 1);
REQUIRE(entities.back() == target); REQUIRE(entities.back() == target);
@ -177,50 +183,80 @@ end
gc_entity e; gc_entity e;
target = &e; target = &e;
{ {
f(e); // same with std::ref(e)! f(e); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
{ {
f(&e); // same with std::ref(e)! f(&e); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
{ {
f(std::ref(e)); // same with std::ref(e)! f(std::ref(e)); // same with std::ref(e)!
lua.collect_garbage(); // destroys e for some reason lua.collect_garbage(); // destroys e for some reason
} }
} }
REQUIRE(entities.size() == 1); REQUIRE(entities.size() == 1);
REQUIRE(entities.back() == target); REQUIRE(entities.back() == target);
} }
} }
TEST_CASE("gc/function storage", "show that proper copies / destruction happens for function storage (or not)") { TEST_CASE("gc/function storage", "show that proper copies / destruction happens for function storage (or not)") {
static int created = 0; static int created = 0;
static int destroyed = 0; static int destroyed = 0;
static void* last_call = nullptr; static void* last_call = nullptr;
static void* static_call = reinterpret_cast<void*>(0x01); static void* static_call = reinterpret_cast<void*>(0x01);
typedef void(*fptr)(); typedef void (*fptr)();
struct x { struct x {
x() { ++created; } x() {
x(const x&) { ++created; } ++created;
x(x&&) { ++created; } }
x& operator=(const x&) { return *this; } x(const x&) {
x& operator=(x&&) { return *this; } ++created;
void func() { last_call = static_cast<void*>(this); }; }
~x() { ++destroyed; } x(x&&) {
++created;
}
x& operator=(const x&) {
return *this;
}
x& operator=(x&&) {
return *this;
}
void func() {
last_call = static_cast<void*>(this);
};
~x() {
++destroyed;
}
}; };
struct y { struct y {
y() { ++created; } y() {
y(const x&) { ++created; } ++created;
y(x&&) { ++created; } }
y& operator=(const x&) { return *this; } y(const x&) {
y& operator=(x&&) { return *this; } ++created;
static void func() { last_call = static_call; }; }
void operator()() { func(); } y(x&&) {
operator fptr () { return func; } ++created;
~y() { ++destroyed; } }
y& operator=(const x&) {
return *this;
}
y& operator=(x&&) {
return *this;
}
static void func() {
last_call = static_call;
};
void operator()() {
func();
}
operator fptr() {
return func;
}
~y() {
++destroyed;
}
}; };
// stateful functors/member functions should always copy unless specified // stateful functors/member functions should always copy unless specified
@ -274,7 +310,6 @@ TEST_CASE("gc/function storage", "show that proper copies / destruction happens
} }
} }
TEST_CASE("gc/same type closures", "make sure destructions are per-object, not per-type, by destroying one type multiple times") { TEST_CASE("gc/same type closures", "make sure destructions are per-object, not per-type, by destroying one type multiple times") {
static std::set<void*> last_my_closures; static std::set<void*> last_my_closures;
static bool checking_closures = false; static bool checking_closures = false;
@ -283,7 +318,9 @@ TEST_CASE("gc/same type closures", "make sure destructions are per-object, not p
struct my_closure { struct my_closure {
int& n; int& n;
my_closure(int& n) : n(n) {} my_closure(int& n)
: n(n) {
}
~my_closure() noexcept(false) { ~my_closure() noexcept(false) {
if (!checking_closures) if (!checking_closures)
return; return;
@ -295,8 +332,9 @@ TEST_CASE("gc/same type closures", "make sure destructions are per-object, not p
last_my_closures.insert(f, addr); last_my_closures.insert(f, addr);
} }
int operator() () { int operator()() {
++n; return n; ++n;
return n;
} }
}; };
@ -318,12 +356,24 @@ TEST_CASE("gc/usertypes", "show that proper copies / destruction happens for use
static int created = 0; static int created = 0;
static int destroyed = 0; static int destroyed = 0;
struct x { struct x {
x() { ++created; } x() {
x(const x&) { ++created; } ++created;
x(x&&) { ++created; } }
x& operator=(const x&) { return *this; } x(const x&) {
x& operator=(x&&) { return *this; } ++created;
~x() { ++destroyed; } }
x(x&&) {
++created;
}
x& operator=(const x&) {
return *this;
}
x& operator=(x&&) {
return *this;
}
~x() {
++destroyed;
}
}; };
SECTION("plain") { SECTION("plain") {
created = 0; created = 0;
@ -392,8 +442,12 @@ TEST_CASE("gc/usertypes", "show that proper copies / destruction happens for use
TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destructed and don't double-delete memory or segfault") { TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destructed and don't double-delete memory or segfault") {
class crash_class { class crash_class {
public: public:
crash_class() {} crash_class() {
~crash_class() { a = 10; } }
~crash_class() {
a = 10;
}
private: private:
int a; int a;
}; };
@ -402,8 +456,7 @@ TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destruct
SECTION("regular") { SECTION("regular") {
lua.new_usertype<crash_class>("CrashClass", lua.new_usertype<crash_class>("CrashClass",
sol::call_constructor, sol::constructors<sol::types<>>() sol::call_constructor, sol::constructors<sol::types<>>());
);
lua.safe_script(R"( lua.safe_script(R"(
function testCrash() function testCrash()
@ -417,8 +470,7 @@ TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destruct
} }
SECTION("simple") { SECTION("simple") {
lua.new_simple_usertype<crash_class>("CrashClass", lua.new_simple_usertype<crash_class>("CrashClass",
sol::call_constructor, sol::constructors<sol::types<>>() sol::call_constructor, sol::constructors<sol::types<>>());
);
lua.safe_script(R"( lua.safe_script(R"(
function testCrash() function testCrash()
@ -455,10 +507,9 @@ TEST_CASE("gc/shared_ptr regression", "metatables should not screw over unique u
lua.new_usertype<test>("test", lua.new_usertype<test>("test",
"create", [&]() -> std::shared_ptr<test> { "create", [&]() -> std::shared_ptr<test> {
tests.push_back(std::make_shared<test>()); tests.push_back(std::make_shared<test>());
return tests.back(); return tests.back();
} });
);
REQUIRE(created == 0); REQUIRE(created == 0);
REQUIRE(destroyed == 0); REQUIRE(destroyed == 0);
lua.safe_script("x = test.create()"); lua.safe_script("x = test.create()");
@ -483,10 +534,9 @@ TEST_CASE("gc/shared_ptr regression", "metatables should not screw over unique u
lua.new_simple_usertype<test>("test", lua.new_simple_usertype<test>("test",
"create", [&]() -> std::shared_ptr<test> { "create", [&]() -> std::shared_ptr<test> {
tests.push_back(std::make_shared<test>()); tests.push_back(std::make_shared<test>());
return tests.back(); return tests.back();
} });
);
REQUIRE(created == 0); REQUIRE(created == 0);
REQUIRE(destroyed == 0); REQUIRE(destroyed == 0);
lua.safe_script("x = test.create()"); lua.safe_script("x = test.create()");
@ -505,8 +555,12 @@ TEST_CASE("gc/shared_ptr regression", "metatables should not screw over unique u
TEST_CASE("gc/double deleter guards", "usertype metatables internally must not rely on C++ state") { TEST_CASE("gc/double deleter guards", "usertype metatables internally must not rely on C++ state") {
SECTION("regular") { SECTION("regular") {
struct c_a { int xv; }; struct c_a {
struct c_b { int yv; }; int xv;
};
struct c_b {
int yv;
};
auto routine = []() { auto routine = []() {
sol::state lua; sol::state lua;
lua.new_usertype<c_a>("c_a", "x", &c_a::xv); lua.new_usertype<c_a>("c_a", "x", &c_a::xv);
@ -519,8 +573,12 @@ TEST_CASE("gc/double deleter guards", "usertype metatables internally must not r
REQUIRE_NOTHROW(routine()); REQUIRE_NOTHROW(routine());
} }
SECTION("simple") { SECTION("simple") {
struct sc_a { int xv; }; struct sc_a {
struct sc_b { int yv; }; int xv;
};
struct sc_b {
int yv;
};
auto routine = []() { auto routine = []() {
sol::state lua; sol::state lua;
lua.new_simple_usertype<sc_a>("c_a", "x", &sc_a::xv); lua.new_simple_usertype<sc_a>("c_a", "x", &sc_a::xv);

View File

@ -28,19 +28,15 @@ TEST_CASE("inheritance/basic", "test that metatables are properly inherited") {
sol::state lua; sol::state lua;
lua.new_usertype<A>("A", lua.new_usertype<A>("A",
"a", &A::a "a", &A::a);
);
lua.new_usertype<B>("B", lua.new_usertype<B>("B",
"b", &B::b "b", &B::b);
);
lua.new_usertype<C>("C", lua.new_usertype<C>("C",
"c", &C::c, "c", &C::c,
sol::base_classes, sol::bases<B, A>() sol::base_classes, sol::bases<B, A>());
);
lua.new_usertype<D>("D", lua.new_usertype<D>("D",
"d", &D::d, "d", &D::d,
sol::base_classes, sol::bases<C, B, A>() sol::base_classes, sol::bases<C, B, A>());
);
lua.safe_script("obj = D.new()"); lua.safe_script("obj = D.new()");
lua.safe_script("d = obj:d()"); lua.safe_script("d = obj:d()");
@ -61,32 +57,52 @@ TEST_CASE("inheritance/basic", "test that metatables are properly inherited") {
TEST_CASE("inheritance/multi base", "test that multiple bases all work and overloading for constructors works with them") { TEST_CASE("inheritance/multi base", "test that multiple bases all work and overloading for constructors works with them") {
class TestClass00 { class TestClass00 {
public: public:
int Thing() const { return 123; } int Thing() const {
return 123;
}
}; };
class TestClass01 : public TestClass00 { class TestClass01 : public TestClass00 {
public: public:
TestClass01() : a(1) {} TestClass01()
TestClass01(const TestClass00& other) : a(other.Thing()) {} : a(1) {
}
TestClass01(const TestClass00& other)
: a(other.Thing()) {
}
int a; int a;
}; };
class TestClass02 : public TestClass01 { class TestClass02 : public TestClass01 {
public: public:
TestClass02() : b(2) {} TestClass02()
TestClass02(const TestClass01& other) : b(other.a) {} : b(2) {
TestClass02(const TestClass00& other) : b(other.Thing()) {} }
TestClass02(const TestClass01& other)
: b(other.a) {
}
TestClass02(const TestClass00& other)
: b(other.Thing()) {
}
int b; int b;
}; };
class TestClass03 : public TestClass02 { class TestClass03 : public TestClass02 {
public: public:
TestClass03() : c(2) {} TestClass03()
TestClass03(const TestClass02& other) : c(other.b) {} : c(2) {
TestClass03(const TestClass01& other) : c(other.a) {} }
TestClass03(const TestClass00& other) : c(other.Thing()) {} TestClass03(const TestClass02& other)
: c(other.b) {
}
TestClass03(const TestClass01& other)
: c(other.a) {
}
TestClass03(const TestClass00& other)
: c(other.Thing()) {
}
int c; int c;
}; };
@ -95,32 +111,28 @@ TEST_CASE("inheritance/multi base", "test that multiple bases all work and overl
sol::usertype<TestClass00> s_TestUsertype00( sol::usertype<TestClass00> s_TestUsertype00(
sol::call_constructor, sol::constructors<sol::types<>>(), sol::call_constructor, sol::constructors<sol::types<>>(),
"Thing", &TestClass00::Thing "Thing", &TestClass00::Thing);
);
lua.set_usertype("TestClass00", s_TestUsertype00); lua.set_usertype("TestClass00", s_TestUsertype00);
sol::usertype<TestClass01> s_TestUsertype01( sol::usertype<TestClass01> s_TestUsertype01(
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(),
sol::base_classes, sol::bases<TestClass00>(), sol::base_classes, sol::bases<TestClass00>(),
"a", &TestClass01::a "a", &TestClass01::a);
);
lua.set_usertype("TestClass01", s_TestUsertype01); lua.set_usertype("TestClass01", s_TestUsertype01);
sol::usertype<TestClass02> s_TestUsertype02( sol::usertype<TestClass02> s_TestUsertype02(
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
sol::base_classes, sol::bases<TestClass01, TestClass00>(), sol::base_classes, sol::bases<TestClass01, TestClass00>(),
"b", &TestClass02::b "b", &TestClass02::b);
);
lua.set_usertype("TestClass02", s_TestUsertype02); lua.set_usertype("TestClass02", s_TestUsertype02);
sol::usertype<TestClass03> s_TestUsertype03( sol::usertype<TestClass03> s_TestUsertype03(
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(), sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(),
"c", &TestClass03::c "c", &TestClass03::c);
);
lua.set_usertype("TestClass03", s_TestUsertype03); lua.set_usertype("TestClass03", s_TestUsertype03);
@ -156,66 +168,82 @@ tc3 = TestClass03(tc1)
TEST_CASE("inheritance/simple multi base", "test that multiple bases all work and overloading for constructors works with them") { TEST_CASE("inheritance/simple multi base", "test that multiple bases all work and overloading for constructors works with them") {
class TestClass00 { class TestClass00 {
public: public:
int Thing() const { return 123; } int Thing() const {
return 123;
}
}; };
class TestClass01 : public TestClass00 { class TestClass01 : public TestClass00 {
public: public:
TestClass01() : a(1) {} TestClass01()
TestClass01(const TestClass00& other) : a(other.Thing()) {} : a(1) {
}
TestClass01(const TestClass00& other)
: a(other.Thing()) {
}
int a; int a;
}; };
class TestClass02 : public TestClass01 { class TestClass02 : public TestClass01 {
public: public:
TestClass02() : b(2) {} TestClass02()
TestClass02(const TestClass01& other) : b(other.a) {} : b(2) {
TestClass02(const TestClass00& other) : b(other.Thing()) {} }
TestClass02(const TestClass01& other)
: b(other.a) {
}
TestClass02(const TestClass00& other)
: b(other.Thing()) {
}
int b; int b;
}; };
class TestClass03 : public TestClass02 { class TestClass03 : public TestClass02 {
public: public:
TestClass03() : c(2) {} TestClass03()
TestClass03(const TestClass02& other) : c(other.b) {} : c(2) {
TestClass03(const TestClass01& other) : c(other.a) {} }
TestClass03(const TestClass00& other) : c(other.Thing()) {} TestClass03(const TestClass02& other)
: c(other.b) {
}
TestClass03(const TestClass01& other)
: c(other.a) {
}
TestClass03(const TestClass00& other)
: c(other.Thing()) {
}
int c; int c;
}; };
sol::state lua; sol::state lua;
sol::simple_usertype<TestClass00> s_TestUsertype00( lua, sol::simple_usertype<TestClass00> s_TestUsertype00(lua,
sol::call_constructor, sol::constructors<sol::types<>>(), sol::call_constructor, sol::constructors<sol::types<>>(),
"Thing", &TestClass00::Thing "Thing", &TestClass00::Thing);
);
lua.set_usertype("TestClass00", s_TestUsertype00); lua.set_usertype("TestClass00", s_TestUsertype00);
sol::simple_usertype<TestClass01> s_TestUsertype01( lua, sol::simple_usertype<TestClass01> s_TestUsertype01(lua,
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(),
sol::base_classes, sol::bases<TestClass00>(), sol::base_classes, sol::bases<TestClass00>(),
"a", &TestClass01::a "a", &TestClass01::a);
);
lua.set_usertype("TestClass01", s_TestUsertype01); lua.set_usertype("TestClass01", s_TestUsertype01);
sol::simple_usertype<TestClass02> s_TestUsertype02( lua, sol::simple_usertype<TestClass02> s_TestUsertype02(lua,
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
sol::base_classes, sol::bases<TestClass01, TestClass00>(), sol::base_classes, sol::bases<TestClass01, TestClass00>(),
"b", &TestClass02::b "b", &TestClass02::b);
);
lua.set_usertype("TestClass02", s_TestUsertype02); lua.set_usertype("TestClass02", s_TestUsertype02);
sol::simple_usertype<TestClass03> s_TestUsertype03( lua, sol::simple_usertype<TestClass03> s_TestUsertype03(lua,
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(), sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(),
"c", &TestClass03::c "c", &TestClass03::c);
);
lua.set_usertype("TestClass03", s_TestUsertype03); lua.set_usertype("TestClass03", s_TestUsertype03);

View File

@ -60,7 +60,7 @@ TEST_CASE("large_integer/unsigned64", "pass too large unsigned 64bit value to lu
lua.set_function("f", [&](T num) -> T { lua.set_function("f", [&](T num) -> T {
return num; return num;
}); });
REQUIRE_THROWS([&lua](){ REQUIRE_THROWS([&lua]() {
sol::protected_function pf = lua["f"]; sol::protected_function pf = lua["f"];
auto result = pf(0xFFFFFFFFFFFFFFFFull); auto result = pf(0xFFFFFFFFFFFFFFFFull);
}()); }());
@ -72,7 +72,7 @@ TEST_CASE("large_integer/double", "pass negative and large positive values as si
lua.set_function("s32", [&](std::int32_t num) { lua.set_function("s32", [&](std::int32_t num) {
return num; return num;
}); });
lua.set_function("s64", [&](std::int64_t num) { lua.set_function("s64", [&](std::int64_t num) {
return num; return num;
}); });
lua.set_function("u32", [&](std::uint32_t num) { lua.set_function("u32", [&](std::uint32_t num) {

View File

@ -12,14 +12,18 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor
struct T {}; struct T {};
struct U { struct U {
int a; int a;
U(int x = 20) : a(x) {} U(int x = 20)
: a(x) {
}
bool operator==(const U& r) { bool operator==(const U& r) {
return a == r.a; return a == r.a;
} }
}; };
struct V { struct V {
int a; int a;
V(int x = 20) : a(x) {} V(int x = 20)
: a(x) {
}
bool operator==(const V& r) const { bool operator==(const V& r) const {
return a == r.a; return a == r.a;
} }
@ -170,7 +174,7 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor
TEST_CASE("operators/call", "test call operator generation") { TEST_CASE("operators/call", "test call operator generation") {
struct callable { struct callable {
int operator ()(int a, std::string b) { int operator()(int a, std::string b) {
return a + static_cast<int>(b.length()); return a + static_cast<int>(b.length());
} }
}; };
@ -211,7 +215,7 @@ struct stringable {
}; };
const void* stringable::last_print_ptr = nullptr; const void* stringable::last_print_ptr = nullptr;
std::ostream& operator<< (std::ostream& ostr, const stringable& o) { std::ostream& operator<<(std::ostream& ostr, const stringable& o) {
stringable::last_print_ptr = static_cast<const void*>(&o); stringable::last_print_ptr = static_cast<const void*>(&o);
return ostr << "{ stringable, std::ostream! }"; return ostr << "{ stringable, std::ostream! }";
} }
@ -236,7 +240,7 @@ namespace inside {
adl_stringable2::last_print_ptr = static_cast<const void*>(&o); adl_stringable2::last_print_ptr = static_cast<const void*>(&o);
return "{ inside::adl_stringable2, inside::to_string! }"; return "{ inside::adl_stringable2, inside::to_string! }";
} }
} } // namespace inside
struct member_stringable { struct member_stringable {
static const void* last_print_ptr; static const void* last_print_ptr;
@ -451,8 +455,8 @@ TEST_CASE("operators/length", "test that size is automatically bound to the leng
} }
SECTION("regular") { SECTION("regular") {
lua.new_usertype<sizable>("sizable"); lua.new_usertype<sizable>("sizable");
{ {
lua.safe_script("obj = sizable.new()"); lua.safe_script("obj = sizable.new()");
lua.safe_script("s = #obj"); lua.safe_script("s = #obj");
std::size_t s = lua["s"]; std::size_t s = lua["s"];
REQUIRE(s == 6); REQUIRE(s == 6);

View File

@ -3,7 +3,6 @@
#include <catch.hpp> #include <catch.hpp>
#include <sol.hpp> #include <sol.hpp>
TEST_CASE("issues/stack overflow", "make sure various operations repeated don't trigger stack overflow") { TEST_CASE("issues/stack overflow", "make sure various operations repeated don't trigger stack overflow") {
sol::state lua; sol::state lua;
lua.safe_script("t = {};t[0]=20"); lua.safe_script("t = {};t[0]=20");
@ -11,15 +10,16 @@ TEST_CASE("issues/stack overflow", "make sure various operations repeated don't
sol::function f = lua["lua_function"]; sol::function f = lua["lua_function"];
std::string teststring = "testtext"; std::string teststring = "testtext";
REQUIRE_NOTHROW([&]{ REQUIRE_NOTHROW([&] {
for (int i = 0; i < 1000000; ++i) { for (int i = 0; i < 1000000; ++i) {
std::string result = f(teststring); std::string result = f(teststring);
if (result != teststring) throw std::logic_error("RIP"); if (result != teststring)
throw std::logic_error("RIP");
} }
}()); }());
sol::table t = lua["t"]; sol::table t = lua["t"];
int expected = 20; int expected = 20;
REQUIRE_NOTHROW([&]{ REQUIRE_NOTHROW([&] {
for (int i = 0; i < 1000000; ++i) { for (int i = 0; i < 1000000; ++i) {
int result = t[0]; int result = t[0];
t.size(); t.size();
@ -29,7 +29,6 @@ TEST_CASE("issues/stack overflow", "make sure various operations repeated don't
}()); }());
} }
TEST_CASE("issues/stack overflow 2", "make sure basic iterators clean up properly when they're not iterated through (e.g., with empty())") { TEST_CASE("issues/stack overflow 2", "make sure basic iterators clean up properly when they're not iterated through (e.g., with empty())") {
sol::state lua; sol::state lua;
sol::table t = lua.create_table_with(1, "wut"); sol::table t = lua.create_table_with(1, "wut");

View File

@ -36,9 +36,9 @@ TEST_CASE("plain/indestructible", "test that we error for types that are innatel
i->~indestructible(); i->~indestructible();
} }
}; };
private: private:
~indestructible() { ~indestructible() {
} }
}; };
@ -61,10 +61,9 @@ TEST_CASE("plain/indestructible", "test that we error for types that are innatel
lua.new_usertype<indestructible>("indestructible", lua.new_usertype<indestructible>("indestructible",
sol::default_constructor, sol::default_constructor,
sol::meta_function::garbage_collect, sol::destructor([](indestructible& i) { sol::meta_function::garbage_collect, sol::destructor([](indestructible& i) {
indestructible::insider del; indestructible::insider del;
del(&i); del(&i);
}) }));
);
lua.safe_script("i = nil"); lua.safe_script("i = nil");
auto result = lua.safe_script("collectgarbage()", sol::script_pass_on_error); auto result = lua.safe_script("collectgarbage()", sol::script_pass_on_error);
REQUIRE(result.valid()); REQUIRE(result.valid());

View File

@ -42,12 +42,11 @@ TEST_CASE("simple_usertype/usertypes", "Ensure that simple usertypes properly wo
lua.new_simple_usertype<bark>("bark", lua.new_simple_usertype<bark>("bark",
"fun", &bark::fun, "fun", &bark::fun,
"get", &bark::get, "get", &bark::get,
"var", sol::as_function( &bark::var ), "var", sol::as_function(&bark::var),
"the_marker", sol::as_function(&bark::the_marker), "the_marker", sol::as_function(&bark::the_marker),
"x", sol::overload(&bark::get), "x", sol::overload(&bark::get),
"y", sol::overload(&bark::set), "y", sol::overload(&bark::set),
"z", sol::overload(&bark::get, &bark::set) "z", sol::overload(&bark::get, &bark::set));
);
lua.safe_script("b = bark.new()"); lua.safe_script("b = bark.new()");
bark& b = lua["b"]; bark& b = lua["b"];
@ -95,8 +94,11 @@ TEST_CASE("simple_usertype/usertype constructors", "Ensure that calls with speci
int var = 50; int var = 50;
marker mark; marker mark;
bark() {} bark() {
bark(int v) : var(v) {} }
bark(int v)
: var(v) {
}
void fun() { void fun() {
var = 51; var = 51;
@ -123,14 +125,13 @@ TEST_CASE("simple_usertype/usertype constructors", "Ensure that calls with speci
sol::state lua; sol::state lua;
lua.new_simple_usertype<bark>("bark", lua.new_simple_usertype<bark>("bark",
sol::constructors<sol::types<>, sol::types<int>>(), sol::constructors<sol::types<>, sol::types<int>>(),
"fun", sol::protect( &bark::fun ), "fun", sol::protect(&bark::fun),
"get", &bark::get, "get", &bark::get,
"var", sol::as_function( &bark::var ), "var", sol::as_function(&bark::var),
"the_marker", &bark::the_marker, "the_marker", &bark::the_marker,
"x", sol::overload(&bark::get), "x", sol::overload(&bark::get),
"y", sol::overload(&bark::set), "y", sol::overload(&bark::set),
"z", sol::overload(&bark::get, &bark::set) "z", sol::overload(&bark::get, &bark::set));
);
lua.safe_script("bx = bark.new(760)"); lua.safe_script("bx = bark.new(760)");
bark& bx = lua["bx"]; bark& bx = lua["bx"];
@ -185,9 +186,8 @@ TEST_CASE("simple_usertype/vars", "simple usertype vars can bind various values
"straight", sol::var(2), "straight", sol::var(2),
"global", sol::var(muh_variable), "global", sol::var(muh_variable),
"global2", sol::var(through_variable), "global2", sol::var(through_variable),
"global3", sol::var(std::ref(through_variable)) "global3", sol::var(std::ref(through_variable)));
);
through_variable = 20; through_variable = 20;
lua.safe_script(R"( lua.safe_script(R"(
@ -214,22 +214,28 @@ g3 = test.global3
TEST_CASE("simple_usertype/variable-control", "test to see if usertypes respond to inheritance and variable controls") { TEST_CASE("simple_usertype/variable-control", "test to see if usertypes respond to inheritance and variable controls") {
class A { class A {
public: public:
virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; virtual void a() {
throw std::runtime_error("entered base pure virtual implementation");
};
}; };
class B : public A { class B : public A {
public: public:
virtual void a() override { } virtual void a() override {
}
}; };
class sA { class sA {
public: public:
virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; virtual void a() {
throw std::runtime_error("entered base pure virtual implementation");
};
}; };
class sB : public sA { class sB : public sA {
public: public:
virtual void a() override { } virtual void a() override {
}
}; };
struct sV { struct sV {
@ -287,14 +293,18 @@ TEST_CASE("simple_usertype/variable-control", "test to see if usertypes respond
TEST_CASE("simple_usertype/factory constructor overloads", "simple usertypes should invoke the proper factories") { TEST_CASE("simple_usertype/factory constructor overloads", "simple usertypes should invoke the proper factories") {
class A { class A {
public: public:
virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; virtual void a() {
throw std::runtime_error("entered base pure virtual implementation");
};
}; };
class B : public A { class B : public A {
public: public:
int bvar = 24; int bvar = 24;
virtual void a() override { } virtual void a() override {
void f() {} }
void f() {
}
}; };
sol::state lua; sol::state lua;
@ -302,20 +312,13 @@ TEST_CASE("simple_usertype/factory constructor overloads", "simple usertypes sho
sol::constructors<sol::types<>, sol::types<const B&>> c; sol::constructors<sol::types<>, sol::types<const B&>> c;
lua.new_simple_usertype<B>("B", lua.new_simple_usertype<B>("B",
sol::call_constructor, c, sol::call_constructor, c,
"new", sol::factories([]() { "new", sol::factories([]() {
return B(); return B();
}), }),
"new2", sol::initializers( "new2", sol::initializers([](B& mem) { new (&mem) B(); }, [](B& mem, int v) {
[](B& mem) { new(&mem)B(); mem.bvar = v; }),
new(&mem)B();
},
[](B& mem, int v) {
new(&mem)B(); mem.bvar = v;
}
),
"f", sol::as_function(&B::bvar), "f", sol::as_function(&B::bvar),
"g", sol::overload([](B&) { return 2; }, [](B&, int v) { return v; }) "g", sol::overload([](B&) { return 2; }, [](B&, int v) { return v; }));
);
lua.safe_script("b = B()"); lua.safe_script("b = B()");
lua.safe_script("b2 = B.new()"); lua.safe_script("b2 = B.new()");
@ -369,7 +372,7 @@ TEST_CASE("simple_usertype/runtime append", "allow extra functions to be appende
int y = lua["y"]; int y = lua["y"];
REQUIRE(x == 200); REQUIRE(x == 200);
REQUIRE(y == 200); REQUIRE(y == 200);
lua.safe_script("z = b.method2(b)"); lua.safe_script("z = b.method2(b)");
lua.safe_script("w = b:method2()"); lua.safe_script("w = b:method2()");
int z = lua["z"]; int z = lua["z"];
@ -395,7 +398,7 @@ TEST_CASE("simple_usertype/table append", "Ensure that appending to the meta tab
lua.set("a", &a); lua.set("a", &a);
lua.set("pa", &a); lua.set("pa", &a);
lua.set("ua", std::make_unique<A>()); lua.set("ua", std::make_unique<A>());
REQUIRE_NOTHROW([&]{ REQUIRE_NOTHROW([&] {
lua.safe_script("assert(a:func() == 5000)"); lua.safe_script("assert(a:func() == 5000)");
lua.safe_script("assert(pa:func() == 5000)"); lua.safe_script("assert(pa:func() == 5000)");
lua.safe_script("assert(ua:func() == 5000)"); lua.safe_script("assert(ua:func() == 5000)");
@ -406,7 +409,9 @@ TEST_CASE("simple_usertype/class call propogation", "make sure methods and varia
class A { class A {
public: public:
int var = 200; int var = 200;
int thing() const { return 123; } int thing() const {
return 123;
}
}; };
class B : public A { class B : public A {
@ -418,8 +423,7 @@ TEST_CASE("simple_usertype/class call propogation", "make sure methods and varia
lua.new_simple_usertype<B>("B", lua.new_simple_usertype<B>("B",
sol::default_constructor, sol::default_constructor,
"thing", &B::thing, "thing", &B::thing,
"var", &B::var "var", &B::var);
);
lua.safe_script(R"( lua.safe_script(R"(
b = B.new() b = B.new()
@ -431,40 +435,45 @@ TEST_CASE("simple_usertype/class call propogation", "make sure methods and varia
TEST_CASE("simple_usertype/call constructor", "ensure that all kinds of call-based constructors can be serialized") { TEST_CASE("simple_usertype/call constructor", "ensure that all kinds of call-based constructors can be serialized") {
struct thing {}; struct thing {};
struct v_test { struct v_test {
}; };
struct f_test { struct f_test {
int i; f_test(int i) : i(i) {} int i;
f_test(int i)
: i(i) {
}
}; };
struct i_test { struct i_test {
int i; i_test(int i) : i(i) {} int i;
i_test(int i)
: i(i) {
}
}; };
struct r_test { struct r_test {
int i; r_test(int i) : i(i) {} int i;
r_test(int i)
: i(i) {
}
}; };
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
auto f = sol::factories([]() {return f_test(30); }); auto f = sol::factories([]() { return f_test(30); });
lua.new_simple_usertype<f_test>("f_test", lua.new_simple_usertype<f_test>("f_test",
sol::call_constructor, sol::factories([]() { sol::call_constructor, sol::factories([]() {
return f_test(20); return f_test(20);
}), }),
"new", f "new", f);
);
lua.new_simple_usertype<i_test>("i_test", lua.new_simple_usertype<i_test>("i_test",
sol::call_constructor, sol::initializers([](i_test& obj) { sol::call_constructor, sol::initializers([](i_test& obj) {
new(&obj)i_test(21); new (&obj) i_test(21);
}) }));
);
lua.new_simple_usertype<r_test>("r_test", lua.new_simple_usertype<r_test>("r_test",
sol::call_constructor, [](sol::table) { sol::call_constructor, [](sol::table) {
return r_test(22); return r_test(22);
} });
);
lua.safe_script("a = f_test()"); lua.safe_script("a = f_test()");
lua.safe_script("b = i_test()"); lua.safe_script("b = i_test()");
@ -486,13 +495,11 @@ TEST_CASE("simple_usertype/call constructor", "ensure that all kinds of call-bas
REQUIRE(v.second.is<thing>()); REQUIRE(v.second.is<thing>());
} }
return v_test(); return v_test();
} });
);
lua.new_simple_usertype<v_test>("v_test", lua.new_simple_usertype<v_test>("v_test",
sol::meta_function::construct, vfactories, sol::meta_function::construct, vfactories,
sol::call_constructor, vfactories sol::call_constructor, vfactories);
);
lua.new_simple_usertype<thing>("thing"); lua.new_simple_usertype<thing>("thing");
lua.safe_script("things = {thing.new(), thing.new()}"); lua.safe_script("things = {thing.new(), thing.new()}");
@ -513,8 +520,7 @@ TEST_CASE("simple_usertype/no_constructor", "make sure simple usertype errors wh
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<thing>("thing", lua.new_simple_usertype<thing>("thing",
sol::meta_function::construct, sol::no_constructor sol::meta_function::construct, sol::no_constructor);
);
auto result = lua.safe_script("a = thing.new()", sol::script_pass_on_error); auto result = lua.safe_script("a = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -524,11 +530,10 @@ TEST_CASE("simple_usertype/no_constructor", "make sure simple usertype errors wh
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<thing>("thing", lua.new_simple_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor sol::call_constructor, sol::no_constructor);
);
auto result = lua.safe_script("a = thing()", sol::script_pass_on_error); auto result = lua.safe_script("a = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
} }
TEST_CASE("simple_usertype/missing key", "make sure a missing key returns nil") { TEST_CASE("simple_usertype/missing key", "make sure a missing key returns nil") {
@ -544,7 +549,9 @@ TEST_CASE("simple_usertype/missing key", "make sure a missing key returns nil")
TEST_CASE("simple_usertype/runtime extensibility", "Check if usertypes are runtime extensible") { TEST_CASE("simple_usertype/runtime extensibility", "Check if usertypes are runtime extensible") {
struct thing { struct thing {
int v = 20; int v = 20;
int func(int a) { return a; } int func(int a) {
return a;
}
}; };
int val = 0; int val = 0;
@ -553,8 +560,7 @@ TEST_CASE("simple_usertype/runtime extensibility", "Check if usertypes are runti
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<thing>("thing", lua.new_simple_usertype<thing>("thing",
"func", &thing::func "func", &thing::func);
);
lua.safe_script(R"( lua.safe_script(R"(
t = thing.new() t = thing.new()
@ -565,7 +571,8 @@ t = thing.new()
t.runtime_func = function (a) t.runtime_func = function (a)
return a + 50 return a + 50
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -574,7 +581,8 @@ end
function t:runtime_func(a) function t:runtime_func(a)
return a + 52 return a + 52
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -600,8 +608,7 @@ end
lua.new_simple_usertype<thing>("thing", lua.new_simple_usertype<thing>("thing",
"func", &thing::func, "func", &thing::func,
"v", &thing::v "v", &thing::v);
);
lua.safe_script(R"( lua.safe_script(R"(
t = thing.new() t = thing.new()
@ -612,7 +619,8 @@ t = thing.new()
t.runtime_func = function (a) t.runtime_func = function (a)
return a + 50 return a + 50
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -621,7 +629,8 @@ end
function t:runtime_func(a) function t:runtime_func(a)
return a + 52 return a + 52
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
}()); }());
@ -646,7 +655,8 @@ end
TEST_CASE("simple_usertype/runtime replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") { TEST_CASE("simple_usertype/runtime replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") {
struct heart_base_t {}; struct heart_base_t {};
struct heart_t : heart_base_t { struct heart_t : heart_base_t {
void func() {} void func() {
}
}; };
SECTION("plain") { SECTION("plain") {
@ -675,8 +685,7 @@ TEST_CASE("simple_usertype/runtime replacement", "ensure that functions can be p
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<heart_t>("a", lua.new_simple_usertype<heart_t>("a",
sol::base_classes, sol::bases<heart_base_t>() sol::base_classes, sol::bases<heart_base_t>());
);
REQUIRE_NOTHROW([&lua]() { REQUIRE_NOTHROW([&lua]() {
lua.safe_script("obj = a.new()"); lua.safe_script("obj = a.new()");
@ -700,8 +709,7 @@ TEST_CASE("simple_usertype/runtime replacement", "ensure that functions can be p
lua.new_simple_usertype<heart_t>("a", lua.new_simple_usertype<heart_t>("a",
"func", &heart_t::func, "func", &heart_t::func,
sol::base_classes, sol::bases<heart_base_t>() sol::base_classes, sol::bases<heart_base_t>());
);
REQUIRE_NOTHROW([&lua]() { REQUIRE_NOTHROW([&lua]() {
lua.safe_script("obj = a.new()"); lua.safe_script("obj = a.new()");
@ -740,7 +748,6 @@ TEST_CASE("simple_usertype/meta key retrievals", "allow for special meta keys (_
s[sol::metatable_key][sol::meta_function::new_index] = &d_sample::foo; s[sol::metatable_key][sol::meta_function::new_index] = &d_sample::foo;
lua["var"] = s; lua["var"] = s;
lua.safe_script("var = sample.new()"); lua.safe_script("var = sample.new()");
lua.safe_script("var.key = 2"); lua.safe_script("var.key = 2");
lua.safe_script("var.__newindex = 4"); lua.safe_script("var.__newindex = 4");
@ -770,7 +777,7 @@ TEST_CASE("simple_usertype/meta key retrievals", "allow for special meta keys (_
sol::state lua; sol::state lua;
lua.new_simple_usertype<sample>("sample", sol::meta_function::new_index, &sample::foo); lua.new_simple_usertype<sample>("sample", sol::meta_function::new_index, &sample::foo);
lua.safe_script("var = sample.new()"); lua.safe_script("var = sample.new()");
lua.safe_script("var.key = 2"); lua.safe_script("var.key = 2");
lua.safe_script("var.__newindex = 4"); lua.safe_script("var.__newindex = 4");
@ -808,8 +815,7 @@ TEST_CASE("simple_usertype/static properties", "allow for static functions to ge
lua.new_simple_usertype<test_t>("test", lua.new_simple_usertype<test_t>("test",
"f", std::function<std::size_t()>(std::bind(std::mem_fn(&test_t::func), &manager)), "f", std::function<std::size_t()>(std::bind(std::mem_fn(&test_t::func), &manager)),
"g", sol::property(&test_t::s_func, &test_t::g_func) "g", sol::property(&test_t::s_func, &test_t::g_func));
);
lua.safe_script("v1 = test.f()"); lua.safe_script("v1 = test.f()");
lua.safe_script("v2 = test.g"); lua.safe_script("v2 = test.g");
@ -825,10 +831,12 @@ TEST_CASE("simple_usertype/static properties", "allow for static functions to ge
TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed/new_indexed properly without breaking") { TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed/new_indexed properly without breaking") {
static int val = 0; static int val = 0;
class indexing_test { class indexing_test {
public: public:
indexing_test() { val = 0; } indexing_test() {
val = 0;
}
sol::object getter(const std::string& name, sol::this_state _s) { sol::object getter(const std::string& name, sol::this_state _s) {
REQUIRE(name == "a"); REQUIRE(name == "a");
@ -851,8 +859,7 @@ TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<indexing_test>("test", lua.new_simple_usertype<indexing_test>("test",
sol::meta_function::index, &indexing_test::getter, sol::meta_function::index, &indexing_test::getter,
sol::meta_function::new_index, &indexing_test::setter sol::meta_function::new_index, &indexing_test::setter);
);
lua.safe_script(R"( lua.safe_script(R"(
local t = test.new() local t = test.new()
@ -869,8 +876,7 @@ TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_simple_usertype<indexing_test>("test", lua.new_simple_usertype<indexing_test>("test",
sol::meta_function::index, &indexing_test::getter, sol::meta_function::index, &indexing_test::getter,
sol::meta_function::new_index, &indexing_test::setter sol::meta_function::new_index, &indexing_test::setter);
);
lua["test"]["hi"] = [](indexing_test& _self) -> int { return _self.hi(); }; lua["test"]["hi"] = [](indexing_test& _self) -> int { return _self.hi(); };

View File

@ -4,8 +4,11 @@ struct test_stack_guard {
lua_State* L; lua_State* L;
int& begintop; int& begintop;
int& endtop; int& endtop;
test_stack_guard(lua_State* L, int& begintop, int& endtop) : L(L), begintop(begintop), endtop(endtop) { test_stack_guard(lua_State* L, int& begintop, int& endtop)
: L(L), begintop(begintop), endtop(endtop) {
begintop = lua_gettop(L); begintop = lua_gettop(L);
} }
~test_stack_guard() { endtop = lua_gettop(L); } ~test_stack_guard() {
endtop = lua_gettop(L);
}
}; };

View File

@ -39,6 +39,26 @@ struct write_file_attempt_object {
} }
}; };
struct string_reader_load {
const std::string& str;
std::size_t reads;
string_reader_load(const std::string& s)
: str(s), reads(0) {
}
};
const char* string_reader(lua_State* L, void* vpstr, size_t* sz) {
(void)L;
string_reader_load& srl = *static_cast<string_reader_load*>(vpstr);
if (srl.reads++ > 0) {
*sz = 0;
return NULL;
}
*sz = static_cast<size_t>(srl.str.size());
return srl.str.c_str();
}
TEST_CASE("state/require_file", "opening files as 'requires'") { TEST_CASE("state/require_file", "opening files as 'requires'") {
static const char file_require_file[] = "./tmp_thingy.lua"; static const char file_require_file[] = "./tmp_thingy.lua";
static const char file_require_file_user[] = "./tmp_thingy_user.lua"; static const char file_require_file_user[] = "./tmp_thingy_user.lua";
@ -57,9 +77,11 @@ TEST_CASE("state/require_file", "opening files as 'requires'") {
std::remove(file_require_file_user); std::remove(file_require_file_user);
}; };
SECTION("with usertypes") { SECTION("with usertypes") {
struct foo { struct foo {
foo(int bar) : bar(bar) {} foo(int bar)
: bar(bar) {
}
const int bar; const int bar;
}; };
@ -69,8 +91,7 @@ TEST_CASE("state/require_file", "opening files as 'requires'") {
lua.new_usertype<foo>("foo", lua.new_usertype<foo>("foo",
sol::constructors<sol::types<int>>{}, sol::constructors<sol::types<int>>{},
"bar", &foo::bar "bar", &foo::bar);
);
const sol::table thingy1 = lua.require_file("thingy", file_require_file_user); const sol::table thingy1 = lua.require_file("thingy", file_require_file_user);
@ -140,7 +161,7 @@ TEST_CASE("state/require", "require using a function") {
REQUIRE(val2 == 221); REQUIRE(val2 == 221);
// THIS IS ONLY REQUIRED IN LUA 5.3, FOR SOME REASON // THIS IS ONLY REQUIRED IN LUA 5.3, FOR SOME REASON
// must have loaded the same table // must have loaded the same table
// REQUIRE(thingy1 == thingy2); // REQUIRE(thingy1 == thingy2);
} }
TEST_CASE("state/multi require", "make sure that requires transfers across hand-rolled script implementation and standard requiref") { TEST_CASE("state/multi require", "make sure that requires transfers across hand-rolled script implementation and standard requiref") {
@ -347,7 +368,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
std::call_once(flag_file_g, write_file_attempt_object(), file_good, good); std::call_once(flag_file_g, write_file_attempt_object(), file_good, good);
auto clean_files = []() { auto clean_files = []() {
if (finished.fetch_add(1) < 10) { if (finished.fetch_add(1) < 14) {
return; return;
} }
std::remove(file_bad_syntax); std::remove(file_bad_syntax);
@ -412,7 +433,7 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
sol::stack_guard sg(lua); sol::stack_guard sg(lua);
auto errbsload = lua.load(bad_syntax); auto errbsload = lua.load(bad_syntax);
REQUIRE(!errbsload.valid()); REQUIRE(!errbsload.valid());
sol::load_result errbrload = lua.load(bad_runtime); sol::load_result errbrload = lua.load(bad_runtime);
REQUIRE(errbrload.valid()); REQUIRE(errbrload.valid());
sol::protected_function errbrpf = errbrload; sol::protected_function errbrpf = errbrload;
@ -430,6 +451,87 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
REQUIRE(ar == 21); REQUIRE(ar == 21);
clean_files(); clean_files();
} }
SECTION("load") {
sol::state lua;
sol::stack_guard sg(lua);
string_reader_load bssrl(bad_syntax);
void* vpbssrl = static_cast<void*>(&bssrl);
auto errbsload = lua.load(&string_reader, vpbssrl, bad_syntax);
REQUIRE(!errbsload.valid());
string_reader_load brsrl(bad_runtime);
void* vpbrsrl = static_cast<void*>(&brsrl);
sol::load_result errbrload = lua.load(&string_reader, vpbrsrl, bad_runtime);
REQUIRE(errbrload.valid());
sol::protected_function errbrpf = errbrload;
auto errbr = errbrpf();
REQUIRE(!errbr.valid());
string_reader_load gsrl(good);
void* vpgsrl = static_cast<void*>(&gsrl);
sol::load_result resultload = lua.load(&string_reader, vpgsrl, good);
REQUIRE(resultload.valid());
sol::protected_function resultpf = resultload;
auto result = resultpf();
int a = lua["a"];
int ar = result;
REQUIRE(result.valid());
REQUIRE(a == 21);
REQUIRE(ar == 21);
clean_files();
}
SECTION("load_string (text)") {
sol::state lua;
sol::stack_guard sg(lua);
auto errbsload = lua.load(bad_syntax, bad_syntax, sol::load_mode::text);
REQUIRE(!errbsload.valid());
sol::load_result errbrload = lua.load(bad_runtime, bad_runtime, sol::load_mode::text);
REQUIRE(errbrload.valid());
sol::protected_function errbrpf = errbrload;
auto errbr = errbrpf();
REQUIRE(!errbr.valid());
sol::load_result resultload = lua.load(good, good, sol::load_mode::text);
REQUIRE(resultload.valid());
sol::protected_function resultpf = resultload;
auto result = resultpf();
int a = lua["a"];
int ar = result;
REQUIRE(result.valid());
REQUIRE(a == 21);
REQUIRE(ar == 21);
clean_files();
}
SECTION("load (text)") {
sol::state lua;
sol::stack_guard sg(lua);
string_reader_load bssrl(bad_syntax);
void* vpbssrl = static_cast<void*>(&bssrl);
auto errbsload = lua.load(&string_reader, vpbssrl, bad_syntax, sol::load_mode::text);
REQUIRE(!errbsload.valid());
string_reader_load brsrl(bad_runtime);
void* vpbrsrl = static_cast<void*>(&brsrl);
sol::load_result errbrload = lua.load(&string_reader, vpbrsrl, bad_runtime, sol::load_mode::text);
REQUIRE(errbrload.valid());
sol::protected_function errbrpf = errbrload;
auto errbr = errbrpf();
REQUIRE(!errbr.valid());
string_reader_load gsrl(good);
void* vpgsrl = static_cast<void*>(&gsrl);
sol::load_result resultload = lua.load(&string_reader, vpgsrl, good, sol::load_mode::text);
REQUIRE(resultload.valid());
sol::protected_function resultpf = resultload;
auto result = resultpf();
int a = lua["a"];
int ar = result;
REQUIRE(result.valid());
REQUIRE(a == 21);
REQUIRE(ar == 21);
clean_files();
}
SECTION("script_file") { SECTION("script_file") {
sol::state lua; sol::state lua;
sol::stack_guard sg(lua); sol::stack_guard sg(lua);
@ -522,6 +624,29 @@ TEST_CASE("state/script, do, and load", "test success and failure cases for load
REQUIRE(ar == 21); REQUIRE(ar == 21);
clean_files(); clean_files();
} }
SECTION("load_file (text)") {
sol::state lua;
sol::stack_guard sg(lua);
auto errbsload = lua.load_file(file_bad_syntax, sol::load_mode::text);
REQUIRE(!errbsload.valid());
sol::load_result errbrload = lua.load_file(file_bad_runtime, sol::load_mode::text);
REQUIRE(errbrload.valid());
sol::protected_function errbrpf = errbrload;
auto errbr = errbrpf();
REQUIRE(!errbr.valid());
sol::load_result resultload = lua.load_file(file_good, sol::load_mode::text);
REQUIRE(resultload.valid());
sol::protected_function resultpf = resultload;
auto result = resultpf();
int a = lua["a"];
int ar = result;
REQUIRE(result.valid());
REQUIRE(a == 21);
REQUIRE(ar == 21);
clean_files();
}
} }
TEST_CASE("state/script return converts", "make sure that script return values are convertable from one to another") { TEST_CASE("state/script return converts", "make sure that script return values are convertable from one to another") {

View File

@ -14,8 +14,8 @@ namespace muh_namespace {
namespace { namespace {
struct ns_anon_test {}; struct ns_anon_test {};
} } // namespace
} } // namespace muh_namespace
// There isn't a single library roundtripping which codecvt works on. We'll do the nitty-gritty of it later... // There isn't a single library roundtripping which codecvt works on. We'll do the nitty-gritty of it later...
TEST_CASE("stack/strings", "test that strings can be roundtripped") { TEST_CASE("stack/strings", "test that strings can be roundtripped") {
@ -57,7 +57,7 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") {
REQUIRE(utf16_to_utf8 == utf8str_s); REQUIRE(utf16_to_utf8 == utf8str_s);
REQUIRE(utf32_to_utf8 == utf8str_s); REQUIRE(utf32_to_utf8 == utf8str_s);
REQUIRE(wide_to_utf8 == utf8str_s); REQUIRE(wide_to_utf8 == utf8str_s);
std::wstring utf8_to_wide = lua["utf8"]; std::wstring utf8_to_wide = lua["utf8"];
std::wstring utf16_to_wide = lua["utf16"]; std::wstring utf16_to_wide = lua["utf16"];
std::wstring utf32_to_wide = lua["utf32"]; std::wstring utf32_to_wide = lua["utf32"];

View File

@ -16,7 +16,7 @@ std::string free_function() {
} }
struct object { struct object {
std::string operator() () { std::string operator()() {
INFO("member_test()"); INFO("member_test()");
return "test"; return "test";
} }
@ -34,7 +34,7 @@ TEST_CASE("tables/as enums", "Making sure enums can be put in and gotten out as
left, left,
right right
}; };
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
@ -42,8 +42,7 @@ TEST_CASE("tables/as enums", "Making sure enums can be put in and gotten out as
"up", direction::up, "up", direction::up,
"down", direction::down, "down", direction::down,
"left", direction::left, "left", direction::left,
"right", direction::right "right", direction::right);
);
sol::object obj = lua["direction"]["up"]; sol::object obj = lua["direction"]["up"];
bool isdir = obj.is<direction>(); bool isdir = obj.is<direction>();
@ -67,8 +66,7 @@ TEST_CASE("tables/as enum classes", "Making sure enums can be put in and gotten
"up", direction::up, "up", direction::up,
"down", direction::down, "down", direction::down,
"left", direction::left, "left", direction::left,
"right", direction::right "right", direction::right);
);
sol::object obj = lua["direction"]["up"]; sol::object obj = lua["direction"]["up"];
bool isdir = obj.is<direction>(); bool isdir = obj.is<direction>();
@ -129,8 +127,7 @@ TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as
"up", direction::up, "up", direction::up,
"down", direction::down, "down", direction::down,
"left", direction::left, "left", direction::left,
"right", direction::right "right", direction::right);
);
direction d = lua["direction"]["left"]; direction d = lua["direction"]["left"];
REQUIRE(d == direction::left); REQUIRE(d == direction::left);
@ -143,12 +140,7 @@ TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_enum<direction>("direction", { lua.new_enum<direction>("direction", { { "up", direction::up }, { "down", direction::down }, { "left", direction::left }, { "right", direction::right } });
{ "up", direction::up },
{ "down", direction::down },
{ "left", direction::left },
{ "right", direction::right }
} );
direction d = lua["direction"]["left"]; direction d = lua["direction"]["left"];
REQUIRE(d == direction::left); REQUIRE(d == direction::left);
@ -163,7 +155,8 @@ TEST_CASE("tables/for_each", "Testing the use of for_each to get values from a l
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.safe_script("arr = {\n" lua.safe_script(
"arr = {\n"
"[0] = \"Hi\",\n" "[0] = \"Hi\",\n"
"[1] = 123.45,\n" "[1] = 123.45,\n"
"[2] = \"String value\",\n" "[2] = \"String value\",\n"
@ -277,7 +270,8 @@ TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.safe_script("arr = {\n" lua.safe_script(
"arr = {\n"
"[0] = \"Hi\",\n" "[0] = \"Hi\",\n"
"[1] = 123.45,\n" "[1] = 123.45,\n"
"[2] = \"String value\",\n" "[2] = \"String value\",\n"
@ -328,7 +322,8 @@ TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a
} }
}(kvp.first, kvp.second); }(kvp.first, kvp.second);
} }
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
REQUIRE(iterations == tablesize); REQUIRE(iterations == tablesize);
} }
@ -393,10 +388,9 @@ TEST_CASE("tables/function variables", "Check if tables and function calls work
lua.get<sol::table>("os").set_function("fun", lua.get<sol::table>("os").set_function("fun",
[]() { []() {
INFO("stateless lambda()"); INFO("stateless lambda()");
return "test"; return "test";
} });
);
REQUIRE_NOTHROW(run_script(lua)); REQUIRE_NOTHROW(run_script(lua));
lua.get<sol::table>("os").set_function("fun", &free_function); lua.get<sol::table>("os").set_function("fun", &free_function);
@ -414,15 +408,13 @@ TEST_CASE("tables/function variables", "Check if tables and function calls work
lua.get<sol::table>("os").set_function("fun", &object::operator(), std::ref(reflval)); lua.get<sol::table>("os").set_function("fun", &object::operator(), std::ref(reflval));
REQUIRE_NOTHROW(run_script(lua)); REQUIRE_NOTHROW(run_script(lua));
// stateful lambda: non-convertible, cannot be optimised // stateful lambda: non-convertible, cannot be optimised
int breakit = 50; int breakit = 50;
lua.get<sol::table>("os").set_function("fun", lua.get<sol::table>("os").set_function("fun",
[&breakit]() { [&breakit]() {
INFO("stateful lambda()"); INFO("stateful lambda()");
return "test"; return "test";
} });
);
REQUIRE_NOTHROW(run_script(lua)); REQUIRE_NOTHROW(run_script(lua));
// r-value, cannot optimise // r-value, cannot optimise
@ -573,8 +565,7 @@ TEST_CASE("tables/raw set and raw get", "ensure raw setting and getting works th
sol::table t = lua.create_table(); sol::table t = lua.create_table();
t[sol::metatable_key] = lua.create_table_with( t[sol::metatable_key] = lua.create_table_with(
sol::meta_function::new_index, [](lua_State* L) { return luaL_error(L, "nay"); }, sol::meta_function::new_index, [](lua_State* L) { return luaL_error(L, "nay"); },
sol::meta_function::index, [](lua_State* L) { return luaL_error(L, "nay"); } sol::meta_function::index, [](lua_State* L) { return luaL_error(L, "nay"); });
);
t.raw_set("a", 2.5); t.raw_set("a", 2.5);
double la = t.raw_get<double>("a"); double la = t.raw_get<double>("a");
REQUIRE(la == 2.5); REQUIRE(la == 2.5);

View File

@ -7,7 +7,6 @@
#include <list> #include <list>
#include <memory> #include <memory>
struct non_copyable { struct non_copyable {
non_copyable() = default; non_copyable() = default;
non_copyable(const non_copyable&) = delete; non_copyable(const non_copyable&) = delete;
@ -18,21 +17,23 @@ struct non_copyable {
struct vars { struct vars {
vars() { vars() {
} }
int boop = 0; int boop = 0;
~vars() { ~vars() {
} }
}; };
struct fuser { struct fuser {
int x; int x;
fuser() : x(0) {} fuser()
: x(0) {
}
fuser(int x) : x(x) {} fuser(int x)
: x(x) {
}
int add(int y) { int add(int y) {
return x + y; return x + y;
@ -46,9 +47,15 @@ struct fuser {
namespace crapola { namespace crapola {
struct fuser { struct fuser {
int x; int x;
fuser() : x(0) {} fuser()
fuser(int x) : x(x) {} : x(0) {
fuser(int x, int x2) : x(x * x2) {} }
fuser(int x)
: x(x) {
}
fuser(int x, int x2)
: x(x * x2) {
}
int add(int y) { int add(int y) {
return x + y; return x + y;
@ -57,11 +64,13 @@ namespace crapola {
return x + y + 2; return x + y + 2;
} }
}; };
} // crapola } // namespace crapola
class Base { class Base {
public: public:
Base(int a_num) : m_num(a_num) { } Base(int a_num)
: m_num(a_num) {
}
int get_num() { int get_num() {
return m_num; return m_num;
@ -73,7 +82,9 @@ protected:
class Derived : public Base { class Derived : public Base {
public: public:
Derived(int a_num) : Base(a_num) { } Derived(int a_num)
: Base(a_num) {
}
int get_num_10() { int get_num_10() {
return 10 * m_num; return 10 * m_num;
@ -94,13 +105,15 @@ public:
struct Vec { struct Vec {
float x, y, z; float x, y, z;
Vec(float x, float y, float z) : x{ x }, y{ y }, z{ z } {} Vec(float x, float y, float z)
: x{ x }, y{ y }, z{ z } {
}
float length() { float length() {
return sqrtf(x*x + y*y + z*z); return sqrtf(x * x + y * y + z * z);
} }
Vec normalized() { Vec normalized() {
float invS = 1 / length(); float invS = 1 / length();
return{ x * invS, y * invS, z * invS }; return { x * invS, y * invS, z * invS };
} }
}; };
@ -108,7 +121,6 @@ struct giver {
int a = 0; int a = 0;
giver() { giver() {
} }
void gief() { void gief() {
@ -116,7 +128,6 @@ struct giver {
} }
static void stuff() { static void stuff() {
} }
static void gief_stuff(giver& t, int a) { static void gief_stuff(giver& t, int a) {
@ -124,15 +135,18 @@ struct giver {
} }
~giver() { ~giver() {
} }
}; };
struct factory_test { struct factory_test {
private: private:
factory_test() { a = true_a; } factory_test() {
~factory_test() { a = 0; } a = true_a;
}
~factory_test() {
a = 0;
}
public: public:
static int num_saved; static int num_saved;
static int num_killed; static int num_killed;
@ -151,7 +165,7 @@ public:
} }
static void save(factory_test& f) { static void save(factory_test& f) {
new(&f)factory_test(); new (&f) factory_test();
++num_saved; ++num_saved;
} }
@ -172,15 +186,18 @@ bool something() {
struct thing { struct thing {
int v = 100; int v = 100;
thing() {} thing() {
thing(int x) : v(x) {} }
thing(int x)
: v(x) {
}
}; };
struct self_test { struct self_test {
int bark; int bark;
self_test() : bark(100) { self_test()
: bark(100) {
} }
void g(const std::string& str) { void g(const std::string& str) {
@ -203,13 +220,14 @@ struct ext_getset {
const int meow = 56; const int meow = 56;
ext_getset() = default; ext_getset() = default;
ext_getset(int v) : bark(v) {} ext_getset(int v)
: bark(v) {
}
ext_getset(ext_getset&&) = default; ext_getset(ext_getset&&) = default;
ext_getset(const ext_getset&) = delete; ext_getset(const ext_getset&) = delete;
ext_getset& operator=(ext_getset&&) = default; ext_getset& operator=(ext_getset&&) = default;
ext_getset& operator=(const ext_getset&) = delete; ext_getset& operator=(const ext_getset&) = delete;
~ext_getset() { ~ext_getset() {
} }
std::string x() { std::string x() {
@ -229,13 +247,11 @@ struct ext_getset {
} }
static void s_set(int) { static void s_set(int) {
} }
static int s_get(int x) { static int s_get(int x) {
return x + 20; return x + 20;
} }
}; };
template <typename T> template <typename T>
@ -271,7 +287,8 @@ TEST_CASE("usertype/usertype", "Show that we can create classes from usertype an
sol::usertype<fuser> lc{ "add", &fuser::add, "add2", &fuser::add2 }; sol::usertype<fuser> lc{ "add", &fuser::add, "add2", &fuser::add2 };
lua.set_usertype(lc); lua.set_usertype(lc);
lua.safe_script("a = fuser:new()\n" lua.safe_script(
"a = fuser:new()\n"
"b = a:add(1)\n" "b = a:add(1)\n"
"c = a:add2(1)\n"); "c = a:add2(1)\n");
@ -339,7 +356,8 @@ TEST_CASE("usertype/usertype-utility", "Show internal management of classes regi
lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2); lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
lua.safe_script("a = fuser.new()\n" lua.safe_script(
"a = fuser.new()\n"
"b = a:add(1)\n" "b = a:add(1)\n"
"c = a:add2(1)\n"); "c = a:add2(1)\n");
@ -373,15 +391,16 @@ TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice
sol::constructors<sol::types<int>> derivedctor; sol::constructors<sol::types<int>> derivedctor;
sol::usertype<Derived> derivedusertype(derivedctor, sol::usertype<Derived> derivedusertype(derivedctor,
"get_num_10", &Derived::get_num_10, "get_num_10", &Derived::get_num_10,
"get_num", &Derived::get_num "get_num", &Derived::get_num);
);
lua.set_usertype(derivedusertype); lua.set_usertype(derivedusertype);
lua.safe_script("derived = Derived.new(7)"); lua.safe_script("derived = Derived.new(7)");
lua.safe_script("dgn = derived:get_num()\n" lua.safe_script(
"dgn = derived:get_num()\n"
"print(dgn)"); "print(dgn)");
lua.safe_script("dgn10 = derived:get_num_10()\n" lua.safe_script(
"dgn10 = derived:get_num_10()\n"
"print(dgn10)"); "print(dgn10)");
REQUIRE((lua.get<int>("dgn10") == 70)); REQUIRE((lua.get<int>("dgn10") == 70));
@ -397,8 +416,7 @@ TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice
lua.safe_script( lua.safe_script(
"local a = test.new()\n" "local a = test.new()\n"
"a:g(\"woof\")\n" "a:g(\"woof\")\n"
"a:f(a)\n" "a:f(a)\n");
);
} }
TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") { TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
@ -449,9 +467,11 @@ TEST_CASE("usertype/issue-number-thirty-five", "using value types created from l
sol::usertype<Vec> udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length); sol::usertype<Vec> udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length);
lua.set_usertype(udata); lua.set_usertype(udata);
REQUIRE_NOTHROW(lua.safe_script("v = Vec.new(1, 2, 3)\n" REQUIRE_NOTHROW(lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:length())")); "print(v:length())"));
REQUIRE_NOTHROW(lua.safe_script("v = Vec.new(1, 2, 3)\n" REQUIRE_NOTHROW(lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())")); "print(v:normalized():length())"));
} }
@ -469,11 +489,13 @@ TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored
// usertype dies, but still usable in lua! // usertype dies, but still usable in lua!
} }
REQUIRE_NOTHROW(lua.safe_script("collectgarbage()\n" REQUIRE_NOTHROW(lua.safe_script(
"collectgarbage()\n"
"v = Vec.new(1, 2, 3)\n" "v = Vec.new(1, 2, 3)\n"
"print(v:length())")); "print(v:length())"));
REQUIRE_NOTHROW(lua.safe_script("v = Vec.new(1, 2, 3)\n" REQUIRE_NOTHROW(lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())")); "print(v:normalized():length())"));
} }
@ -489,23 +511,23 @@ TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as
"length", &Vec::length); "length", &Vec::length);
lua.set_usertype(udata); lua.set_usertype(udata);
REQUIRE_NOTHROW(lua.safe_script("v = Vec.new(1, 2, 3)\n" REQUIRE_NOTHROW(lua.safe_script(
"v = Vec.new(1, 2, 3)\n"
"v2 = Vec.new(0, 1, 0)\n" "v2 = Vec.new(0, 1, 0)\n"
"print(v:length())\n" "print(v:length())\n"));
)); REQUIRE_NOTHROW(lua.safe_script(
REQUIRE_NOTHROW(lua.safe_script("v.x = 2\n" "v.x = 2\n"
"v2.y = 2\n" "v2.y = 2\n"
"print(v.x, v.y, v.z)\n" "print(v.x, v.y, v.z)\n"
"print(v2.x, v2.y, v2.z)\n" "print(v2.x, v2.y, v2.z)\n"));
)); REQUIRE_NOTHROW(lua.safe_script(
REQUIRE_NOTHROW(lua.safe_script("assert(v.x == 2)\n" "assert(v.x == 2)\n"
"assert(v2.x == 0)\n" "assert(v2.x == 0)\n"
"assert(v2.y == 2)\n" "assert(v2.y == 2)\n"));
)); REQUIRE_NOTHROW(lua.safe_script(
REQUIRE_NOTHROW(lua.safe_script("v.x = 3\n" "v.x = 3\n"
"local x = v.x\n" "local x = v.x\n"
"assert(x == 3)\n" "assert(x == 3)\n"));
));
struct breaks { struct breaks {
sol::function f; sol::function f;
@ -514,8 +536,7 @@ TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.set("b", breaks()); lua.set("b", breaks());
lua.new_usertype<breaks>("breaks", lua.new_usertype<breaks>("breaks",
"f", &breaks::f "f", &breaks::f);
);
breaks& b = lua["b"]; breaks& b = lua["b"];
REQUIRE_NOTHROW(lua.safe_script("b.f = function () print('BARK!') end")); REQUIRE_NOTHROW(lua.safe_script("b.f = function () print('BARK!') end"));
@ -528,15 +549,17 @@ TEST_CASE("usertype/nonmember-functions", "let users set non-member functions th
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<giver>("giver", lua.new_usertype<giver>("giver",
"gief_stuff", giver::gief_stuff, "gief_stuff", giver::gief_stuff,
"gief", &giver::gief, "gief", &giver::gief,
"__tostring", [](const giver& t) { "__tostring", [](const giver& t) {
return std::to_string(t.a) + ": giving value"; return std::to_string(t.a) + ": giving value";
} })
).get<sol::table>("giver").set_function("stuff", giver::stuff); .get<sol::table>("giver")
.set_function("stuff", giver::stuff);
REQUIRE_NOTHROW(lua.safe_script("giver.stuff()")); REQUIRE_NOTHROW(lua.safe_script("giver.stuff()"));
REQUIRE_NOTHROW(lua.safe_script("t = giver.new()\n" REQUIRE_NOTHROW(lua.safe_script(
"t = giver.new()\n"
"print(tostring(t))\n" "print(tostring(t))\n"
"t:gief()\n" "t:gief()\n"
"t:gief_stuff(20)\n")); "t:gief_stuff(20)\n"));
@ -549,24 +572,25 @@ TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique
auto uniqueint = std::make_unique<int64_t>(unique_value); auto uniqueint = std::make_unique<int64_t>(unique_value);
auto sharedint = std::make_shared<int64_t>(unique_value); auto sharedint = std::make_shared<int64_t>(unique_value);
long preusecount = sharedint.use_count(); long preusecount = sharedint.use_count();
{ sol::state lua; {
lua.open_libraries(sol::lib::base); sol::state lua;
lua.set("uniqueint", std::move(uniqueint)); lua.open_libraries(sol::lib::base);
lua.set("sharedint", sharedint); lua.set("uniqueint", std::move(uniqueint));
std::unique_ptr<int64_t>& uniqueintref = lua["uniqueint"]; lua.set("sharedint", sharedint);
std::shared_ptr<int64_t>& sharedintref = lua["sharedint"]; std::unique_ptr<int64_t>& uniqueintref = lua["uniqueint"];
int64_t* rawuniqueintref = lua["uniqueint"]; std::shared_ptr<int64_t>& sharedintref = lua["sharedint"];
int64_t* rawsharedintref = lua["sharedint"]; int64_t* rawuniqueintref = lua["uniqueint"];
int siusecount = sharedintref.use_count(); int64_t* rawsharedintref = lua["sharedint"];
REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref)); int siusecount = sharedintref.use_count();
REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr)); REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref));
REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get())); REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr));
REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref)); REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get()));
REQUIRE(siusecount == sharedint.use_count()); REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref));
std::shared_ptr<int64_t> moreref = sharedint; REQUIRE(siusecount == sharedint.use_count());
REQUIRE(unique_value == *moreref.get()); std::shared_ptr<int64_t> moreref = sharedint;
REQUIRE(moreref.use_count() == sharedint.use_count()); REQUIRE(unique_value == *moreref.get());
REQUIRE(moreref.use_count() == sharedintref.use_count()); REQUIRE(moreref.use_count() == sharedint.use_count());
REQUIRE(moreref.use_count() == sharedintref.use_count());
} }
REQUIRE(preusecount == sharedint.use_count()); REQUIRE(preusecount == sharedint.use_count());
} }
@ -575,7 +599,8 @@ TEST_CASE("regressions/one", "issue number 48") {
sol::state lua; sol::state lua;
lua.new_usertype<vars>("vars", lua.new_usertype<vars>("vars",
"boop", &vars::boop); "boop", &vars::boop);
REQUIRE_NOTHROW(lua.safe_script("beep = vars.new()\n" REQUIRE_NOTHROW(lua.safe_script(
"beep = vars.new()\n"
"beep.boop = 1")); "beep.boop = 1"));
// test for segfault // test for segfault
auto my_var = lua.get<vars>("beep"); auto my_var = lua.get<vars>("beep");
@ -622,8 +647,7 @@ TEST_CASE("usertype/private-constructible", "Check to make sure special snowflak
lua.new_usertype<factory_test>("factory_test", lua.new_usertype<factory_test>("factory_test",
"new", sol::initializers(factory_test::save), "new", sol::initializers(factory_test::save),
"__gc", sol::destructor(factory_test::kill), "__gc", sol::destructor(factory_test::kill),
"a", &factory_test::a "a", &factory_test::a);
);
std::unique_ptr<factory_test, factory_test::deleter> f = factory_test::make(); std::unique_ptr<factory_test, factory_test::deleter> f = factory_test::make();
lua.set("true_a", factory_test::true_a, "f", f.get()); lua.set("true_a", factory_test::true_a, "f", f.get());
@ -640,15 +664,18 @@ TEST_CASE("usertype/private-constructible", "Check to make sure special snowflak
} }
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") { TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
struct A_x { int x = 201; }; struct A_x {
int x = 201;
};
struct B_foo { struct B_foo {
int foo(const A_x* a) { return a->x; }; int foo(const A_x* a) {
return a->x;
};
}; };
sol::state lua; sol::state lua;
lua.new_usertype<B_foo>("B", lua.new_usertype<B_foo>("B",
"foo", &B_foo::foo "foo", &B_foo::foo);
);
lua.set("a", A_x()); lua.set("a", A_x());
lua.set("b", B_foo()); lua.set("b", B_foo());
lua.safe_script("x = b:foo(a)"); lua.safe_script("x = b:foo(a)");
@ -677,8 +704,7 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
lua.new_usertype<woof>("woof", lua.new_usertype<woof>("woof",
"var", &woof::var, "var", &woof::var,
"func", sol::overload(&woof::func, &woof::func2, &woof::func2s) "func", sol::overload(&woof::func, &woof::func2, &woof::func2s));
);
const std::string bark_58 = "bark 58"; const std::string bark_58 = "bark 58";
@ -686,8 +712,7 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
"r = woof:new()\n" "r = woof:new()\n"
"a = r:func(1)\n" "a = r:func(1)\n"
"b = r:func(1, 2)\n" "b = r:func(1, 2)\n"
"c = r:func(58, 'bark')\n" "c = r:func(58, 'bark')\n"));
));
REQUIRE((lua["a"] == 1)); REQUIRE((lua["a"] == 1));
REQUIRE((lua["b"] == 3.5)); REQUIRE((lua["b"] == 3.5));
REQUIRE((lua["c"] == bark_58)); REQUIRE((lua["c"] == bark_58));
@ -697,15 +722,20 @@ TEST_CASE("usertype/overloading", "Check if overloading works properly for usert
TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") { TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
struct overloading_test { struct overloading_test {
int print(int i) { INFO("Integer print: " << i); return 500 + i; } int print(int i) {
int print() { INFO("No param print."); return 500; } INFO("Integer print: " << i);
return 500 + i;
}
int print() {
INFO("No param print.");
return 500;
}
}; };
sol::state lua; sol::state lua;
lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(), lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(),
"print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)), "print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
"print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)) "print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)));
);
lua.set("test", overloading_test()); lua.set("test", overloading_test());
sol::function f0_0 = lua.load("return test:print()"); sol::function f0_0 = lua.load("return test:print()");
@ -783,9 +813,11 @@ TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions c
struct bark { struct bark {
int var = 50; int var = 50;
void func() {} void func() {
}
static void oh_boy() {} static void oh_boy() {
}
static int oh_boy(std::string name) { static int oh_boy(std::string name) {
return static_cast<int>(name.length()); return static_cast<int>(name.length());
@ -805,8 +837,7 @@ TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions c
"something2", [](int x, int y) { return x + y; }, "something2", [](int x, int y) { return x + y; },
"func", &bark::func, "func", &bark::func,
"oh_boy", sol::overload(sol::resolve<void()>(&bark::oh_boy), sol::resolve<int(std::string)>(&bark::oh_boy)), "oh_boy", sol::overload(sol::resolve<void()>(&bark::oh_boy), sol::resolve<int(std::string)>(&bark::oh_boy)),
sol::meta_function::call_function, &bark::operator() sol::meta_function::call_function, &bark::operator());
);
REQUIRE_NOTHROW(lua.safe_script("assert(bark.oh_boy('woo') == 3)")); REQUIRE_NOTHROW(lua.safe_script("assert(bark.oh_boy('woo') == 3)"));
REQUIRE_NOTHROW(lua.safe_script("bark.oh_boy()")); REQUIRE_NOTHROW(lua.safe_script("bark.oh_boy()"));
@ -889,8 +920,7 @@ TEST_CASE("usertype/properties", "Check if member properties/variables work") {
"a", sol::property(&bark::get_var2, &bark::set_var2), "a", sol::property(&bark::get_var2, &bark::set_var2),
"b", sol::property(&bark::get_var2), "b", sol::property(&bark::get_var2),
"c", sol::property(&bark::get_var3), "c", sol::property(&bark::get_var3),
"d", sol::property(&bark::set_var2) "d", sol::property(&bark::set_var2));
);
bark b; bark b;
lua.set("b", &b); lua.set("b", &b);
@ -933,7 +963,9 @@ TEST_CASE("usertype/properties", "Check if member properties/variables work") {
TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") { TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
class Test { class Test {
public: public:
void sayHello() { std::cout << "Hey\n"; } void sayHello() {
std::cout << "Hey\n";
}
}; };
sol::state lua; sol::state lua;
@ -952,9 +984,7 @@ TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed w
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
"v", &thing::v "v", &thing::v, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>());
, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>()
);
lua.safe_script(R"( lua.safe_script(R"(
t = thing(256) t = thing(256)
@ -970,14 +1000,12 @@ TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed
lua.open_libraries(); lua.open_libraries();
lua.new_usertype<matrix_xf>("mat", lua.new_usertype<matrix_xf>("mat",
sol::call_constructor, sol::factories(&matrix_xf::from_lua_table) sol::call_constructor, sol::factories(&matrix_xf::from_lua_table));
);
lua.safe_script("m = mat{ {1.1, 2.2} }"); lua.safe_script("m = mat{ {1.1, 2.2} }");
lua.new_usertype<matrix_xi>("mati", lua.new_usertype<matrix_xi>("mati",
sol::call_constructor, sol::factories(&matrix_xi::from_lua_table) sol::call_constructor, sol::factories(&matrix_xi::from_lua_table));
);
lua.safe_script("mi = mati{ {1, 2} }"); lua.safe_script("mi = mati{ {1, 2} }");
@ -993,25 +1021,27 @@ TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") {
class class01 { class class01 {
public: public:
int x = 57; int x = 57;
class01() {} class01() {
}
}; };
class class02 { class class02 {
public: public:
int x = 50; int x = 50;
class02() {} class02() {
class02(const class01& other) : x(other.x) {} }
class02(const class01& other)
: x(other.x) {
}
}; };
sol::state lua; sol::state lua;
lua.new_usertype<class01>("class01", lua.new_usertype<class01>("class01",
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>() sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>());
);
lua.new_usertype<class02>("class02", lua.new_usertype<class02>("class02",
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>() sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>());
);
REQUIRE_NOTHROW(lua.safe_script(R"( REQUIRE_NOTHROW(lua.safe_script(R"(
x = class01() x = class01()
@ -1026,24 +1056,20 @@ TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be construct
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
"v", &thing::v "v", &thing::v, sol::call_constructor, sol::constructors<>());
, sol::call_constructor, sol::constructors<>()
);
auto result = lua.safe_script("t = thing(256)", sol::script_pass_on_error); auto result = lua.safe_script("t = thing(256)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") { TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
SECTION("order1") { SECTION("order1") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
"v", &thing::v, "v", &thing::v,
sol::call_constructor, sol::no_constructor sol::call_constructor, sol::no_constructor);
);
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error); auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -1051,22 +1077,20 @@ TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed
SECTION("order2") { SECTION("order2") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor, sol::call_constructor, sol::no_constructor,
"v", &thing::v "v", &thing::v);
);
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error); auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
SECTION("new no_constructor") { SECTION("new no_constructor") {
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
sol::meta_function::construct, sol::no_constructor sol::meta_function::construct, sol::no_constructor);
);
auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error); auto result = lua.safe_script("t = thing.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -1076,8 +1100,7 @@ TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
sol::call_constructor, sol::no_constructor sol::call_constructor, sol::no_constructor);
);
auto result = lua.safe_script("t = thing()", sol::script_pass_on_error); auto result = lua.safe_script("t = thing()", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
} }
@ -1090,20 +1113,10 @@ TEST_CASE("usertype/coverage", "try all the things") {
lua.new_usertype<ext_getset>("ext_getset", lua.new_usertype<ext_getset>("ext_getset",
sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>(), sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>(),
sol::meta_function::garbage_collect, sol::destructor(des<ext_getset>), sol::meta_function::garbage_collect, sol::destructor(des<ext_getset>),
"x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) { "x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) {
return m.meow + 50 + y + x.length(); return m.meow + 50 + y + x.length();
}), }),
"bark", &ext_getset::bark, "bark", &ext_getset::bark, "meow", &ext_getset::meow, "readonlybark", sol::readonly(&ext_getset::bark), "set", &ext_getset::set, "get", &ext_getset::get, "sset", &ext_getset::s_set, "sget", &ext_getset::s_get, "propbark", sol::property(&ext_getset::set, &ext_getset::get), "readonlypropbark", sol::property(&ext_getset::get), "writeonlypropbark", sol::property(&ext_getset::set));
"meow", &ext_getset::meow,
"readonlybark", sol::readonly(&ext_getset::bark),
"set", &ext_getset::set,
"get", &ext_getset::get,
"sset", &ext_getset::s_set,
"sget", &ext_getset::s_get,
"propbark", sol::property(&ext_getset::set, &ext_getset::get),
"readonlypropbark", sol::property(&ext_getset::get),
"writeonlypropbark", sol::property(&ext_getset::set)
);
INFO("usertype created"); INFO("usertype created");
@ -1129,7 +1142,7 @@ y = e.sget(20)
int y = lua["y"]; int y = lua["y"];
REQUIRE(x == 500); REQUIRE(x == 500);
REQUIRE(y == 40); REQUIRE(y == 40);
INFO("REQUIRE(x, y) successful"); INFO("REQUIRE(x, y) successful");
lua.safe_script(R"( lua.safe_script(R"(
@ -1197,8 +1210,12 @@ print(e.bark)
TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") { TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") {
struct NoCopy { struct NoCopy {
int get() const { return _you_can_copy_me; } int get() const {
void set(int val) { _you_can_copy_me = val; } return _you_can_copy_me;
}
void set(int val) {
_you_can_copy_me = val;
}
int _you_can_copy_me; int _you_can_copy_me;
non_copyable _haha_you_cant_copy_me; non_copyable _haha_you_cant_copy_me;
@ -1211,8 +1228,7 @@ TEST_CASE("usertype/copyability", "make sure user can write to a class variable
lua.safe_script(R"__( lua.safe_script(R"__(
nocopy = NoCopy.new() nocopy = NoCopy.new()
nocopy.val = 5 nocopy.val = 5
)__") )__"));
);
} }
TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") { TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") {
@ -1224,16 +1240,14 @@ TEST_CASE("usertype/protect", "users should be allowed to manually protect a fun
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<protect_me>("protect_me", lua.new_usertype<protect_me>("protect_me",
"gen", sol::protect( &protect_me::gen ) "gen", sol::protect(&protect_me::gen));
);
REQUIRE_NOTHROW( REQUIRE_NOTHROW(
lua.safe_script(R"__( lua.safe_script(R"__(
pm = protect_me.new() pm = protect_me.new()
value = pcall(pm.gen,pm) value = pcall(pm.gen,pm)
)__") )__"));
);
bool value = lua["value"]; bool value = lua["value"];
REQUIRE_FALSE(value); REQUIRE_FALSE(value);
} }
@ -1250,8 +1264,7 @@ TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
"global", sol::var(muh_variable), "global", sol::var(muh_variable),
"ref_global", sol::var(std::ref(muh_variable)), "ref_global", sol::var(std::ref(muh_variable)),
"global2", sol::var(through_variable), "global2", sol::var(through_variable),
"ref_global2", sol::var(std::ref(through_variable)) "ref_global2", sol::var(std::ref(through_variable)));
);
int prets = lua["test"]["straight"]; int prets = lua["test"]["straight"];
int pretg = lua["test"]["global"]; int pretg = lua["test"]["global"];
@ -1283,7 +1296,6 @@ print(t.global)
REQUIRE(mv == 50); REQUIRE(mv == 50);
REQUIRE(muh_variable == 25); REQUIRE(muh_variable == 25);
lua.safe_script(R"( lua.safe_script(R"(
print(t.ref_global) print(t.ref_global)
t.ref_global = 50 t.ref_global = 50
@ -1334,8 +1346,7 @@ TEST_CASE("usertype/static-properties", "allow for static functions to get and s
lua.new_usertype<test_t>("test", lua.new_usertype<test_t>("test",
"f", std::function<std::size_t()>(std::bind(std::mem_fn(&test_t::func), &manager)), "f", std::function<std::size_t()>(std::bind(std::mem_fn(&test_t::func), &manager)),
"g", sol::property(&test_t::s_func, &test_t::g_func) "g", sol::property(&test_t::s_func, &test_t::g_func));
);
lua.safe_script("v1 = test.f()"); lua.safe_script("v1 = test.f()");
lua.safe_script("v2 = test.g"); lua.safe_script("v2 = test.g");
@ -1360,16 +1371,8 @@ TEST_CASE("usertype/var-and-property", "make sure const vars are readonly and pr
lua.open_libraries(); lua.open_libraries();
lua.new_usertype<test>("test", lua.new_usertype<test>("test",
"prop", sol::property( "prop", sol::property([](test& t) { return t.value; }, [](test& t, int x) { t.value = x; }),
[](test& t) { "global", sol::var(std::ref(arf)));
return t.value;
},
[](test& t, int x) {
t.value = x;
}
),
"global", sol::var(std::ref(arf))
);
lua.safe_script(R"( lua.safe_script(R"(
t = test.new() t = test.new()
@ -1405,8 +1408,7 @@ TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't ge
lua.new_usertype<Entity>("Entity", lua.new_usertype<Entity>("Entity",
"new", sol::no_constructor, "new", sol::no_constructor,
"get_name", &Entity::GetName "get_name", &Entity::GetName);
);
lua.safe_script(R"( lua.safe_script(R"(
function my_func(entity) function my_func(entity)
@ -1416,7 +1418,7 @@ TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't ge
)"); )");
sol::function my_func = lua["my_func"]; sol::function my_func = lua["my_func"];
REQUIRE_NOTHROW([&]{ REQUIRE_NOTHROW([&] {
auto ent = std::make_shared<Entity>(); auto ent = std::make_shared<Entity>();
my_func(ent); my_func(ent);
Entity ent2; Entity ent2;
@ -1425,7 +1427,7 @@ TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't ge
}()); }());
} }
TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") { TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
sol::state lua; sol::state lua;
lua.new_usertype<abstract_A>("A", "a", &abstract_A::a); lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);
lua.new_usertype<abstract_B>("B", sol::base_classes, sol::bases<abstract_A>()); lua.new_usertype<abstract_B>("B", sol::base_classes, sol::bases<abstract_A>());
@ -1470,8 +1472,7 @@ TEST_CASE("usertype/call-initializers", "Ensure call constructors with initializ
lua.open_libraries(); lua.open_libraries();
lua.new_usertype<A>("A", lua.new_usertype<A>("A",
sol::call_constructor, sol::initializers(&A::init) sol::call_constructor, sol::initializers(&A::init));
);
lua.safe_script(R"( lua.safe_script(R"(
a = A(24.3) a = A(24.3)
@ -1496,7 +1497,9 @@ TEST_CASE("usertype/missing-key", "make sure a missing key returns nil") {
TEST_CASE("usertype/runtime-extensibility", "Check if usertypes are runtime extensible") { TEST_CASE("usertype/runtime-extensibility", "Check if usertypes are runtime extensible") {
struct thing { struct thing {
int v = 20; int v = 20;
int func(int a) { return a; } int func(int a) {
return a;
}
}; };
int val = 0; int val = 0;
@ -1505,8 +1508,7 @@ TEST_CASE("usertype/runtime-extensibility", "Check if usertypes are runtime exte
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
"func", &thing::func "func", &thing::func);
);
lua.safe_script(R"( lua.safe_script(R"(
t = thing.new() t = thing.new()
@ -1517,7 +1519,8 @@ t = thing.new()
t.runtime_func = function (a) t.runtime_func = function (a)
return a + 50 return a + 50
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
}; };
@ -1526,7 +1529,8 @@ end
function t:runtime_func(a) function t:runtime_func(a)
return a + 52 return a + 52
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
}; };
@ -1552,8 +1556,7 @@ end
lua.new_usertype<thing>("thing", lua.new_usertype<thing>("thing",
"func", &thing::func, "func", &thing::func,
"v", &thing::v "v", &thing::v);
);
lua.safe_script(R"( lua.safe_script(R"(
t = thing.new() t = thing.new()
@ -1564,7 +1567,8 @@ t = thing.new()
t.runtime_func = function (a) t.runtime_func = function (a)
return a + 50 return a + 50
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
}; };
@ -1573,7 +1577,8 @@ end
function t:runtime_func(a) function t:runtime_func(a)
return a + 52 return a + 52
end end
)", sol::script_pass_on_error); )",
sol::script_pass_on_error);
REQUIRE_FALSE(result.valid()); REQUIRE_FALSE(result.valid());
}; };
@ -1598,7 +1603,8 @@ end
TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") { TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") {
struct heart_base_t {}; struct heart_base_t {};
struct heart_t : heart_base_t { struct heart_t : heart_base_t {
void func() {} void func() {
}
}; };
SECTION("plain") { SECTION("plain") {
@ -1627,8 +1633,7 @@ TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<heart_t>("a", lua.new_usertype<heart_t>("a",
sol::base_classes, sol::bases<heart_base_t>() sol::base_classes, sol::bases<heart_base_t>());
);
REQUIRE_NOTHROW([&lua]() { REQUIRE_NOTHROW([&lua]() {
lua.safe_script("obj = a.new()"); lua.safe_script("obj = a.new()");
@ -1652,8 +1657,7 @@ TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly
lua.new_usertype<heart_t>("a", lua.new_usertype<heart_t>("a",
"func", &heart_t::func, "func", &heart_t::func,
sol::base_classes, sol::bases<heart_base_t>() sol::base_classes, sol::bases<heart_base_t>());
);
REQUIRE_NOTHROW([&lua]() { REQUIRE_NOTHROW([&lua]() {
lua.safe_script("obj = a.new()"); lua.safe_script("obj = a.new()");
@ -1692,7 +1696,6 @@ TEST_CASE("usertype/meta-key-retrievals", "allow for special meta keys (__index,
s[sol::metatable_key][sol::meta_function::new_index] = &d_sample::foo; s[sol::metatable_key][sol::meta_function::new_index] = &d_sample::foo;
lua["var"] = s; lua["var"] = s;
lua.safe_script("var = sample.new()"); lua.safe_script("var = sample.new()");
lua.safe_script("var.key = 2"); lua.safe_script("var.key = 2");
lua.safe_script("var.__newindex = 4"); lua.safe_script("var.__newindex = 4");
@ -1751,10 +1754,9 @@ TEST_CASE("usertype/noexcept-methods", "make sure noexcept functinos and methods
}; };
sol::state lua; sol::state lua;
lua.new_usertype<T>("T", lua.new_usertype<T>("T",
"nf", &T::noexcept_function, "nf", &T::noexcept_function,
"nm", &T::noexcept_method "nm", &T::noexcept_method);
);
lua.safe_script("t = T.new()"); lua.safe_script("t = T.new()");
lua.safe_script("v1 = t.nf()"); lua.safe_script("v1 = t.nf()");

View File

@ -14,7 +14,7 @@
std::mutex basic_init_require_mutex; std::mutex basic_init_require_mutex;
void basic_initialization_and_lib_open() { void basic_initialization_and_lib_open() {
sol::state lua; sol::state lua;
try { try {
lua.open_libraries(); lua.open_libraries();
@ -36,7 +36,6 @@ void basic_initialization_and_lib_open() {
} }
} }
TEST_CASE("utility/variant", "test that variant can be round-tripped") { TEST_CASE("utility/variant", "test that variant can be round-tripped") {
#ifdef SOL_CXX17_FEATURES #ifdef SOL_CXX17_FEATURES
SECTION("okay") { SECTION("okay") {
@ -134,8 +133,7 @@ TEST_CASE("utility/this_state", "Ensure this_state argument can be gotten anywhe
INFO("created lua state"); INFO("created lua state");
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<bark>("bark", lua.new_usertype<bark>("bark",
"with_state", &bark::with_state "with_state", &bark::with_state);
);
INFO("setting b and with_state_2"); INFO("setting b and with_state_2");
bark b; bark b;

View File

@ -22,7 +22,7 @@ TEST_CASE("variadics/variadic_args", "Check to see we can receive multiple argum
int value = v; int value = v;
r += value; r += value;
} }
return{ r, r > 200 }; return { r, r > 200 };
}); });
lua.safe_script("x = v(25, 25)"); lua.safe_script("x = v(25, 25)");
@ -44,8 +44,7 @@ TEST_CASE("variadics/required with variadic_args", "Check if a certain number of
sol::state lua; sol::state lua;
lua.set_function("v", lua.set_function("v",
[](sol::this_state, sol::variadic_args, int, int) { [](sol::this_state, sol::variadic_args, int, int) {
} });
);
REQUIRE_NOTHROW(lua.safe_script("v(20, 25, 30)")); REQUIRE_NOTHROW(lua.safe_script("v(20, 25, 30)"));
REQUIRE_NOTHROW(lua.safe_script("v(20, 25)")); REQUIRE_NOTHROW(lua.safe_script("v(20, 25)"));
auto result = lua.safe_script("v(20)", sol::script_pass_on_error); auto result = lua.safe_script("v(20)", sol::script_pass_on_error);
@ -181,16 +180,14 @@ TEST_CASE("variadics/variadic_results", "returning a variable amount of argument
} }
TEST_CASE("variadics/fallback_constructor", "ensure constructor matching behaves properly in the presence of variadic fallbacks") { TEST_CASE("variadics/fallback_constructor", "ensure constructor matching behaves properly in the presence of variadic fallbacks") {
struct vec2 { float x = 0, y = 0; }; struct vec2 {
float x = 0, y = 0;
};
sol::state lua; sol::state lua;
lua.new_simple_usertype<vec2>("vec2", lua.new_simple_usertype<vec2>("vec2",
sol::call_constructor, sol::factories([]() { sol::call_constructor, sol::factories([]() { return vec2{}; }, [](vec2 const& v) -> vec2 { return v; }, [](sol::variadic_args va) {
return vec2{};
}, [](vec2 const& v) -> vec2 {
return v;
}, [](sol::variadic_args va) {
vec2 res{}; vec2 res{};
if (va.size() == 1) { if (va.size() == 1) {
res.x = va[0].get<float>(); res.x = va[0].get<float>();
@ -203,9 +200,7 @@ TEST_CASE("variadics/fallback_constructor", "ensure constructor matching behaves
else { else {
throw sol::error("invalid args"); throw sol::error("invalid args");
} }
return res; return res; }));
})
);
REQUIRE_NOTHROW([&]() { REQUIRE_NOTHROW([&]() {
lua.safe_script("v0 = vec2();"); lua.safe_script("v0 = vec2();");

View File

@ -13,12 +13,10 @@
#include "test_stack_guard.hpp" #include "test_stack_guard.hpp"
bool func_opt_ret_bool(sol::optional<int> i) { bool func_opt_ret_bool(sol::optional<int> i) {
if (i) if (i) {
{
INFO(i.value()); INFO(i.value());
} }
else else {
{
INFO("optional isn't set"); INFO("optional isn't set");
} }
return true; return true;
@ -35,39 +33,45 @@ TEST_CASE("table/traversal", "ensure that we can chain requests and tunnel down
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
int traversex24 = lua.traverse_get<int>("t1", "t2", "t3"); int traversex24 = lua.traverse_get<int>("t1", "t2", "t3");
REQUIRE(traversex24 == 24); REQUIRE(traversex24 == 24);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
int x24 = lua["t1"]["t2"]["t3"]; int x24 = lua["t1"]["t2"]["t3"];
REQUIRE(x24 == 24); REQUIRE(x24 == 24);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
lua["t1"]["t2"]["t3"] = 64; lua["t1"]["t2"]["t3"] = 64;
int traversex64 = lua.traverse_get<int>("t1", "t2", "t3"); int traversex64 = lua.traverse_get<int>("t1", "t2", "t3");
REQUIRE(traversex64 == 64); REQUIRE(traversex64 == 64);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
int x64 = lua["t1"]["t2"]["t3"]; int x64 = lua["t1"]["t2"]["t3"];
REQUIRE(x64 == 64); REQUIRE(x64 == 64);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
lua.traverse_set("t1", "t2", "t3", 13); lua.traverse_set("t1", "t2", "t3", 13);
int traversex13 = lua.traverse_get<int>("t1", "t2", "t3"); int traversex13 = lua.traverse_get<int>("t1", "t2", "t3");
REQUIRE(traversex13 == 13); REQUIRE(traversex13 == 13);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
int x13 = lua["t1"]["t2"]["t3"]; int x13 = lua["t1"]["t2"]["t3"];
REQUIRE(x13 == 13); REQUIRE(x13 == 13);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
} }
TEST_CASE("simple/set", "Check if the set works properly.") { TEST_CASE("simple/set", "Check if the set works properly.") {
@ -76,18 +80,21 @@ TEST_CASE("simple/set", "Check if the set works properly.") {
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
lua.set("a", 9); lua.set("a", 9);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
REQUIRE_NOTHROW(lua.safe_script("if a ~= 9 then error('wrong value') end")); REQUIRE_NOTHROW(lua.safe_script("if a ~= 9 then error('wrong value') end"));
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
lua.set("d", "hello"); lua.set("d", "hello");
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
REQUIRE_NOTHROW(lua.safe_script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); REQUIRE_NOTHROW(lua.safe_script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end"));
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
lua.set("e", std::string("hello"), "f", true); lua.set("e", std::string("hello"), "f", true);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
REQUIRE_NOTHROW(lua.safe_script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); REQUIRE_NOTHROW(lua.safe_script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end"));
REQUIRE_NOTHROW(lua.safe_script("if f ~= true then error('wrong value') end")); REQUIRE_NOTHROW(lua.safe_script("if f ~= true then error('wrong value') end"));
} }
@ -101,13 +108,15 @@ TEST_CASE("simple/get", "Tests if the get function works properly.") {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
auto a = lua.get<int>("a"); auto a = lua.get<int>("a");
REQUIRE(a == 9.0); REQUIRE(a == 9.0);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
lua.safe_script("b = nil"); lua.safe_script("b = nil");
{ {
test_stack_guard g(lua.lua_state(), begintop, endtop); test_stack_guard g(lua.lua_state(), begintop, endtop);
REQUIRE_NOTHROW(lua.get<sol::nil_t>("b")); REQUIRE_NOTHROW(lua.get<sol::nil_t>("b"));
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
lua.safe_script("d = 'hello'"); lua.safe_script("d = 'hello'");
lua.safe_script("e = true"); lua.safe_script("e = true");
@ -118,7 +127,8 @@ TEST_CASE("simple/get", "Tests if the get function works properly.") {
std::tie(d, e) = lua.get<std::string, bool>("d", "e"); std::tie(d, e) = lua.get<std::string, bool>("d", "e");
REQUIRE(d == "hello"); REQUIRE(d == "hello");
REQUIRE(e == true); REQUIRE(e == true);
} REQUIRE(begintop == endtop); }
REQUIRE(begintop == endtop);
} }
TEST_CASE("simple/set and get global integer", "Tests if the get function works properly with global integers") { TEST_CASE("simple/set and get global integer", "Tests if the get function works properly with global integers") {
@ -223,7 +233,8 @@ TEST_CASE("interop/null-to-nil-and-back", "nil should be the given type when a p
lua.set_function("rofl", [](int* x) { lua.set_function("rofl", [](int* x) {
INFO(x); INFO(x);
}); });
REQUIRE_NOTHROW(lua.safe_script("x = lol()\n" REQUIRE_NOTHROW(lua.safe_script(
"x = lol()\n"
"rofl(x)\n" "rofl(x)\n"
"assert(x == nil)")); "assert(x == nil)"));
} }
@ -338,14 +349,12 @@ TEST_CASE("object/main_* conversions", "make sure all basic reference types can
TEST_CASE("feature/indexing overrides", "make sure index functions can be overridden on types") { TEST_CASE("feature/indexing overrides", "make sure index functions can be overridden on types") {
struct PropertySet { struct PropertySet {
sol::object get_property_lua(const char* name, sol::this_state s) sol::object get_property_lua(const char* name, sol::this_state s) {
{
auto& var = props[name]; auto& var = props[name];
return sol::make_object(s, var); return sol::make_object(s, var);
} }
void set_property_lua(const char* name, sol::stack_object object) void set_property_lua(const char* name, sol::stack_object object) {
{
props[name] = object.as<std::string>(); props[name] = object.as<std::string>();
} }
@ -363,13 +372,8 @@ TEST_CASE("feature/indexing overrides", "make sure index functions can be overri
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<PropertySet>("PropertySet" lua.new_usertype<PropertySet>("PropertySet", sol::meta_function::new_index, &PropertySet::set_property_lua, sol::meta_function::index, &PropertySet::get_property_lua);
, sol::meta_function::new_index, &PropertySet::set_property_lua lua.new_usertype<DynamicObject>("DynamicObject", "props", sol::property(&DynamicObject::get_dynamic_props));
, sol::meta_function::index, &PropertySet::get_property_lua
);
lua.new_usertype<DynamicObject>("DynamicObject"
, "props", sol::property(&DynamicObject::get_dynamic_props)
);
lua.safe_script(R"__( lua.safe_script(R"__(
obj = DynamicObject:new() obj = DynamicObject:new()
@ -386,21 +390,19 @@ TEST_CASE("features/indexing numbers", "make sure indexing functions can be over
public: public:
double data[3]; double data[3];
vector() : data{ 0,0,0 } {} vector()
: data{ 0, 0, 0 } {
}
double& operator[](int i) double& operator[](int i) {
{
return data[i]; return data[i];
} }
static double my_index(vector& v, int i) {
static double my_index(vector& v, int i)
{
return v[i]; return v[i];
} }
static void my_new_index(vector& v, int i, double x) static void my_new_index(vector& v, int i, double x) {
{
v[i] = x; v[i] = x;
} }
}; };
@ -410,11 +412,11 @@ TEST_CASE("features/indexing numbers", "make sure indexing functions can be over
lua.new_usertype<vector>("vector", sol::constructors<sol::types<>>(), lua.new_usertype<vector>("vector", sol::constructors<sol::types<>>(),
sol::meta_function::index, &vector::my_index, sol::meta_function::index, &vector::my_index,
sol::meta_function::new_index, &vector::my_new_index); sol::meta_function::new_index, &vector::my_new_index);
lua.safe_script("v = vector.new()\n" lua.safe_script(
"v = vector.new()\n"
"print(v[1])\n" "print(v[1])\n"
"v[2] = 3\n" "v[2] = 3\n"
"print(v[2])\n" "print(v[2])\n");
);
vector& v = lua["v"]; vector& v = lua["v"];
REQUIRE(v[0] == 0.0); REQUIRE(v[0] == 0.0);
@ -432,36 +434,29 @@ TEST_CASE("features/multiple inheritance", "Ensure that multiple inheritance wor
}; };
struct simple : base1 { struct simple : base1 {
}; };
struct complex : base1, base2 { struct complex : base1, base2 {
}; };
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<base1>("base1", lua.new_usertype<base1>("base1",
"a1", &base1::a1 "a1", &base1::a1);
);
lua.new_usertype<base2>("base2", lua.new_usertype<base2>("base2",
"a2", &base2::a2 "a2", &base2::a2);
);
lua.new_usertype<simple>("simple", lua.new_usertype<simple>("simple",
"a1", &simple::a1, "a1", &simple::a1,
sol::base_classes, sol::bases<base1>() sol::base_classes, sol::bases<base1>());
);
lua.new_usertype<complex>("complex", lua.new_usertype<complex>("complex",
"a1", &complex::a1, "a1", &complex::a1,
"a2", &complex::a2, "a2", &complex::a2,
sol::base_classes, sol::bases<base1, base2>() sol::base_classes, sol::bases<base1, base2>());
); lua.safe_script(
lua.safe_script("c = complex.new()\n" "c = complex.new()\n"
"s = simple.new()\n" "s = simple.new()\n"
"b1 = base1.new()\n" "b1 = base1.new()\n"
"b2 = base1.new()\n" "b2 = base1.new()\n");
);
base1* sb1 = lua["s"]; base1* sb1 = lua["s"];
REQUIRE(sb1 != nullptr); REQUIRE(sb1 != nullptr);
@ -476,7 +471,6 @@ TEST_CASE("features/multiple inheritance", "Ensure that multiple inheritance wor
REQUIRE(cb2->a2 == 500); 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") { TEST_CASE("regressions/std::ref", "Ensure that std::reference_wrapper<> isn't considered as a function by using unwrap_unqualified_t trait") {
struct base1 { struct base1 {
int a1 = 250; int a1 = 250;
@ -494,7 +488,7 @@ TEST_CASE("regressions/std::ref", "Ensure that std::reference_wrapper<> isn't co
REQUIRE(vp->a1 == 250); REQUIRE(vp->a1 == 250);
REQUIRE(vr.a1 == 250); REQUIRE(vr.a1 == 250);
v.a1 = 568; v.a1 = 568;
REQUIRE(vp->a1 == 568); REQUIRE(vp->a1 == 568);
@ -508,8 +502,8 @@ TEST_CASE("optional/left out args", "Make sure arguments can be left out of opti
// sol::optional needs an argument no matter what? // sol::optional needs an argument no matter what?
lua.set_function("func_opt_ret_bool", func_opt_ret_bool); lua.set_function("func_opt_ret_bool", func_opt_ret_bool);
REQUIRE_NOTHROW([&]{ REQUIRE_NOTHROW([&] {
lua.safe_script(R"( lua.safe_script(R"(
func_opt_ret_bool(42) func_opt_ret_bool(42)
func_opt_ret_bool() func_opt_ret_bool()
print('ok') print('ok')
@ -519,18 +513,21 @@ TEST_CASE("optional/left out args", "Make sure arguments can be left out of opti
TEST_CASE("pusher/constness", "Make sure more types can handle being const and junk") { TEST_CASE("pusher/constness", "Make sure more types can handle being const and junk") {
struct Foo { struct Foo {
Foo(const sol::function& f) : _f(f) {} Foo(const sol::function& f)
: _f(f) {
}
const sol::function& _f; const sol::function& _f;
const sol::function& f() const { return _f; } const sol::function& f() const {
return _f;
}
}; };
sol::state lua; sol::state lua;
lua.new_usertype<Foo>("Foo", lua.new_usertype<Foo>("Foo",
sol::call_constructor, sol::no_constructor, sol::call_constructor, sol::no_constructor,
"f", &Foo::f "f", &Foo::f);
);
lua["func"] = []() { return 20; }; lua["func"] = []() { return 20; };
sol::function f = lua["func"]; sol::function f = lua["func"];
@ -561,13 +558,13 @@ TEST_CASE("proxy/equality", "check to make sure equality tests work") {
REQUIRE_FALSE((lua["a"] == nullptr)); REQUIRE_FALSE((lua["a"] == nullptr));
REQUIRE_FALSE((lua["a"] == 0)); REQUIRE_FALSE((lua["a"] == 0));
REQUIRE_FALSE((lua["a"] == 2)); REQUIRE_FALSE((lua["a"] == 2));
lua["a"] = 2; lua["a"] = 2;
REQUIRE_FALSE((lua["a"] == sol::nil)); //0 REQUIRE_FALSE((lua["a"] == sol::nil)); //0
REQUIRE_FALSE((lua["a"] == nullptr)); //0 REQUIRE_FALSE((lua["a"] == nullptr)); //0
REQUIRE_FALSE((lua["a"] == 0)); //0 REQUIRE_FALSE((lua["a"] == 0)); //0
REQUIRE((lua["a"] == 2)); //1 REQUIRE((lua["a"] == 2)); //1
} }
TEST_CASE("compilation/const regression", "make sure constness in tables is respected all the way down") { TEST_CASE("compilation/const regression", "make sure constness in tables is respected all the way down") {
@ -588,7 +585,7 @@ TEST_CASE("compilation/const regression", "make sure constness in tables is resp
TEST_CASE("numbers/integers", "make sure integers are detectable on most platforms") { TEST_CASE("numbers/integers", "make sure integers are detectable on most platforms") {
sol::state lua; sol::state lua;
lua["a"] = 50; // int lua["a"] = 50; // int
lua["b"] = 50.5; // double lua["b"] = 50.5; // double
sol::object a = lua["a"]; sol::object a = lua["a"];
@ -611,17 +608,15 @@ TEST_CASE("numbers/integers", "make sure integers are detectable on most platfor
TEST_CASE("object/is", "test whether or not the is abstraction works properly for a user-defined type") { TEST_CASE("object/is", "test whether or not the is abstraction works properly for a user-defined type") {
struct thing {}; struct thing {};
SECTION("stack_object") SECTION("stack_object") {
{
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.set_function("is_thing", [](sol::stack_object obj) { return obj.is<thing>(); } ); lua.set_function("is_thing", [](sol::stack_object obj) { return obj.is<thing>(); });
lua["a"] = thing{}; lua["a"] = thing{};
REQUIRE_NOTHROW(lua.safe_script("assert(is_thing(a))")); REQUIRE_NOTHROW(lua.safe_script("assert(is_thing(a))"));
} }
SECTION("object") SECTION("object") {
{
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.set_function("is_thing", [](sol::object obj) { return obj.is<thing>(); }); lua.set_function("is_thing", [](sol::object obj) { return obj.is<thing>(); });