From 7aae1aaaaa1bbcc03fd059fe38075cfe3f4b2e90 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 6 May 2021 18:44:25 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20asdhjsahd=20DO=20NOT=20BUILD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add a flag to allow size_t(-1) and similar shenanigans (SOL_ALL_INTEGER_VALUES_FIT) - Half-fix, but not fully, for #1183, #1072, #1038, #965 - Fix #1126 - Prepare for #1061 --- .github/workflows/{macosx.yml => macos.yml} | 2 +- CMakeLists.txt | 51 +-- cmake/Includes/Project.cmake | 77 ++++ cmake/Modules/CheckCompilerDiagnostic.cmake | 93 +++++ cmake/Modules/CheckCompilerFlag.cmake | 83 +++++ cmake/Modules/FindVersion.cmake | 61 ++++ .../FindKaguyaBuild.cmake | 0 .../FindLua/set_version_vars.cmake | 0 .../FindLua/version_check.cmake | 0 .../FindLuaBridgeBuild.cmake | 0 .../{Modules => Packages}/FindLuaBuild.cmake | 0 .../FindLuaBuild/LuaJIT.cmake | 0 .../FindLuaBuild/LuaVanilla.cmake | 0 .../FindLuwraBuild.cmake | 0 cmake/{Modules => Packages}/FindSphinx.cmake | 0 .../FindToLuappBuild.cmake | 0 documentation/CMakeLists.txt | 5 +- documentation/source/api/environment.rst | 2 +- examples/CMakeLists.txt | 79 ++-- examples/source/environments_on_functions.cpp | 7 +- examples/source/pairs.cpp | 2 +- examples/source/pairs_with_raw_functions.cpp | 2 +- .../source/usertype_automatic_operators.cpp | 2 +- include/sol/compatibility/lua_version.hpp | 6 +- include/sol/coroutine.hpp | 2 +- include/sol/environment.hpp | 62 +++- include/sol/function_types.hpp | 31 +- include/sol/packaged_coroutine.hpp | 2 +- include/sol/reference.hpp | 2 +- include/sol/stack_check_get_unqualified.hpp | 2 +- include/sol/stack_check_unqualified.hpp | 2 +- include/sol/stack_core.hpp | 2 +- include/sol/stack_field.hpp | 18 +- include/sol/stack_get_unqualified.hpp | 12 +- include/sol/stack_push.hpp | 58 ++- include/sol/state_handling.hpp | 2 +- include/sol/state_view.hpp | 24 +- include/sol/usertype_storage.hpp | 78 ++-- include/sol/version.hpp | 14 + tests/CMakeLists.txt | 60 +++- tests/config_tests/CMakeLists.txt | 1 + .../integer_value_fits/CMakeLists.txt | 36 ++ .../integer_value_fits/source/main.cpp | 30 ++ .../source/negative_size_t.cpp | 51 +++ tests/environment/CMakeLists.txt | 33 ++ tests/environment/source/get.cpp | 132 +++++++ tests/environment/source/main.cpp | 30 ++ tests/environment/source/sandboxing.cpp | 92 +++++ tests/environment/source/shadowing.cpp | 111 ++++++ tests/environment/source/this_environment.cpp | 93 +++++ tests/exceptions/CMakeLists.txt | 40 +++ tests/exceptions/source/functions.cpp | 192 ++++++++++ .../exceptions/source/functions.noexcept.cpp | 95 +++++ .../exceptions/source/functions.yielding.cpp | 30 ++ tests/exceptions/source/main.cpp | 30 ++ tests/exceptions/source/usertypes.cpp | 30 ++ .../exceptions/source/usertypes.yielding.cpp | 30 ++ tests/inclusion/CMakeLists.txt | 95 ++--- tests/numerics/CMakeLists.txt | 34 ++ .../source/large.cpp} | 336 +++++++++--------- tests/numerics/source/main.cpp | 30 ++ tests/run_time/CMakeLists.txt | 33 ++ .../source/basic.cpp | 0 .../source/common_classes.hpp | 0 .../source/container.usertype_check.cpp | 0 .../source/container_semantics.cpp | 0 .../source/container_semantics.custom.cpp | 0 .../source/container_semantics.ordered.cpp | 2 +- .../source/container_semantics.unordered.cpp | 0 .../source/container_shims.cpp | 2 +- .../source/container_table.cpp | 0 .../source/containers.cpp | 0 .../source/containers.roundtrip.cpp | 0 .../source/containers.table.cpp | 0 .../source/coroutines.cpp | 3 +- .../source/customizations.cpp | 0 .../source/customizations_private.cpp | 0 .../source/dump.cpp | 0 .../source/functions.cpp | 59 --- .../source/functions.std.cpp | 0 .../{runtime_tests => run_time}/source/gc.cpp | 0 .../source/lua_value.cpp | 0 tests/run_time/source/main.cpp | 30 ++ .../source/operators.cpp | 4 +- .../source/overflow.cpp | 0 .../source/plain_types.cpp | 2 +- .../source/policies.cpp | 0 .../source/proxies.cpp | 0 .../source/sol_test.hpp | 0 .../source/state.cpp | 0 .../source/storage.cpp | 0 .../source/strings.cpp | 0 .../source/tables.checks.cpp | 0 .../source/tables.clear.cpp | 0 .../source/tables.cpp | 0 .../source/tables.enums.cpp | 0 .../source/tables.indexing.cpp | 0 .../source/tables.insertion.cpp | 0 .../source/tables.traversal.cpp | 0 .../source/usertypes.auxiliary_keys.cpp | 0 .../source/usertypes.basic.cpp | 0 .../source/usertypes.constructors.cpp | 107 ++++++ .../source/usertypes.cpp | 0 .../source/usertypes.inheritance.cpp | 0 .../source/usertypes.inheritance.multi.cpp | 0 .../source/usertypes.member_variables.cpp | 0 .../source/usertypes.overload.cpp | 0 .../source/usertypes.properties.cpp | 0 .../source/usertypes.runtime.cpp | 0 .../source/usertypes.unique.cpp | 0 .../source/usertypes.unregister.cpp | 0 .../source/utility.cpp | 0 .../source/variadics.cpp | 0 tests/runtime_tests/CMakeLists.txt | 97 ----- tests/runtime_tests/source/environments.cpp | 312 ---------------- tests/runtime_tests/source/main.cpp | 7 - 116 files changed, 2127 insertions(+), 925 deletions(-) rename .github/workflows/{macosx.yml => macos.yml} (95%) create mode 100644 cmake/Includes/Project.cmake create mode 100644 cmake/Modules/CheckCompilerDiagnostic.cmake create mode 100644 cmake/Modules/CheckCompilerFlag.cmake create mode 100644 cmake/Modules/FindVersion.cmake rename cmake/{Modules => Packages}/FindKaguyaBuild.cmake (100%) rename cmake/{Modules => Packages}/FindLua/set_version_vars.cmake (100%) rename cmake/{Modules => Packages}/FindLua/version_check.cmake (100%) rename cmake/{Modules => Packages}/FindLuaBridgeBuild.cmake (100%) rename cmake/{Modules => Packages}/FindLuaBuild.cmake (100%) rename cmake/{Modules => Packages}/FindLuaBuild/LuaJIT.cmake (100%) rename cmake/{Modules => Packages}/FindLuaBuild/LuaVanilla.cmake (100%) rename cmake/{Modules => Packages}/FindLuwraBuild.cmake (100%) rename cmake/{Modules => Packages}/FindSphinx.cmake (100%) rename cmake/{Modules => Packages}/FindToLuappBuild.cmake (100%) create mode 100644 tests/config_tests/integer_value_fits/CMakeLists.txt create mode 100644 tests/config_tests/integer_value_fits/source/main.cpp create mode 100644 tests/config_tests/integer_value_fits/source/negative_size_t.cpp create mode 100644 tests/environment/CMakeLists.txt create mode 100644 tests/environment/source/get.cpp create mode 100644 tests/environment/source/main.cpp create mode 100644 tests/environment/source/sandboxing.cpp create mode 100644 tests/environment/source/shadowing.cpp create mode 100644 tests/environment/source/this_environment.cpp create mode 100644 tests/exceptions/CMakeLists.txt create mode 100644 tests/exceptions/source/functions.cpp create mode 100644 tests/exceptions/source/functions.noexcept.cpp create mode 100644 tests/exceptions/source/functions.yielding.cpp create mode 100644 tests/exceptions/source/main.cpp create mode 100644 tests/exceptions/source/usertypes.cpp create mode 100644 tests/exceptions/source/usertypes.yielding.cpp create mode 100644 tests/numerics/CMakeLists.txt rename tests/{runtime_tests/source/large_integer.cpp => numerics/source/large.cpp} (95%) create mode 100644 tests/numerics/source/main.cpp create mode 100644 tests/run_time/CMakeLists.txt rename tests/{runtime_tests => run_time}/source/basic.cpp (100%) rename tests/{runtime_tests => run_time}/source/common_classes.hpp (100%) rename tests/{runtime_tests => run_time}/source/container.usertype_check.cpp (100%) rename tests/{runtime_tests => run_time}/source/container_semantics.cpp (100%) rename tests/{runtime_tests => run_time}/source/container_semantics.custom.cpp (100%) rename tests/{runtime_tests => run_time}/source/container_semantics.ordered.cpp (96%) rename tests/{runtime_tests => run_time}/source/container_semantics.unordered.cpp (100%) rename tests/{runtime_tests => run_time}/source/container_shims.cpp (95%) rename tests/{runtime_tests => run_time}/source/container_table.cpp (100%) rename tests/{runtime_tests => run_time}/source/containers.cpp (100%) rename tests/{runtime_tests => run_time}/source/containers.roundtrip.cpp (100%) rename tests/{runtime_tests => run_time}/source/containers.table.cpp (100%) rename tests/{runtime_tests => run_time}/source/coroutines.cpp (99%) rename tests/{runtime_tests => run_time}/source/customizations.cpp (100%) rename tests/{runtime_tests => run_time}/source/customizations_private.cpp (100%) rename tests/{runtime_tests => run_time}/source/dump.cpp (100%) rename tests/{runtime_tests => run_time}/source/functions.cpp (96%) rename tests/{runtime_tests => run_time}/source/functions.std.cpp (100%) rename tests/{runtime_tests => run_time}/source/gc.cpp (100%) rename tests/{runtime_tests => run_time}/source/lua_value.cpp (100%) create mode 100644 tests/run_time/source/main.cpp rename tests/{runtime_tests => run_time}/source/operators.cpp (99%) rename tests/{runtime_tests => run_time}/source/overflow.cpp (100%) rename tests/{runtime_tests => run_time}/source/plain_types.cpp (99%) rename tests/{runtime_tests => run_time}/source/policies.cpp (100%) rename tests/{runtime_tests => run_time}/source/proxies.cpp (100%) rename tests/{runtime_tests => run_time}/source/sol_test.hpp (100%) rename tests/{runtime_tests => run_time}/source/state.cpp (100%) rename tests/{runtime_tests => run_time}/source/storage.cpp (100%) rename tests/{runtime_tests => run_time}/source/strings.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.checks.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.clear.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.enums.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.indexing.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.insertion.cpp (100%) rename tests/{runtime_tests => run_time}/source/tables.traversal.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.auxiliary_keys.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.basic.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.constructors.cpp (68%) rename tests/{runtime_tests => run_time}/source/usertypes.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.inheritance.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.inheritance.multi.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.member_variables.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.overload.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.properties.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.runtime.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.unique.cpp (100%) rename tests/{runtime_tests => run_time}/source/usertypes.unregister.cpp (100%) rename tests/{runtime_tests => run_time}/source/utility.cpp (100%) rename tests/{runtime_tests => run_time}/source/variadics.cpp (100%) delete mode 100644 tests/runtime_tests/CMakeLists.txt delete mode 100644 tests/runtime_tests/source/environments.cpp delete mode 100644 tests/runtime_tests/source/main.cpp diff --git a/.github/workflows/macosx.yml b/.github/workflows/macos.yml similarity index 95% rename from .github/workflows/macosx.yml rename to .github/workflows/macos.yml index e6c96077a..a882b19d1 100644 --- a/.github/workflows/macosx.yml +++ b/.github/workflows/macos.yml @@ -1,4 +1,4 @@ -name: Mac OSX +name: Mac OS on: [push] diff --git a/CMakeLists.txt b/CMakeLists.txt index 07d8b5411..7fea7ec57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,17 +22,13 @@ # # # # sol2 # # # Required minimum version statement -cmake_minimum_required(VERSION 3.15.0) +cmake_minimum_required(VERSION 3.16.0) +# # # Project Include - file that is included after project declaration is finished +set(CMAKE_PROJECT_INCLUDE "${CMAKE_SOURCE_DIR}/cmake/Includes/Project.cmake") # # # project declaration project(sol2 VERSION 4.0.0 LANGUAGES CXX C) -# # # Modules -# # Include modules useful to the project, whether locally made in our own cmake DIRECTORY -# # our from the standard cmake libraries -# Add home-rolled modules path to front of module path list -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules" "${CMAKE_MODULE_PATH}") - if (PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(SOL2_IS_TOP_LEVEL TRUE) message(STATUS "sol2 is the top-level directory...") @@ -78,23 +74,8 @@ CMAKE_DEPENDENT_OPTION(BUILD_LUA_AS_DLL "Build Lua as a DLL" ON "SOL2_BUILD_LUA" OFF) -# # # Platform -# Detect x86 and x64 stuff -if (SOL2_PLATFORM MATCHES "i686" OR SOL2_PLATFORM STREQUAL "x86") - set(SOL2_IS_X86 TRUE) -elseif (SOL2_PLATFORM MATCHES "ARM64") - set(IS_ARM64 TRUE) - set(IS_X64 TRUE) -elseif (SOL2_PLATFORM MATCHES "ARM") - set(IS_ARM TRUE) -elseif (SOL2_PLATFORM MATCHES "x86_64" OR SOL2_PLATFORM STREQUAL "x64") - set(IS_X64 TRUE) -else() - set(IS_X64 TRUE) -endif() - if (SOL2_SYSTEM_INCLUDE) - set(--sol2-system-include SYSTEM) + set(sol2-system-include SYSTEM) endif() # # # sol2 Source Groups @@ -112,7 +93,7 @@ set_target_properties(sol2 PROPERTIES EXPORT_NAME sol2::sol2) -target_include_directories(sol2 ${--sol2-system-include} INTERFACE +target_include_directories(sol2 ${sol2-system-include} INTERFACE $ $) @@ -191,7 +172,7 @@ endif() # # # Tests, Examples and other CI suites that come with sol2 if (SOL2_IS_TOP_LEVEL AND (SOL2_DO_TESTS OR SOL2_DO_EXAMPLES)) # # # General project output locations - if (SOL2_IS_X86 OR CMAKE_SIZEOF_VOID_P EQUAL 4) + if (CMAKE_SIZEOF_VOID_P EQUAL 4) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/lib") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/x86/bin") @@ -204,26 +185,6 @@ if (SOL2_IS_TOP_LEVEL AND (SOL2_DO_TESTS OR SOL2_DO_EXAMPLES)) # # # Libraries # Here, we pull in all the necessary libraries for building examples and tests # Find threading library - if (NOT MSVC) - if (SOL2_IS_X86) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - set(CMAKE_EXECUTABLE_LINKER_FLAGS "${CMAKE_EXECUTABLE_LINKER_FLAGS} -m32") - endif() - set(CMAKE_THREAD_PREFER_PTHREAD TRUE) - set(THREADS_PREFER_PTHREAD_FLAG TRUE) - else() - string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) - string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - if (BUILD_LUA_AS_DLL) - string(REGEX REPLACE "/MT" "/MD" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) - string(REGEX REPLACE "/MT" "/MD" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - else () - string(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) - string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - endif() - endif() find_package(Threads REQUIRED) string(TOLOWER ${SOL2_LUA_VERSION} NORMALIZED_LUA_VERSION) diff --git a/cmake/Includes/Project.cmake b/cmake/Includes/Project.cmake new file mode 100644 index 000000000..8af740072 --- /dev/null +++ b/cmake/Includes/Project.cmake @@ -0,0 +1,77 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 - cmake - basic project configuration + +include_guard(DIRECTORY) + +list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Packages") +list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules") +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MESSAGE_CONTEXT "${PROJECT_NAME}") + +# # Standard Project version +if (NOT CMAKE_CXX_STANDARD GREATER_EQUAL 17) + set(CMAKE_CXX_STANDARD 17) +endif() + +if (NOT CMAKE_C_STANDARD GREATER_EQUAL 11) + set(CMAKE_C_STANDARD 11) +endif() + +# # CMake and sol2 Includes +# CMake +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) +include(CheckIPOSupported) +include(CMakeDependentOption) +include(CMakePrintHelpers) +include(GNUInstallDirs) +include(FeatureSummary) +include(FetchContent) +include(CTest) +# sol2 +include(CheckCompilerDiagnostic) +include(CheckCompilerFlag) +include(FindVersion) + +# # Check environment/prepare generator expressions +# Basic/Normal flags +check_compiler_flag(disable-permissive MSVC /permissive- GCC -pedantic) +check_compiler_flag(utf8-literal-encoding MSVC /execution-charset:utf-8 GCC -fexec-charset=utf-8) +check_compiler_flag(utf8-source-encoding MSVC /source-charset:utf-8 GCC -finput-charset=utf-8) +check_compiler_flag(extra-constexpr-depth MSVC /constexpr:depth2147483647 GCC -fconstexpr-depth=2147483647 CLANG -fconstexpr-depth=2147483647) +check_compiler_flag(extra-constexpr-steps MSVC /constexpr:steps2147483647 GCC -fconstexpr-ops-limit=2147483647 CLANG -fconstexpr-steps=2147483647) +check_compiler_flag(template-debugging-mode GCC -ftemplate-backtrace-limit=0) +check_compiler_flag(big-obj MSVC /bigobj) +# Overall warning flags +check_compiler_flag(pedantic GCC -pedantic) +check_compiler_flag(warn-pedantic GCC -Wpedantic) +check_compiler_flag(warn-all MSVC /W4 GCC -Wall) +check_compiler_flag(warn-extra GCC -Wextra) +check_compiler_flag(warn-errors MSVC /WX GCC -Werror) +# Individual warnings/errors +check_compiler_diagnostic(unknown-warning) +check_compiler_diagnostic(unknown-warning-option) +check_compiler_diagnostic(microsoft-cast) +check_compiler_diagnostic(noexcept-type) +check_compiler_diagnostic(unreachable-code MSVC 4702) diff --git a/cmake/Modules/CheckCompilerDiagnostic.cmake b/cmake/Modules/CheckCompilerDiagnostic.cmake new file mode 100644 index 000000000..d87bdf8b3 --- /dev/null +++ b/cmake/Modules/CheckCompilerDiagnostic.cmake @@ -0,0 +1,93 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 - cmake - compiler diagnostic checking + +include_guard(GLOBAL) + +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) + +#[[ +Given a diagnostic name and flag, like +check_cxx_compiler_diagnostic(pig MSVC 1312) +or +check_cxx_compiler_diagnostic(pig GCC acab) +we check if the given flag works C++ compiler. If it does, we then generate +a --warn, --allow, --deny, and --forbid prefixed set of variables. Users are +then free to simply apply them to targets at will. +]] +function (check_compiler_diagnostic diagnostic) + cmake_parse_arguments(diagnostic "" "GCC;MSVC;CLANG" "" ${ARGN}) + if (NOT diagnostic_GCC) + set(diagnostic_GCC ${diagnostic}) + endif() + if (NOT diagnostic_MSVC) + set(diagnostic_MSVC ${diagnostic}) + endif() + if (NOT diagnostic_CLANG) + set(diagnostic_CLANG ${diagnostic_GCC}) + endif() + string(MAKE_C_IDENTIFIER "${diagnostic}" suffix) + string(TOUPPER "${suffix}" suffix) + get_property(enabled-languages GLOBAL PROPERTY ENABLED_LANGUAGES) + if (CXX IN_LIST enabled-languages) + if (MSVC) + check_cxx_compiler_flag(-wo${diagnostic_MSVC} CXX_DIAGNOSTIC_${suffix}) + elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) + check_cxx_compiler_flag(-W${diagnostic_CLANG} CXX_DIAGNOSTIC_${suffix}) + else() + check_cxx_compiler_flag(-W${diagnostic_GCC} CXX_DIAGNOSTIC_${suffix}) + endif() + endif() + if (C IN_LIST enabled-languages) + if (MSVC) + check_c_compiler_flag(-wo${diagnostic_MSVC} C_DIAGNOSTIC_${suffix}) + elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) + check_c_compiler_flag(-W${diagnostic_CLANG} C_DIAGNOSTIC_${suffix}) + else() + check_c_compiler_flag(-W${diagnostic_GCC} C_DIAGNOSTIC_${suffix}) + endif() + endif() + string(CONCAT when $,$>, + $,$> + >) + string(CONCAT diagnostic_flag + $<$:${diagnostic_MSVC}> + $<$:${diagnostic_MSVC}> + $<$:${diagnostic_GCC}> + $<$:${diagnostic_GCC}> + $<$:${diagnostic_CLANG}> + $<$:${diagnostic_CLANG}> + ) + set(forbid_prefix $,-we,-Werror=>) + set(allow_prefix $,-wd,-Wno->) + set(warn_prefix $,-w1,-W>) + + set(--forbid-${diagnostic} $<${when}:${forbid_prefix}${diagnostic_flag}> PARENT_SCOPE) + set(--allow-${diagnostic} $<${when}:${allow_prefix}${diagnostic_flag}> PARENT_SCOPE) + # Set these warnings to level 1 warnings, so they appear by default + set(--warn-${diagnostic} $<${when}:${warn_prefix}${diagnostic_flag}> PARENT_SCOPE) + + set(--deny-${diagnostic} ${--forbid-${diagnostic_flag}} PARENT_SCOPE) +endfunction() \ No newline at end of file diff --git a/cmake/Modules/CheckCompilerFlag.cmake b/cmake/Modules/CheckCompilerFlag.cmake new file mode 100644 index 000000000..a70d1a6e2 --- /dev/null +++ b/cmake/Modules/CheckCompilerFlag.cmake @@ -0,0 +1,83 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 - cmake - compiler flag checking + +include_guard(GLOBAL) + +include(CheckCXXCompilerFlag) +include(CheckCCompilerFlag) + +#[[ +Given a flag name and the actual flag, like +check_cxx_compiler_flag(strict-conformance MSVC /permissive- GCC -pedantic) +we check if the given flag works C++ compiler. If it is, then +--strict-conformance will be the provided flag. MSVC and GCC are the 2 different +"style" of flags to be tested for. +]] +function (check_compiler_flag flag_name) + cmake_parse_arguments(PARSE_ARGV 1 flag "" "" "GCC;MSVC;CLANG") + if (NOT flag_MSVC) + set(flag_MSVC /${flag_name}) + endif() + if (NOT flag_GCC) + set(flag_GCC ${flag_name}) + endif() + if (NOT flag_CLANG) + set(flag_CLANG ${flag_GCC}) + endif() + string(MAKE_C_IDENTIFIER "${flag_name}" suffix) + string(TOUPPER "${suffix}" suffix) + get_property(enabled-languages GLOBAL PROPERTY ENABLED_LANGUAGES) + if (CXX IN_LIST enabled-languages) + if (MSVC) + check_cxx_compiler_flag(${flag_MSVC} CXX_CHECK_FLAG_${suffix}) + elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) + check_cxx_compiler_flag(${flag_CLANG} CXX_CHECK_FLAG_${suffix}) + else() + check_cxx_compiler_flag(${flag_GCC} CXX_CHECK_FLAG_${suffix}) + endif() + endif() + if (C IN_LIST enabled-languages) + if (MSVC) + check_c_compiler_flag(${flag_MSVC} C_CHECK_FLAG_${suffix}) + elseif (CMAKE_C_COMPILER_ID MATCHES Clang) + check_c_compiler_flag(${flag_CLANG} C_CHECK_FLAG_${suffix}) + else() + check_c_compiler_flag(${flag_GCC} C_CHECK_FLAG_${suffix}) + endif() + endif() + string(CONCAT when $,$>, + $,$> + >) + string(CONCAT compiler_flag + $<$:${flag_MSVC}> + $<$:${flag_MSVC}> + $<$:${flag_GCC}> + $<$:${flag_GCC}> + $<$:${flag_CLANG}> + $<$:${flag_CLANG}> + ) + + set(--${flag_name} $<${when}:${compiler_flag}> PARENT_SCOPE) +endfunction() diff --git a/cmake/Modules/FindVersion.cmake b/cmake/Modules/FindVersion.cmake new file mode 100644 index 000000000..c12a7f49e --- /dev/null +++ b/cmake/Modules/FindVersion.cmake @@ -0,0 +1,61 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 - cmake - version matching + +include_guard(GLOBAL) + +#[[ +This is used to create a version variable. How these are used or set is up +to the user. +TODO: Support find_version( SOURCE ) for parsing a version name from a header file +TODO: Support find_version( LIBRARY ) for .dll/.lib/.so/.dylib parsing +]] +function (find_version output) + cmake_parse_arguments(ARG "" "OPTION;REGEX;COMMAND;DOC" "" ${ARGN}) + unset(version-output) + unset(version-check) + if (NOT ARG_OPTION) + set(ARG_OPTION "--version") + endif() + if (NOT ARG_REGEX) + set(ARG_REGEX "[^0-9]*([0-9]+)[.]([0-9]+)?[.]?([0-9]+)?[.]?([0-9]+)?.*") + endif() + if (ARG_COMMAND AND NOT DEFINED ${output}) + execute_process( + COMMAND ${ARG_COMMAND} ${ARG_OPTION} + OUTPUT_VARIABLE version-output + OUTPUT_STRIP_TRAILING_WHITESPACE + ENCODING UTF-8) + if (version-output) + string(REGEX MATCH "${ARG_REGEX}" version-check ${version-output}) + endif() + if (version-check) + string(JOIN "." ${output} + ${CMAKE_MATCH_1} + ${CMAKE_MATCH_2} + ${CMAKE_MATCH_3} + ${CMAKE_MATCH_4}) + set(${output} "${${output}}" CACHE STRING "${ARG_DOC}" FORCE) + endif() + endif() +endfunction() diff --git a/cmake/Modules/FindKaguyaBuild.cmake b/cmake/Packages/FindKaguyaBuild.cmake similarity index 100% rename from cmake/Modules/FindKaguyaBuild.cmake rename to cmake/Packages/FindKaguyaBuild.cmake diff --git a/cmake/Modules/FindLua/set_version_vars.cmake b/cmake/Packages/FindLua/set_version_vars.cmake similarity index 100% rename from cmake/Modules/FindLua/set_version_vars.cmake rename to cmake/Packages/FindLua/set_version_vars.cmake diff --git a/cmake/Modules/FindLua/version_check.cmake b/cmake/Packages/FindLua/version_check.cmake similarity index 100% rename from cmake/Modules/FindLua/version_check.cmake rename to cmake/Packages/FindLua/version_check.cmake diff --git a/cmake/Modules/FindLuaBridgeBuild.cmake b/cmake/Packages/FindLuaBridgeBuild.cmake similarity index 100% rename from cmake/Modules/FindLuaBridgeBuild.cmake rename to cmake/Packages/FindLuaBridgeBuild.cmake diff --git a/cmake/Modules/FindLuaBuild.cmake b/cmake/Packages/FindLuaBuild.cmake similarity index 100% rename from cmake/Modules/FindLuaBuild.cmake rename to cmake/Packages/FindLuaBuild.cmake diff --git a/cmake/Modules/FindLuaBuild/LuaJIT.cmake b/cmake/Packages/FindLuaBuild/LuaJIT.cmake similarity index 100% rename from cmake/Modules/FindLuaBuild/LuaJIT.cmake rename to cmake/Packages/FindLuaBuild/LuaJIT.cmake diff --git a/cmake/Modules/FindLuaBuild/LuaVanilla.cmake b/cmake/Packages/FindLuaBuild/LuaVanilla.cmake similarity index 100% rename from cmake/Modules/FindLuaBuild/LuaVanilla.cmake rename to cmake/Packages/FindLuaBuild/LuaVanilla.cmake diff --git a/cmake/Modules/FindLuwraBuild.cmake b/cmake/Packages/FindLuwraBuild.cmake similarity index 100% rename from cmake/Modules/FindLuwraBuild.cmake rename to cmake/Packages/FindLuwraBuild.cmake diff --git a/cmake/Modules/FindSphinx.cmake b/cmake/Packages/FindSphinx.cmake similarity index 100% rename from cmake/Modules/FindSphinx.cmake rename to cmake/Packages/FindSphinx.cmake diff --git a/cmake/Modules/FindToLuappBuild.cmake b/cmake/Packages/FindToLuappBuild.cmake similarity index 100% rename from cmake/Modules/FindToLuappBuild.cmake rename to cmake/Packages/FindToLuappBuild.cmake diff --git a/documentation/CMakeLists.txt b/documentation/CMakeLists.txt index 231b515a7..04e7af512 100644 --- a/documentation/CMakeLists.txt +++ b/documentation/CMakeLists.txt @@ -22,7 +22,7 @@ # # # # sol2, documentation generation # # # Required minimum version statement -cmake_minimum_required(VERSION 3.15.0) +cmake_minimum_required(VERSION 3.16.0) find_package(Doxygen REQUIRED) find_package(Python3 REQUIRED) @@ -98,7 +98,6 @@ if (NOT SOL2_DOCUMENTATION_NO_SPHINX) endif() # For the install target -include(GNUInstallDirs) install(DIRECTORY ${SOL2_SPHINX_BUILD_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR} -) \ No newline at end of file +) diff --git a/documentation/source/api/environment.rst b/documentation/source/api/environment.rst index 712fb409a..75883b12b 100644 --- a/documentation/source/api/environment.rst +++ b/documentation/source/api/environment.rst @@ -10,7 +10,7 @@ environment class environment : public table; template - void set_environment( const environment& env, const T& target ); + bool set_environment( const environment& env, const T& target ); template basic_environment get_environment( const T& target ); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 94a83834c..2d386d6e7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -22,6 +22,47 @@ # # # sol2 Examples +function(sol2_add_example_properties target-name) + target_link_libraries(${target-name} + PUBLIC Threads::Threads ${LUA_LIBRARIES} ${CMAKE_DL_LIBS}) + target_compile_definitions(${target-name} + PUBLIC SOL_PRINT_ERRORS=1) + target_compile_options(${target-name} + PRIVATE + ${--template-debugging-mode} + ${--big-obj} + ${--no-unknown-warning} + ${--disable-permissive} + ${--pedantic} + ${--warn-all} + ${--warn-pedantic} + ${--warn-extra} + ${--warn-errors} + ${--utf8-literal-encoding} + ${--utf8-source-encoding} + + ${--allow-unknown-warning} + ${--allow-unknown-warning-option} + ${--allow-noexcept-type} + ${--allow-microsoft-casts} + ) + + target_compile_definitions(${target-name} + PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE) + + if (SOL2_CI) + target_compile_definitions(${target-name} + PRIVATE SOL2_CI) + endif() + + if (SOL2_TESTS_EXAMPLES) + add_test(NAME ${target-name} COMMAND ${target-name}) + endif() + if(SOL2_ENABLE_INSTALL) + install(TARGETS ${target-name} RUNTIME DESTINATION bin) + endif() +endfunction() + if (SOL2_DYNAMIC_LOADING_EXAMPLES OR SOL2_DYNAMIC_LOADING_EXAMPLES_SINGLE) # # require_from_dll example # just add the subdirectory @@ -45,7 +86,6 @@ file(GLOB sol2.examples.sources source/*.cpp source/tutorials/*.cpp source/tutor source_group(examples FILES ${sol2.examples.sources}) function (MAKE_EXAMPLE example_source_file example_prefix target_sol) - get_filename_component(example_name ${example_source_file} NAME_WE) file(RELATIVE_PATH example_source_file_relative ${CMAKE_SOURCE_DIR} ${example_source_file}) get_filename_component(example_output_relative_dir ${example_source_file_relative} DIRECTORY) @@ -60,42 +100,9 @@ function (MAKE_EXAMPLE example_source_file example_prefix target_sol) endif() add_executable(${example_name} ${example_source_file}) - set_target_properties(${example_name} - PROPERTIES - OUTPUT_NAME "${example_output_name}") - - if (MSVC) - target_compile_options(${example_name} - PRIVATE /std:c++latest /EHsc /W4) - target_compile_definitions(${example_name} - PRIVATE UNICODE _UNICODE - _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE ) - else() - target_compile_options(${example_name} - PRIVATE -std=c++1z - -ftemplate-backtrace-limit=0 - -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wpedantic -Werror -pedantic -pedantic-errors - -Wno-noexcept-type) - - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # For another day, when C++ is not so crap - # and we have time to audit the entire lib - # for all uses of `detail::swallow`... - #target_compile_options(${example_name} - # PRIVATE -Wcomma) - endif() - endif() - + sol2_add_example_properties(${example_name}) target_link_libraries(${example_name} - PRIVATE Threads::Threads ${target_sol} ${LUA_LIBRARIES} ${CMAKE_DL_LIBS}) - - if (SOL2_TESTS_EXAMPLES) - add_test(NAME ${example_output_name} COMMAND ${example_name}) - endif() - if(SOL2_ENABLE_INSTALL) - install(TARGETS ${example_name} RUNTIME DESTINATION bin) - endif() + PRIVATE ${target_sol}) endfunction(MAKE_EXAMPLE) if (SOL2_EXAMPLES) diff --git a/examples/source/environments_on_functions.cpp b/examples/source/environments_on_functions.cpp index 8c541ebc7..f434f54a8 100644 --- a/examples/source/environments_on_functions.cpp +++ b/examples/source/environments_on_functions.cpp @@ -15,7 +15,8 @@ int main(int, char**) { sol::environment env_f(lua, sol::create); env_f["test"] = 31; - sol::set_environment(env_f, f); + bool env_f_set_success = sol::set_environment(env_f, f); + sol_c_assert(env_f_set_success); // the function returns the value from the environment table int result = f(); @@ -27,7 +28,9 @@ int main(int, char**) { lua.script("g = function() test = 5 end"); sol::function g = lua["g"]; sol::environment env_g(lua, sol::create); - env_g.set_on(g); // same as set_environment + bool env_g_set_success + = env_g.set_on(g); // same as set_environment + sol_c_assert(env_g_set_success); g(); // the value can be retrieved from the env table diff --git a/examples/source/pairs.cpp b/examples/source/pairs.cpp index 563b087b2..0d33c652b 100644 --- a/examples/source/pairs.cpp +++ b/examples/source/pairs.cpp @@ -82,7 +82,7 @@ int main(int, char*[]) { lua.new_usertype( "my_thing", sol::meta_function::pairs, my_pairs); -#if SOL_LUA_VERSION > 501 +#if SOL_LUA_VERSION_I_ > 501 lua.safe_script(R"( local mt = my_thing.new() for k, v in pairs(mt) do diff --git a/examples/source/pairs_with_raw_functions.cpp b/examples/source/pairs_with_raw_functions.cpp index c90daa7b4..1aeaab9ba 100644 --- a/examples/source/pairs_with_raw_functions.cpp +++ b/examples/source/pairs_with_raw_functions.cpp @@ -76,7 +76,7 @@ int main(int, char*[]) { lua.new_usertype( "my_thing", sol::meta_function::pairs, &my_pairs); -#if SOL_LUA_VERSION > 501 +#if SOL_LUA_VERSION_I_ > 501 lua.safe_script(R"( local mt = my_thing.new() for k, v in pairs(mt) do diff --git a/examples/source/usertype_automatic_operators.cpp b/examples/source/usertype_automatic_operators.cpp index 181eb36fa..67dcc608f 100644 --- a/examples/source/usertype_automatic_operators.cpp +++ b/examples/source/usertype_automatic_operators.cpp @@ -106,7 +106,7 @@ print("#obj2:", #obj2) print("#obj3:", #obj3) )"); -#if SOL_LUA_VERSION > 501 +#if SOL_LUA_VERSION_I_ > 501 lua.script(R"( for k, v in pairs(obj1) do assert( (k / 3) == v ) diff --git a/include/sol/compatibility/lua_version.hpp b/include/sol/compatibility/lua_version.hpp index d243054ab..d640c09a0 100644 --- a/include/sol/compatibility/lua_version.hpp +++ b/include/sol/compatibility/lua_version.hpp @@ -91,9 +91,9 @@ #endif // SOL_LUA_VERSION #if defined(SOL_LUA_VERSION) - #define SOL_LUA_VESION_I_ SOL_LUA_VERSION + #define SOL_LUA_VERSION_I_ SOL_LUA_VERSION #else - #define SOL_LUA_VESION_I_ 504 + #define SOL_LUA_VERSION_I_ 504 #endif // Exception safety / propagation, according to Lua information @@ -184,7 +184,7 @@ #else // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) // Lua 5.2, or other versions of Lua with the compat flag, or Lua that is not 5.2 with the specific define (5.4.1 either removed it entirely or broke it) - #if (SOL_LUA_VESION_I_ == 502) || (defined(LUA_COMPAT_BITLIB) && (LUA_COMPAT_BITLIB != 0)) || (SOL_LUA_VESION_I_ < 504 && (defined(LUA_COMPAT_5_2) && (LUA_COMPAT_5_2 != 0))) + #if (SOL_LUA_VERSION_I_ == 502) || (defined(LUA_COMPAT_BITLIB) && (LUA_COMPAT_BITLIB != 0)) || (SOL_LUA_VERSION_I_ < 504 && (defined(LUA_COMPAT_5_2) && (LUA_COMPAT_5_2 != 0))) #define SOL_LUA_BIT32_LIB_I_ SOL_ON #else #define SOL_LUA_BIT32_LIB_I_ SOL_DEFAULT_OFF diff --git a/include/sol/coroutine.hpp b/include/sol/coroutine.hpp index 9904c788a..e4b9d8141 100644 --- a/include/sol/coroutine.hpp +++ b/include/sol/coroutine.hpp @@ -42,7 +42,7 @@ namespace sol { call_status stats = call_status::yielded; void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { -#if SOL_LUA_VESION_I_ >= 504 +#if SOL_LUA_VERSION_I_ >= 504 int nresults; stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount), &nresults)); #else diff --git a/include/sol/environment.hpp b/include/sol/environment.hpp index f1fd8b49a..2529403bc 100644 --- a/include/sol/environment.hpp +++ b/include/sol/environment.hpp @@ -113,27 +113,69 @@ namespace sol { } template - void set_on(const T& target) const { + bool set_on(const T& target) const { lua_State* L = target.lua_state(); auto pp = stack::push_pop(target); -#if SOL_LUA_VESION_I_ < 502 + int target_index = pp.index_of(target); +#if SOL_LUA_VERSION_I_ < 502 // Use lua_setfenv this->push(); - lua_setfenv(L, -2); + int success_result = lua_setfenv(L, target_index); + return success_result != 0; #else - // Use upvalues as explained in Lua 5.2 and beyond's manual - this->push(); - const char* name = lua_setupvalue(L, -2, 1); - if (name == nullptr) { - this->pop(); + // If this is a C function, the environment is always placed in + // the first value, as is expected of sol2 (all upvalues have an empty name, "") + if (lua_iscfunction(L, target_index) != 0) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, 1); + if (maybe_upvalue_name == nullptr) { + return false; + } + string_view upvalue_name(maybe_upvalue_name); + if (upvalue_name == "") { + this->push(); + const char* success = lua_setupvalue(L, target_index, 1); + if (success == nullptr) { + // left things alone on the stack, pop them off + lua_pop(L, 1); + return false; + } + return true; + } + return false; + } + else { + // Must search for the right upvalue target on index + for (int upvalue_index = 1;; ++upvalue_index) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, upvalue_index); + if (maybe_upvalue_name == nullptr) { + break; + } + string_view upvalue_name(maybe_upvalue_name); + if (upvalue_name == "_ENV") { + this->push(); + const char* success = lua_setupvalue(L, target_index, upvalue_index); + if (success == nullptr) { + // left things alone on the stack, pop them off + lua_pop(L, 1); + break; + } + // whether or not we succeeded, we found _ENV + // so we need to break + return true; + } + lua_pop(L, 1); + } + // if we get here, + // we did not find an _ENV here... + return false; } #endif } }; template - void set_environment(const basic_environment& env, const T& target) { - env.set_on(target); + bool set_environment(const basic_environment& env, const T& target) { + return env.set_on(target); } template diff --git a/include/sol/function_types.hpp b/include/sol/function_types.hpp index 1ae29f5e8..c4d22372c 100644 --- a/include/sol/function_types.hpp +++ b/include/sol/function_types.hpp @@ -72,8 +72,8 @@ namespace sol { template void select_set_fx(lua_State* L, Args&&... args) { - lua_CFunction freefunc = no_trampoline ? detail::static_trampoline, 2, is_yielding>> - : function_detail::call, 2, is_yielding>; + lua_CFunction freefunc = no_trampoline ? function_detail::call, 2, is_yielding> + : detail::static_trampoline, 2, is_yielding>>; int upvalues = 0; upvalues += stack::push(L, nullptr); @@ -277,7 +277,7 @@ namespace sol { template struct unqualified_pusher> { template - static int push(lua_State* L, Arg0&& arg0, Args&&... args) { + static int push_yielding(lua_State* L, Arg0&& arg0, Args&&... args) { if constexpr (meta::is_specialization_of_v, std::function>) { if constexpr (is_yielding) { return stack::push>(L, detail::yield_tag, std::forward(arg0), std::forward(args)...); @@ -295,13 +295,13 @@ namespace sol { template static int push(lua_State* L, Arg0&& arg0, Args&&... args) { if constexpr (std::is_same_v, detail::yield_tag_t>) { - push(L, std::forward(args)...); + push_yielding(L, std::forward(args)...); } else if constexpr (meta::is_specialization_of_v, yielding_t>) { - push(L, std::forward(arg0).func, std::forward(args)...); + push_yielding(L, std::forward(arg0).func, std::forward(args)...); } else { - push(L, std::forward(arg0), std::forward(args)...); + push_yielding(L, std::forward(arg0), std::forward(args)...); } return 1; } @@ -315,7 +315,7 @@ namespace sol { return stack::push(L, detail::yield_tag, f.func, std::forward(args)...); } else { - function_detail::select(L, f.func, std::forward(args)...); + function_detail::select(L, f.func, std::forward(args)...); return 1; } } @@ -326,7 +326,7 @@ namespace sol { return stack::push(L, detail::yield_tag, std::move(f.func), std::forward(args)...); } else { - function_detail::select(L, std::move(f.func), std::forward(args)...); + function_detail::select(L, std::move(f.func), std::forward(args)...); return 1; } } @@ -350,9 +350,11 @@ namespace sol { template struct unqualified_pusher> { + using TargetFunctor = function_detail::functor_function, false, true>; + static int push(lua_State* L, detail::yield_tag_t, const std::function& fx) { if (fx) { - function_detail::select(L, fx); + function_detail::select_set_fx(L, fx); return 1; } return stack::push(L, lua_nil); @@ -360,7 +362,7 @@ namespace sol { static int push(lua_State* L, detail::yield_tag_t, std::function&& fx) { if (fx) { - function_detail::select(L, std::move(fx)); + function_detail::select_set_fx(L, std::move(fx)); return 1; } return stack::push(L, lua_nil); @@ -368,7 +370,7 @@ namespace sol { static int push(lua_State* L, const std::function& fx) { if (fx) { - function_detail::select(L, fx); + function_detail::select_set_fx(L, fx); return 1; } return stack::push(L, lua_nil); @@ -376,7 +378,7 @@ namespace sol { static int push(lua_State* L, std::function&& fx) { if (fx) { - function_detail::select(L, std::move(fx)); + function_detail::select_set_fx(L, std::move(fx)); return 1; } return stack::push(L, lua_nil); @@ -387,7 +389,7 @@ namespace sol { struct unqualified_pusher>> { template static int push(lua_State* L, Args&&... args) { - function_detail::select(L, std::forward(args)...); + function_detail::select(L, std::forward(args)...); return 1; } }; @@ -527,7 +529,8 @@ namespace sol { } static int push(lua_State* L, no_construction c, function_detail::call_indicator) { - return push(L, c); + lua_CFunction cf = &function_detail::no_construction_error; + return stack::push(L, cf); } }; diff --git a/include/sol/packaged_coroutine.hpp b/include/sol/packaged_coroutine.hpp index b5ffcb519..0f242306a 100644 --- a/include/sol/packaged_coroutine.hpp +++ b/include/sol/packaged_coroutine.hpp @@ -44,7 +44,7 @@ namespace sol { sol::thread m_thread_reference; void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { -#if SOL_LUA_VESION_I_ >= 504 +#if SOL_LUA_VERSION_I_ >= 504 int nresults; stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount), &nresults)); #else diff --git a/include/sol/reference.hpp b/include/sol/reference.hpp index a3e78fde4..ed296f663 100644 --- a/include/sol/reference.hpp +++ b/include/sol/reference.hpp @@ -218,7 +218,7 @@ namespace sol { } // namespace stack inline lua_State* main_thread(lua_State* L_, lua_State* backup_if_unsupported_ = nullptr) { -#if SOL_LUA_VESION_I_ < 502 +#if SOL_LUA_VERSION_I_ < 502 if (L_ == nullptr) return backup_if_unsupported_; lua_getglobal(L_, detail::default_main_thread_name()); diff --git a/include/sol/stack_check_get_unqualified.hpp b/include/sol/stack_check_get_unqualified.hpp index acdb5541a..31bef9f4f 100644 --- a/include/sol/stack_check_get_unqualified.hpp +++ b/include/sol/stack_check_get_unqualified.hpp @@ -67,7 +67,7 @@ namespace sol { namespace stack { } } else if constexpr ((std::is_integral_v || std::is_same_v)&&!std::is_same_v) { -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 if (lua_isinteger(L, index) != 0) { tracking.use(1); return static_cast(lua_tointeger(L, index)); diff --git a/include/sol/stack_check_unqualified.hpp b/include/sol/stack_check_unqualified.hpp index 4ecd9f6ca..fb9670ad9 100644 --- a/include/sol/stack_check_unqualified.hpp +++ b/include/sol/stack_check_unqualified.hpp @@ -113,7 +113,7 @@ namespace sol { namespace stack { } else if constexpr (std::is_integral_v || std::is_same_v) { tracking.use(1); -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 // Lua 5.3 and greater checks for numeric precision #if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS_I_) // imprecise, sloppy conversions diff --git a/include/sol/stack_core.hpp b/include/sol/stack_core.hpp index 460a9e9a3..4cad844ad 100644 --- a/include/sol/stack_core.hpp +++ b/include/sol/stack_core.hpp @@ -71,7 +71,7 @@ namespace sol { using unique_tag = detail::inheritance_unique_cast_function; inline void* alloc_newuserdata(lua_State* L, std::size_t bytesize) { -#if SOL_LUA_VERSION >= 504 +#if SOL_LUA_VERSION_I_ >= 504 return lua_newuserdatauv(L, bytesize, 1); #else return lua_newuserdata(L, bytesize); diff --git a/include/sol/stack_field.hpp b/include/sol/stack_field.hpp index a9f688dda..9a184e0b5 100644 --- a/include/sol/stack_field.hpp +++ b/include/sol/stack_field.hpp @@ -39,10 +39,10 @@ namespace sol { namespace stack { inline constexpr bool is_get_direct_v = (is_get_direct_tableless_v) // cf-hack || (!global && !raw && (meta::is_c_str_v || meta::is_string_of_v)) // cf-hack || (!global && raw && (std::is_integral_v && !std::is_same_v)) -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 || (!global && !raw && (std::is_integral_v && !std::is_same_v)) #endif // integer keys 5.3 or better -#if SOL_LUA_VESION_I_ >= 502 +#if SOL_LUA_VERSION_I_ >= 502 || (!global && raw && std::is_pointer_v && std::is_void_v>) #endif // void pointer keys 5.2 or better ; @@ -54,10 +54,10 @@ namespace sol { namespace stack { inline constexpr bool is_set_direct_v = (is_set_direct_tableless_v) // cf-hack || (!global && !raw && (meta::is_c_str_v || meta::is_string_of_v)) // cf-hack || (!global && raw && (std::is_integral_v && !std::is_same_v)) // cf-hack -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 || (!global && !raw && (std::is_integral_v && !std::is_same_v)) #endif // integer keys 5.3 or better -#if SOL_LUA_VESION_I_ >= 502 +#if SOL_LUA_VERSION_I_ >= 502 || (!global && raw && (std::is_pointer_v && std::is_void_v>)) #endif // void pointer keys 5.2 or better ; @@ -77,7 +77,7 @@ namespace sol { namespace stack { } else if constexpr (std::is_same_v) { (void)key; -#if SOL_LUA_VESION_I_ < 502 +#if SOL_LUA_VERSION_I_ < 502 // Use lua_setfenv lua_getfenv(L, tableindex); #else @@ -96,7 +96,7 @@ namespace sol { namespace stack { if constexpr (std::is_integral_v && !std::is_same_v) { lua_rawgeti(L, tableindex, static_cast(key)); } -#if SOL_LUA_VESION_I_ >= 502 +#if SOL_LUA_VERSION_I_ >= 502 else if constexpr (std::is_pointer_v && std::is_void_v>) { lua_rawgetp(L, tableindex, key); } @@ -120,7 +120,7 @@ namespace sol { namespace stack { const auto& real_key = to_string(key); lua_getfield(L, tableindex, &real_key[0]); } -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 else if constexpr (std::is_integral_v && !std::is_same_v) { lua_geti(L, tableindex, static_cast(key)); } @@ -199,7 +199,7 @@ namespace sol { namespace stack { push(L, std::forward(value)); lua_rawseti(L, tableindex, static_cast(key)); } -#if SOL_LUA_VESION_I_ >= 502 +#if SOL_LUA_VERSION_I_ >= 502 else if constexpr (std::is_pointer_v && std::is_void_v>) { push(L, std::forward(value)); lua_rawsetp(L, tableindex, std::forward(key)); @@ -223,7 +223,7 @@ namespace sol { namespace stack { lua_setfield(L, tableindex, &key[0]); } } -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 else if constexpr (std::is_integral_v && !std::is_same_v) { push(L, std::forward(value)); lua_seti(L, tableindex, static_cast(key)); diff --git a/include/sol/stack_get_unqualified.hpp b/include/sol/stack_get_unqualified.hpp index b2c75e6b7..50b657bdd 100644 --- a/include/sol/stack_get_unqualified.hpp +++ b/include/sol/stack_get_unqualified.hpp @@ -127,7 +127,7 @@ namespace sol { namespace stack { } else if constexpr (std::is_integral_v || std::is_same_v) { tracking.use(1); -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 if (lua_isinteger(L, index) != 0) { return static_cast(lua_tointeger(L, index)); } @@ -344,7 +344,7 @@ namespace sol { namespace stack { int index = lua_absindex(L, relindex); T cont; std::size_t idx = 0; -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 // This method is HIGHLY performant over regular table iteration // thanks to the Lua API changes in 5.3 // Questionable in 5.4 @@ -355,7 +355,7 @@ namespace sol { namespace stack { } bool isnil = false; for (int vi = 0; vi < lua_size::value; ++vi) { -#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES_I_) && SOL_LUA_VESION_I_ >= 600 +#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES_I_) && SOL_LUA_VERSION_I_ >= 600 #if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); #endif // make sure stack doesn't overflow @@ -376,7 +376,7 @@ namespace sol { namespace stack { if (i == 0) { break; } -#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES_I_) && SOL_LUA_VESION_I_ >= 600 +#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES_I_) && SOL_LUA_VERSION_I_ >= 600 lua_pop(L, vi); #else lua_pop(L, (vi + 1)); @@ -386,7 +386,7 @@ namespace sol { namespace stack { } } if (isnil) { -#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES_I_) && SOL_LUA_VESION_I_ >= 600 +#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES_I_) && SOL_LUA_VERSION_I_ >= 600 #else lua_pop(L, lua_size::value); #endif @@ -494,7 +494,7 @@ namespace sol { namespace stack { C cont; auto at = cont.cbefore_begin(); std::size_t idx = 0; -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 for (lua_Integer i = 0;; i += lua_size::value, lua_pop(L, lua_size::value)) { if (idx >= cont.max_size()) { diff --git a/include/sol/stack_push.hpp b/include/sol/stack_push.hpp index f02d30718..098fa0a0b 100644 --- a/include/sol/stack_push.hpp +++ b/include/sol/stack_push.hpp @@ -45,7 +45,20 @@ namespace sol { namespace stack { namespace stack_detail { template inline bool integer_value_fits(const T& value) { - if constexpr (sizeof(T) < sizeof(lua_Integer) || (std::is_signed_v && sizeof(T) == sizeof(lua_Integer))) { + // We check if we can rely on casts or a lack of padding bits to satisfy + // the requirements here + // If it lacks padding bits, we can jump back and forth between lua_Integer and whatever type without + // loss of information + constexpr bool is_same_signedness + = (std::is_signed_v && std::is_signed_v) || (std::is_unsigned_v && std::is_unsigned_v); + constexpr bool probaby_fits_within_lua_Integer = sizeof(T) == sizeof(lua_Integer) +#if SOL_IS_ON(SOL_ALL_INTEGER_VALUES_FIT_I_) + && ((std::has_unique_object_representations_v && std::has_unique_object_representations_v) ? true : is_same_signedness) +#else + && is_same_signedness +#endif + ; + if constexpr (sizeof(T) < sizeof(lua_Integer) || probaby_fits_within_lua_Integer) { (void)value; return true; } @@ -87,18 +100,38 @@ namespace sol { namespace stack { } } // namespace stack_detail - inline int push_environment_of(lua_State* L, int index = -1) { + inline int push_environment_of(lua_State* L, int target_index = -1) { #if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) luaL_checkstack(L, 1, detail::not_enough_stack_space_environment); #endif // make sure stack doesn't overflow -#if SOL_LUA_VESION_I_ < 502 +#if SOL_LUA_VERSION_I_ < 502 // Use lua_getfenv - lua_getfenv(L, index); + lua_getfenv(L, target_index); #else - // Use upvalues as explained in Lua 5.2 and beyond's manual - if (lua_getupvalue(L, index, 1) == nullptr) { - push(L, lua_nil); - return 1; + + if (lua_iscfunction(L, target_index) != 0) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, 1); + if (maybe_upvalue_name != nullptr) { + // it worked, take this one + return 1; + } + } + // Nominally, we search for the `"_ENV"` value. + // If we don't find it.... uh, well. We've got a problem? + for (int upvalue_index = 1;; ++upvalue_index) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, upvalue_index); + if (maybe_upvalue_name == nullptr) { + push(L, lua_nil); + break; + } + + string_view upvalue_name(maybe_upvalue_name); + if (upvalue_name == "_ENV") { + // Keep this one! + break; + } + // Discard what we received, loop back around + lua_pop(L, 1); } #endif return 1; @@ -106,8 +139,9 @@ namespace sol { namespace stack { template int push_environment_of(const T& target) { - target.push(); - return push_environment_of(target.lua_state(), -1) + 1; + lua_State* target_L = target.lua_state(); + int target_index = absolute_index(target_L, -target.push()); + return push_environment_of(target_L, target_index); } template @@ -272,7 +306,7 @@ namespace sol { namespace stack { #if SOL_IS_ON(SOL_SAFE_STACK_CHECK_I_) luaL_checkstack(L, 1, detail::not_enough_stack_space_integral); #endif // make sure stack doesn't overflow -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 if (stack_detail::integer_value_fits(value)) { lua_pushinteger(L, static_cast(value)); return 1; @@ -383,7 +417,7 @@ namespace sol { namespace stack { int tableindex = lua_gettop(L); std::size_t index = 1; for (const auto& i : cont) { -#if SOL_LUA_VESION_I_ >= 503 +#if SOL_LUA_VERSION_I_ >= 503 int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i); for (int pi = 0; pi < p; ++pi) { lua_seti(L, tableindex, static_cast(index++)); diff --git a/include/sol/state_handling.hpp b/include/sol/state_handling.hpp index 5e7ceb1b9..52bfd5279 100644 --- a/include/sol/state_handling.hpp +++ b/include/sol/state_handling.hpp @@ -37,7 +37,7 @@ namespace sol { inline void register_main_thread(lua_State* L) { -#if SOL_LUA_VESION_I_ < 502 +#if SOL_LUA_VERSION_I_ < 502 if (L == nullptr) { lua_pushnil(L); lua_setglobal(L, detail::default_main_thread_name()); diff --git a/include/sol/state_view.hpp b/include/sol/state_view.hpp index 0e3cf820c..499f24bc8 100644 --- a/include/sol/state_view.hpp +++ b/include/sol/state_view.hpp @@ -46,7 +46,7 @@ namespace sol { bool is53mod = loaded && !(loaded->is() && !loaded->as()); if (is53mod) return loaded; -#if SOL_LUA_VESION_I_ <= 501 +#if SOL_LUA_VERSION_I_ <= 501 auto loaded51 = global.traverse_get>("package", "loaded", key); bool is51mod = loaded51 && !(loaded51->is() && !loaded51->as()); if (is51mod) @@ -57,7 +57,7 @@ namespace sol { template void ensure_package(const std::string& key, T&& sr) { -#if SOL_LUA_VESION_I_ <= 501 +#if SOL_LUA_VERSION_I_ <= 501 auto pkg = global["package"]; if (!pkg.valid()) { pkg = create_table_with("loaded", create_table_with(key, sr)); @@ -129,7 +129,7 @@ namespace sol { for (auto&& library : libraries) { switch (library) { -#if SOL_LUA_VESION_I_ <= 501 && SOL_IS_ON(SOL_USE_LUAJIT_I_) +#if SOL_LUA_VERSION_I_ <= 501 && SOL_IS_ON(SOL_USE_LUAJIT_I_) case lib::coroutine: #endif // luajit opens coroutine base stuff case lib::base: @@ -142,7 +142,7 @@ namespace sol { break; #if SOL_IS_OFF(SOL_USE_LUAJIT_I_) case lib::coroutine: -#if SOL_LUA_VESION_I_ > 501 +#if SOL_LUA_VERSION_I_ > 501 luaL_requiref(L, "coroutine", luaopen_coroutine, 1); lua_pop(L, 1); #endif // Lua 5.2+ only @@ -183,7 +183,7 @@ namespace sol { lua_pop(L, 1); break; case lib::utf8: -#if SOL_LUA_VESION_I_ > 502 && SOL_IS_OFF(SOL_USE_LUAJIT_I_) +#if SOL_LUA_VERSION_I_ > 502 && SOL_IS_OFF(SOL_USE_LUAJIT_I_) luaL_requiref(L, "utf8", luaopen_utf8, 1); lua_pop(L, 1); #endif // Lua 5.3+ only @@ -236,7 +236,7 @@ namespace sol { // one day Lua 5.1 will die a peaceful death // and its old bones will find blissful rest auto loaders_proxy = package -#if SOL_LUA_VESION_I_ < 502 +#if SOL_LUA_VERSION_I_ < 502 ["loaders"] #else ["searchers"] @@ -264,7 +264,7 @@ namespace sol { // one day Lua 5.1 will die a peaceful death // and its old bones will find blissful rest auto loaders_proxy = package -#if SOL_LUA_VESION_I_ < 502 +#if SOL_LUA_VERSION_I_ < 502 ["loaders"] #else ["searchers"] @@ -647,7 +647,7 @@ namespace sol { } bool supports_gc_mode(gc_mode mode) const noexcept { -#if SOL_LUA_VESION_I_ >= 504 +#if SOL_LUA_VERSION_I_ >= 504 // supports all modes (void)mode; return true; @@ -656,7 +656,7 @@ namespace sol { } bool is_gc_on() const { -#if SOL_LUA_VESION_I_ >= 502 +#if SOL_LUA_VERSION_I_ >= 502 return lua_gc(lua_state(), LUA_GCISRUNNING, 0) == 1; #else // You cannot turn it off in Lua 5.1 @@ -676,7 +676,7 @@ namespace sol { // THOUGHT: std::chrono-alikes to map "kilobyte size" here...? // Make it harder to give MB or KB to a B parameter...? // Probably overkill for now. -#if SOL_LUA_VESION_I_ >= 504 +#if SOL_LUA_VERSION_I_ >= 504 // The manual implies that this function is almost always successful... // is it?? It could depend on the GC mode... return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) != 0; @@ -701,7 +701,7 @@ namespace sol { // THOUGHT: std::chrono-alikes to map "byte size" here...? // Make it harder to give MB or KB to a B parameter...? // Probably overkill for now. -#if SOL_LUA_VESION_I_ >= 504 +#if SOL_LUA_VERSION_I_ >= 504 int old_mode = lua_gc(lua_state(), LUA_GCINC, pause, step_multiplier, step_byte_size); if (old_mode == LUA_GCGEN) { return gc_mode::generational; @@ -719,7 +719,7 @@ namespace sol { // Returns the old GC mode. Check support using the supports_gc_mode function. gc_mode change_gc_mode_generational(int minor_multiplier, int major_multiplier) { -#if SOL_LUA_VESION_I_ >= 504 +#if SOL_LUA_VERSION_I_ >= 504 // "What does this shit mean?" // http://www.lua.org/manual/5.4/manual.html#2.5.2 int old_mode = lua_gc(lua_state(), LUA_GCGEN, minor_multiplier, major_multiplier); diff --git a/include/sol/usertype_storage.hpp b/include/sol/usertype_storage.hpp index 1cc1fcc47..fdfac5ff5 100644 --- a/include/sol/usertype_storage.hpp +++ b/include/sol/usertype_storage.hpp @@ -173,7 +173,7 @@ namespace sol { namespace u_detail { } struct string_for_each_metatable_func { - bool is_destroyion = false; + bool is_destruction = false; bool is_index = false; bool is_new_index = false; bool is_static_index = false; @@ -207,7 +207,7 @@ namespace sol { namespace u_detail { if (poison_indexing) { (usb.*change_indexing)(L_, smt_, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call); } - if (is_destroyion + if (is_destruction && (smt_ == submetatable_type::reference || smt_ == submetatable_type::const_reference || smt_ == submetatable_type::named || smt_ == submetatable_type::unique)) { // gc does not apply to us here @@ -473,45 +473,47 @@ namespace sol { namespace u_detail { template static inline int self_index_call(types, lua_State* L, usertype_storage_base& self) { - type k_type = stack::get(L, 2); - if (k_type == type::string) { - index_call_storage* target = nullptr; - { + if constexpr (!from_named_metatable || !is_new_index) { + type k_type = stack::get(L, 2); + if (k_type == type::string) { + index_call_storage* target = nullptr; string_view k = stack::get(L, 2); - auto it = self.string_keys.find(k); - if (it != self.string_keys.cend()) { - target = &it->second; - } - } - if (target != nullptr) { - // let the target decide what to do - if constexpr (is_new_index) { - return (target->new_index)(L, target->binding_data); - } - else { - return (target->index)(L, target->binding_data); + { + auto it = self.string_keys.find(k); + if (it != self.string_keys.cend()) { + target = &it->second; + } } - } - } - else if (k_type != type::lua_nil && k_type != type::none) { - stateless_reference* target = nullptr; - { - stack_reference k = stack::get(L, 2); - auto it = self.auxiliary_keys.find(k); - if (it != self.auxiliary_keys.cend()) { - target = &it->second; + if (target != nullptr) { + // let the target decide what to do, unless it's named... + if constexpr (is_new_index) { + return (target->new_index)(L, target->binding_data); + } + else { + return (target->index)(L, target->binding_data); + } } } - if (target != nullptr) { - if constexpr (is_new_index) { - // set value and return - target->reset(L, 3); - return 0; + else if (k_type != type::lua_nil && k_type != type::none) { + stateless_reference* target = nullptr; + { + stack_reference k = stack::get(L, 2); + auto it = self.auxiliary_keys.find(k); + if (it != self.auxiliary_keys.cend()) { + target = &it->second; + } } - else { - // push target to return - // what we found - return stack::push(L, *target); + if (target != nullptr) { + if constexpr (is_new_index) { + // set value and return + target->reset(L, 3); + return 0; + } + else { + // push target to return + // what we found + return stack::push(L, *target); + } } } } @@ -707,7 +709,7 @@ namespace sol { namespace u_detail { bool is_new_index = (s == to_string(meta_function::new_index)); bool is_static_index = (s == to_string(meta_function::static_index)); bool is_static_new_index = (s == to_string(meta_function::static_new_index)); - bool is_destroyion = s == to_string(meta_function::garbage_collect); + bool is_destruction = s == to_string(meta_function::garbage_collect); bool poison_indexing = (!is_using_index || !is_using_new_index) && (is_var_bind::value || is_index || is_new_index); void* derived_this = static_cast(static_cast*>(this)); index_call_storage ics; @@ -718,7 +720,7 @@ namespace sol { namespace u_detail { : &Binding::template index_call_with_; string_for_each_metatable_func for_each_fx; - for_each_fx.is_destroyion = is_destroyion; + for_each_fx.is_destruction = is_destruction; for_each_fx.is_index = is_index; for_each_fx.is_new_index = is_new_index; for_each_fx.is_static_index = is_static_index; diff --git a/include/sol/version.hpp b/include/sol/version.hpp index 1cd8db4c3..34dbb83c1 100644 --- a/include/sol/version.hpp +++ b/include/sol/version.hpp @@ -330,6 +330,20 @@ #endif #endif +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS_I_) && SOL_IS_OFF(SOL_SAFE_NUMERICS_I_) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + #if defined(SOL_SAFE_STACK_CHECK) #if SOL_SAFE_STACK_CHECK != 0 #define SOL_SAFE_STACK_CHECK_I_ SOL_ON diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8ab39765a..5c37d7b27 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,13 +24,65 @@ # # Dependencies FetchContent_Declare( - Catch2 + catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v2.13.4 + GIT_TAG v2.13.6 ) -FetchContent_MakeAvailable(Catch2) +FetchContent_MakeAvailable(catch2) + +function(sol2_add_test_properties target-name) + target_link_libraries(${target-name} + PUBLIC Threads::Threads ${LUA_LIBRARIES} Catch2::Catch2 ${CMAKE_DL_LIBS}) + target_compile_definitions(${target-name} + PUBLIC SOL_PRINT_ERRORS=1) + target_compile_options(${target-name} + PRIVATE + ${--template-debugging-mode} + ${--big-obj} + ${--no-unknown-warning} + ${--disable-permissive} + ${--pedantic} + ${--warn-all} + ${--warn-pedantic} + ${--warn-extra} + ${--warn-errors} + ${--utf8-literal-encoding} + ${--utf8-source-encoding} + + ${--allow-unknown-warning} + ${--allow-unknown-warning-option} + ${--allow-noexcept-type} + ${--allow-microsoft-casts} + ) + + target_compile_definitions(${target-name} + PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE) + + if (SOL2_CI) + target_compile_definitions(${target-name} + PRIVATE SOL2_CI) + endif() + + add_test(NAME ${target-name} COMMAND ${target-name}) + if(SOL2_ENABLE_INSTALL) + install(TARGETS ${target-name} RUNTIME DESTINATION bin) + endif() +endfunction() + +function(sol2_create_basic_test test_target_name target_sol) + set(test_target_name ${test_target_name}) + add_executable(${test_target_name} ${sources}) + sol2_add_test_properties(${test_target_name}) + target_link_libraries(${test_target_name} + PRIVATE ${target_sol}) + target_compile_definitions(${test_target_name} + PRIVATE SOL_ALL_SAFETIES_ON=1) +endfunction() add_subdirectory(inclusion) -add_subdirectory(runtime_tests) +add_subdirectory(environment) +add_subdirectory(numerics) +add_subdirectory(exceptions) add_subdirectory(config_tests) add_subdirectory(regression_tests) +add_subdirectory(run_time) diff --git a/tests/config_tests/CMakeLists.txt b/tests/config_tests/CMakeLists.txt index 080f17df8..89bc64ccb 100644 --- a/tests/config_tests/CMakeLists.txt +++ b/tests/config_tests/CMakeLists.txt @@ -23,3 +23,4 @@ # # # # sol2 tests add_subdirectory(function_pointers) +add_subdirectory(integer_value_fits) diff --git a/tests/config_tests/integer_value_fits/CMakeLists.txt b/tests/config_tests/integer_value_fits/CMakeLists.txt new file mode 100644 index 000000000..1747488e5 --- /dev/null +++ b/tests/config_tests/integer_value_fits/CMakeLists.txt @@ -0,0 +1,36 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 tests - environment + +file(GLOB sources + LIST_DIRECTORIES FALSE + CONFIGURE_DEPENDS + source/*.cpp) +source_group(test_sources FILES ${sources}) + +sol2_create_basic_test(sol2.tests.config.integer_value_fits sol2::sol2) +sol2_create_basic_test(sol2.tests.config.integer_value_fits.SOL_ALL_SAFETIES_ON sol2::sol2) +target_compile_definitions(sol2.tests.config.integer_value_fits PRIVATE + SOL_ALL_INTEGER_VALUES_FIT=1) +target_compile_definitions(sol2.tests.config.integer_value_fits.SOL_ALL_SAFETIES_ON PRIVATE + SOL_ALL_INTEGER_VALUES_FIT=1 SOL_ALL_SAFETIES_ON=1) diff --git a/tests/config_tests/integer_value_fits/source/main.cpp b/tests/config_tests/integer_value_fits/source/main.cpp new file mode 100644 index 000000000..c1cd70f05 --- /dev/null +++ b/tests/config_tests/integer_value_fits/source/main.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#define CATCH_CONFIG_RUNNER +#include + +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/tests/config_tests/integer_value_fits/source/negative_size_t.cpp b/tests/config_tests/integer_value_fits/source/negative_size_t.cpp new file mode 100644 index 000000000..ef5716932 --- /dev/null +++ b/tests/config_tests/integer_value_fits/source/negative_size_t.cpp @@ -0,0 +1,51 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +#include +#include + +inline namespace sol2_tests_negative_size_t { + static inline size_t npos_like_api() { + return size_t(-1); + } +} // namespace sol2_tests_negative_size_t + +#if SOL_LUA_VERSION_I_ >= 502 +TEST_CASE("numeric/negative size_t", "handle negative integers casted to size_t values") { + sol::state lua; + lua.set_function("f", &npos_like_api); + + auto result = lua.safe_script("v = f()", sol::script_pass_on_error); + sol::optional maybe_error = result; + REQUIRE(result.valid()); + REQUIRE(result.status() == sol::call_status::ok); + REQUIRE_FALSE(maybe_error.has_value()); + size_t should_be_like_npos = lua["v"]; + REQUIRE(should_be_like_npos == size_t(-1)); +} + +#endif diff --git a/tests/environment/CMakeLists.txt b/tests/environment/CMakeLists.txt new file mode 100644 index 000000000..bfe53fbee --- /dev/null +++ b/tests/environment/CMakeLists.txt @@ -0,0 +1,33 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 tests - environment + +file(GLOB sources + LIST_DIRECTORIES FALSE + CONFIGURE_DEPENDS + source/*.cpp) +source_group(test_sources FILES ${sources}) + +sol2_create_basic_test(sol2.tests.environment sol2::sol2) +target_compile_definitions(sol2.tests.environment PRIVATE + SOL_ALL_SAFETIES_ON=1) diff --git a/tests/environment/source/get.cpp b/tests/environment/source/get.cpp new file mode 100644 index 000000000..aeca23a85 --- /dev/null +++ b/tests/environment/source/get.cpp @@ -0,0 +1,132 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +inline namespace sol2_tests_environments_get { + struct check_g_env { + sol::state* plua; + sol::environment* penv_g; + + check_g_env(sol::state& lua, sol::environment& env_g) : plua(&lua), penv_g(&env_g) { + } + + void operator()(sol::function target) const { + sol::state& lua = *plua; + sol::environment& env_g = *penv_g; + sol::stack_guard luasg(lua); + sol::environment target_env = sol::get_environment(target); + int test_env_g = env_g["test"]; + int test_target_env = target_env["test"]; + REQUIRE(test_env_g == test_target_env); + REQUIRE(test_env_g == 5); + REQUIRE(env_g == target_env); + } + }; + + struct check_f_env { + sol::state* plua; + sol::environment* penv_f; + + check_f_env(sol::state& lua, sol::environment& env_f) : plua(&lua), penv_f(&env_f) { + } + + void operator()(sol::function target) const { + sol::state& lua = *plua; + sol::environment& env_f = *penv_f; + sol::stack_guard luasg(lua); + sol::environment target_env(sol::env_key, target); + int test_env_f = env_f["test"]; + int test_target_env = target_env["test"]; + REQUIRE(test_env_f == test_target_env); + REQUIRE(test_env_f == 31); + REQUIRE(env_f == target_env); + } + }; + + struct check_h_env { + sol::state* plua; + + check_h_env(sol::state& lua) : plua(&lua) { + } + + void operator()(sol::function target) const { + sol::state& lua = *plua; + sol::stack_guard luasg(lua); + sol::environment target_env = sol::get_environment(target); + // cannot strictly test + // if it's the global table, because different lua runtimes + // give different envs when there is no env + } + }; +} // namespace sol2_tests_environments_get + +TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") { + sol::state lua; + sol::stack_guard luasg(lua); + + lua.open_libraries(sol::lib::base); + + auto result1 = lua.safe_script("f = function() return test end", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::function f = lua["f"]; + + sol::environment env_f(lua, sol::create); + env_f["test"] = 31; + bool env_f_was_set = sol::set_environment(env_f, f); + REQUIRE(env_f_was_set); + + int result = f(); + REQUIRE(result == 31); + + auto result2 = lua.safe_script("g = function() test = 5 end", sol::script_pass_on_error); + REQUIRE(result2.valid()); + sol::function g = lua["g"]; + sol::environment env_g(lua, sol::create); + bool env_g_was_set = env_g.set_on(g); + REQUIRE(env_g_was_set); + + g(); + + int test = env_g["test"]; + REQUIRE(test == 5); + + sol::object global_test = lua["test"]; + REQUIRE(!global_test.valid()); + + auto result3 = lua.safe_script("h = function() end", sol::script_pass_on_error); + REQUIRE(result3.valid()); + + lua.set_function("check_f_env", check_f_env(lua, env_f)); + lua.set_function("check_g_env", check_g_env(lua, env_g)); + lua.set_function("check_h_env", check_h_env(lua)); + + auto checkf = lua.safe_script("check_f_env(f)", sol::script_pass_on_error); + REQUIRE(checkf.valid()); + auto checkg = lua.safe_script("check_g_env(g)", sol::script_pass_on_error); + REQUIRE(checkg.valid()); + auto checkh = lua.safe_script("check_h_env(h)", sol::script_pass_on_error); + REQUIRE(checkh.valid()); +} diff --git a/tests/environment/source/main.cpp b/tests/environment/source/main.cpp new file mode 100644 index 000000000..c1cd70f05 --- /dev/null +++ b/tests/environment/source/main.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#define CATCH_CONFIG_RUNNER +#include + +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/tests/environment/source/sandboxing.cpp b/tests/environment/source/sandboxing.cpp new file mode 100644 index 000000000..49b404942 --- /dev/null +++ b/tests/environment/source/sandboxing.cpp @@ -0,0 +1,92 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +TEST_CASE("environments/sanboxing", "see if environments on functions are working properly") { + SECTION("basic") { + sol::state lua; + sol::stack_guard luasg(lua); + + auto result1 = lua.safe_script("a = function() return 5 end", sol::script_pass_on_error); + REQUIRE(result1.valid()); + REQUIRE(result1.status() == sol::call_status::ok); + + sol::function a = lua["a"]; + + int result0 = a(); + REQUIRE(result0 == 5); + + sol::environment env(lua, sol::create); + bool env_set_on_a = sol::set_environment(env, a); + // either works; there can sometimes no environment + REQUIRE((env_set_on_a || !env_set_on_a)); + + int value = a(); + REQUIRE(value == 5); + } + SECTION("return environment value") { + sol::state lua; + sol::stack_guard luasg(lua); + + auto result1 = lua.safe_script("a = function() return test end", sol::script_pass_on_error); + REQUIRE(result1.valid()); + REQUIRE(result1.status() == sol::call_status::ok); + + sol::function a = lua["a"]; + sol::environment env(lua, sol::create); + env["test"] = 5; + bool env_set_on_a = env.set_on(a); + REQUIRE(env_set_on_a); + + // the function returns the value from the environment table + int result = a(); + REQUIRE(result == 5); + } + + SECTION("set environment value") { + sol::state lua; + sol::stack_guard luasg(lua); + + auto result1 = lua.safe_script("a = function() test = 5 end", sol::script_pass_on_error); + REQUIRE(result1.valid()); + REQUIRE(result1.status() == sol::call_status::ok); + + sol::function a = lua["a"]; + sol::environment env(lua, sol::create); + bool env_set_on_a = sol::set_environment(env, a); + REQUIRE(env_set_on_a); + + a(); + + // the value can be retrieved from the env table + int result = env["test"]; + REQUIRE(result == 5); + + // the global environment is not polluted + auto gtest = lua["test"]; + REQUIRE(!gtest.valid()); + } +} diff --git a/tests/environment/source/shadowing.cpp b/tests/environment/source/shadowing.cpp new file mode 100644 index 000000000..6974c3f8a --- /dev/null +++ b/tests/environment/source/shadowing.cpp @@ -0,0 +1,111 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +TEST_CASE("environments/shadowing", "Environments can properly shadow and fallback on variables") { + + sol::state lua; + sol::stack_guard luasg(lua); + + lua["b"] = 2142; + + SECTION("no fallback") { + sol::environment plain_env(lua, sol::create); + auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); + REQUIRE(result1.valid()); + REQUIRE(result1.status() == sol::call_status::ok); + sol::optional maybe_env_a = plain_env["a"]; + sol::optional maybe_global_a = lua["a"]; + sol::optional maybe_env_b = plain_env["b"]; + sol::optional maybe_global_b = lua["b"]; + + REQUIRE(maybe_env_a != sol::nullopt); + REQUIRE(maybe_env_a.value() == 24); + REQUIRE(maybe_env_b == sol::nullopt); + + REQUIRE(maybe_global_a == sol::nullopt); + REQUIRE(maybe_global_b != sol::nullopt); + REQUIRE(maybe_global_b.value() == 2142); + } + SECTION("fallback") { + sol::environment env_with_fallback(lua, sol::create, lua.globals()); + auto result1 = lua.safe_script("a = 56", env_with_fallback, sol::script_pass_on_error); + REQUIRE(result1.valid()); + REQUIRE(result1.status() == sol::call_status::ok); + sol::optional maybe_env_a = env_with_fallback["a"]; + sol::optional maybe_global_a = lua["a"]; + sol::optional maybe_env_b = env_with_fallback["b"]; + sol::optional maybe_global_b = lua["b"]; + + REQUIRE(maybe_env_a != sol::nullopt); + REQUIRE(maybe_env_a.value() == 56); + REQUIRE(maybe_env_b != sol::nullopt); + REQUIRE(maybe_env_b.value() == 2142); + + REQUIRE(maybe_global_a == sol::nullopt); + REQUIRE(maybe_global_b != sol::nullopt); + REQUIRE(maybe_global_b.value() == 2142); + } + SECTION("from name") { + sol::environment env_with_fallback(lua, sol::create, lua.globals()); + lua["env"] = env_with_fallback; + sol::environment env = lua["env"]; + auto result1 = lua.safe_script("a = 56", env, sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::optional maybe_env_a = env["a"]; + sol::optional maybe_global_a = lua["a"]; + sol::optional maybe_env_b = env["b"]; + sol::optional maybe_global_b = lua["b"]; + + REQUIRE(maybe_env_a != sol::nullopt); + REQUIRE(maybe_env_a.value() == 56); + REQUIRE(maybe_env_b != sol::nullopt); + REQUIRE(maybe_env_b.value() == 2142); + + REQUIRE(maybe_global_a == sol::nullopt); + REQUIRE(maybe_global_b != sol::nullopt); + REQUIRE(maybe_global_b.value() == 2142); + } + SECTION("name with newtable") { + lua["blank_env"] = sol::new_table(0, 1); + sol::environment plain_env = lua["blank_env"]; + auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); + REQUIRE(result1.valid()); + + sol::optional maybe_env_a = plain_env["a"]; + sol::optional maybe_global_a = lua["a"]; + sol::optional maybe_env_b = plain_env["b"]; + sol::optional maybe_global_b = lua["b"]; + + REQUIRE(maybe_env_a != sol::nullopt); + REQUIRE(maybe_env_a.value() == 24); + REQUIRE(maybe_env_b == sol::nullopt); + + REQUIRE(maybe_global_a == sol::nullopt); + REQUIRE(maybe_global_b != sol::nullopt); + REQUIRE(maybe_global_b.value() == 2142); + } +} diff --git a/tests/environment/source/this_environment.cpp b/tests/environment/source/this_environment.cpp new file mode 100644 index 000000000..89151a7fd --- /dev/null +++ b/tests/environment/source/this_environment.cpp @@ -0,0 +1,93 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +TEST_CASE("environments/this_environment", "test various situations of pulling out an environment") { + static std::string code = "return (f(10))"; + + sol::state lua; + sol::stack_guard luasg(lua); + + lua["f"] = [](sol::this_environment te, int x, sol::this_state ts) { + if (te) { + sol::environment& env = te; + return x + static_cast(env["x"]); + } + sol::state_view lua = ts; + return x + static_cast(lua["x"]); + }; + + sol::environment e(lua, sol::create, lua.globals()); + lua["x"] = 5; + e["x"] = 20; + SECTION("from Lua script") { + auto result1 = lua.safe_script(code, e, sol::script_pass_on_error); + REQUIRE(result1.valid()); + int value = result1; + REQUIRE(value == 30); + } + SECTION("from C++") { + sol::function f = lua["f"]; + bool env_set = e.set_on(f); + REQUIRE(env_set); + int value = f(10); + REQUIRE(value == 30); + } + SECTION("from C++, with no env") { + sol::function f = lua["f"]; + int value = f(10); + REQUIRE(value == 15); + } +} + +TEST_CASE("environment/this_environment/nested_calls", "Test that this_environment actually finds the right environment in specific nested Lua call contexts") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("print_no_env", [](int x) { REQUIRE(x == 1); }); + + lua.set_function("print_this_env", [](int x, sol::this_environment env) { REQUIRE(x == 2); }); + + sol::protected_function_result result = lua.safe_script(R"( + local var = nil + + function test_1_no_env() + var = 1 + print_no_env(1) + end + + function test_2_this_env() + var = 1 + print_this_env(2) + end + + test_1_no_env() -- should be ok + test_2_this_env() -- should be okay + )", + sol::script_pass_on_error); + + REQUIRE(result.valid()); +} diff --git a/tests/exceptions/CMakeLists.txt b/tests/exceptions/CMakeLists.txt new file mode 100644 index 000000000..cce65d65a --- /dev/null +++ b/tests/exceptions/CMakeLists.txt @@ -0,0 +1,40 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 tests - environment + +file(GLOB sources + LIST_DIRECTORIES FALSE + CONFIGURE_DEPENDS + source/*.cpp) +source_group(test_sources FILES ${sources}) + +sol2_create_basic_test(sol2.tests.exceptions sol2::sol2) +target_compile_definitions(sol2.tests.exceptions PRIVATE + SOL_ALL_SAFETIES_ON=1) +target_compile_options(sol2.tests.exceptions PRIVATE + ${--allow-unreachable-code}) +sol2_create_basic_test(sol2.tests.exceptions.SOL_ALL_SAFETIES_ON sol2::sol2) +target_compile_definitions(sol2.tests.exceptions.SOL_ALL_SAFETIES_ON PRIVATE + SOL_ALL_SAFETIES_ON=1) +target_compile_options(sol2.tests.exceptions.SOL_ALL_SAFETIES_ON PRIVATE + ${--allow-unreachable-code}) diff --git a/tests/exceptions/source/functions.cpp b/tests/exceptions/source/functions.cpp new file mode 100644 index 000000000..5d49fa831 --- /dev/null +++ b/tests/exceptions/source/functions.cpp @@ -0,0 +1,192 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +#include +#include + +inline namespace sol2_tests_exceptions_functions { + inline constexpr const std::string_view special_string = "Whoopsie [expected]"; + + static void func_throw() { + throw std::runtime_error(special_string.data()); + } + + struct some_class { + void mem_func_throw() { + throw std::runtime_error(special_string.data()); + } + }; +} // namespace sol2_tests_exceptions_functions + +TEST_CASE("exceptions/functions", "exercise the ability to throw exceptions many different function binding code paths") { + sol::state lua; + lua.open_libraries(sol::lib::base, + sol::lib::package, + sol::lib::coroutine, + sol::lib::string, + sol::lib::os, + sol::lib::math, + sol::lib::table, + sol::lib::io, + sol::lib::debug); + + [[maybe_unused]] int a = 10; + some_class sc {}; + auto throw_action = [](sol::state& lua, bool use_sc) { + if (use_sc) { + auto res = lua.safe_script("func_throw(sc)", sol::script_pass_on_error); + REQUIRE_FALSE(res.valid()); + REQUIRE(res.status() == sol::call_status::runtime); + sol::error err = res.get(); + std::string_view err_what(err.what()); + REQUIRE(err_what.find(special_string) != std::string::npos); + } + else { + auto res = lua.safe_script("func_throw()", sol::script_pass_on_error); + REQUIRE_FALSE(res.valid()); + REQUIRE(res.status() == sol::call_status::runtime); + sol::error err = res.get(); + std::string_view err_what(err.what()); + REQUIRE(err_what.find(special_string) != std::string::npos); + } + }; + + lua["sc"] = ≻ + + SECTION("proxy") { + lua["func_throw"] = sol::property(&func_throw, &some_class::mem_func_throw); + REQUIRE_NOTHROW(throw_action(lua, false)); + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua["func_throw"] = sol::property(&some_class::mem_func_throw); + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua["func_throw"] = sol::readonly_property(func_throw); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = sol::writeonly_property(&some_class::mem_func_throw); + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua["func_throw"] = [f = &func_throw] { return f(); }; + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = &func_throw; + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = [] { return func_throw(); }; + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = [a]() { return func_throw(); }; + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = [&sc]() { return sc.mem_func_throw(); }; + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = &some_class::mem_func_throw; + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua["func_throw"] = std::function([f = &func_throw] { return f(); }); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = sol::overload(std::function([f = &func_throw] { return f(); })); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = std::function([] { return func_throw(); }); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = std::function(&func_throw); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua["func_throw"] = std::function(&some_class::mem_func_throw); + REQUIRE_NOTHROW(throw_action(lua, true)); + } + + SECTION("set_function") { + lua.set_function("func_throw", sol::property(&func_throw, &some_class::mem_func_throw)); + REQUIRE_NOTHROW(throw_action(lua, false)); + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua.set_function("func_throw", sol::property(&some_class::mem_func_throw)); + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua.set_function("func_throw", sol::readonly_property(func_throw)); + REQUIRE_NOTHROW(throw_action(lua, false)); + + // TODO: better handling of no_prop in this case here + // lua.set_function("func_throw", sol::writeonly_property(&some_class::mem_func_throw)); + // REQUIRE_NOTHROW(throw_action(lua, true)); + + lua.set_function("func_throw", [f = &func_throw] { return f(); }); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", &func_throw); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", [] { return func_throw(); }); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", [a]() { return func_throw(); }); + REQUIRE_NOTHROW(throw_action(lua, false)); + + // TODO: this should work at some point, yeah? + /* + lua.set_function( + "func_throw", [](some_class& sc) { return sc.mem_func_throw(); }, sc); + REQUIRE_NOTHROW(throw_action(lua, false)); + */ + + lua.set_function("func_throw", [&sc]() { return sc.mem_func_throw(); }); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", &some_class::mem_func_throw); + REQUIRE_NOTHROW(throw_action(lua, true)); + + lua.set_function("func_throw", std::function([f = &func_throw] { return f(); })); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", sol::overload(std::function([f = &func_throw] { return f(); }))); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", std::function([] { return func_throw(); })); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", std::function(&func_throw)); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", &some_class::mem_func_throw, &sc); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", &some_class::mem_func_throw, sc); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", &some_class::mem_func_throw, std::ref(sc)); + REQUIRE_NOTHROW(throw_action(lua, false)); + + lua.set_function("func_throw", std::function(&some_class::mem_func_throw)); + REQUIRE_NOTHROW(throw_action(lua, true)); + } +} diff --git a/tests/exceptions/source/functions.noexcept.cpp b/tests/exceptions/source/functions.noexcept.cpp new file mode 100644 index 000000000..55dbfd68c --- /dev/null +++ b/tests/exceptions/source/functions.noexcept.cpp @@ -0,0 +1,95 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +inline namespace sol2_tests_exceptions_functions_noexcept { + + struct T { + static int noexcept_function() noexcept { + return 0x61; + } + + int noexcept_method() noexcept { + return 0x62; + } + }; + + static int raw_noexcept_function(lua_State* L) noexcept { + return sol::stack::push(L, 0x63); + } + +} // namespace sol2_tests_exceptions_functions_noexcept + +TEST_CASE("exceptions/functions/noexcept", "allow noexcept functions to be serialized properly into Lua using sol2") { + T t {}; + + lua_CFunction ccall = sol::c_call; + + sol::state lua; + + auto check_script_call = [&lua](std::string script) { + auto result = lua.safe_script(script, &sol::script_pass_on_error); + sol::optional maybe_err = result; + REQUIRE(result.valid()); + REQUIRE(result.status() == sol::call_status::ok); + REQUIRE_FALSE(maybe_err.has_value()); + }; + + lua.set_function("f", &T::noexcept_function); + lua.set_function("g", &T::noexcept_method); + lua.set_function("h", &T::noexcept_method, T()); + lua.set_function("i", &T::noexcept_method, std::ref(t)); + lua.set_function("j", &T::noexcept_method, &t); + lua.set_function("k", &T::noexcept_method, t); + lua.set_function("l", &raw_noexcept_function); + lua.set_function("m", ccall); + + lua["t"] = T(); + check_script_call("v1 = f()"); + check_script_call("v2 = g(t)"); + check_script_call("v3 = h()"); + check_script_call("v4 = i()"); + check_script_call("v5 = j()"); + check_script_call("v6 = k()"); + check_script_call("v7 = l()"); + check_script_call("v8 = m()"); + int v1 = lua["v1"]; + int v2 = lua["v2"]; + int v3 = lua["v3"]; + int v4 = lua["v4"]; + int v5 = lua["v5"]; + int v6 = lua["v6"]; + int v7 = lua["v7"]; + int v8 = lua["v8"]; + REQUIRE(v1 == 0x61); + REQUIRE(v2 == 0x62); + REQUIRE(v3 == 0x62); + REQUIRE(v4 == 0x62); + REQUIRE(v5 == 0x62); + REQUIRE(v6 == 0x62); + REQUIRE(v7 == 0x63); + REQUIRE(v8 == 0x63); +} \ No newline at end of file diff --git a/tests/exceptions/source/functions.yielding.cpp b/tests/exceptions/source/functions.yielding.cpp new file mode 100644 index 000000000..bcdd5d7d8 --- /dev/null +++ b/tests/exceptions/source/functions.yielding.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +TEST_CASE("exceptions/functions/yielding", "exercise the ability to throw exceptions many different function binding code paths for sol::yielding") { + sol::state lua; +} diff --git a/tests/exceptions/source/main.cpp b/tests/exceptions/source/main.cpp new file mode 100644 index 000000000..c1cd70f05 --- /dev/null +++ b/tests/exceptions/source/main.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#define CATCH_CONFIG_RUNNER +#include + +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/tests/exceptions/source/usertypes.cpp b/tests/exceptions/source/usertypes.cpp new file mode 100644 index 000000000..cf19e71ce --- /dev/null +++ b/tests/exceptions/source/usertypes.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +TEST_CASE("exceptions/usertypes", "exercise the ability to throw exceptions many different usertype code paths") { + sol::state lua; +} diff --git a/tests/exceptions/source/usertypes.yielding.cpp b/tests/exceptions/source/usertypes.yielding.cpp new file mode 100644 index 000000000..4b18094d7 --- /dev/null +++ b/tests/exceptions/source/usertypes.yielding.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +TEST_CASE("exceptions/usertypes/yielding", "exercise the ability to throw exceptions many different usertype code paths for sol::yielding") { + sol::state lua; +} diff --git a/tests/inclusion/CMakeLists.txt b/tests/inclusion/CMakeLists.txt index 028567b43..23288461e 100644 --- a/tests/inclusion/CMakeLists.txt +++ b/tests/inclusion/CMakeLists.txt @@ -22,81 +22,36 @@ # # # # sol2 tests - header compilation tests -file(GLOB_RECURSE SOL2_COMPILE_TEST_SOURCES +file(GLOB_RECURSE sources LIST_DIRECTORIES FALSE CONFIGURE_DEPENDS source/*.cpp) -source_group(compile_test_sources FILES "${SOL2_COMPILE_TEST_SOURCES}") +set(sources-single + "source/main.cpp" "source/forward.cpp" + "source/sol.cpp" "source/config.cpp") -function(CREATE_TEST test_target_name test_name target_sol) - if (test_name MATCHES ".single") - add_executable(${test_target_name} "source/main.cpp" "source/forward.cpp" "source/sol.cpp" "source/config.cpp") - else() - add_executable(${test_target_name} "${SOL2_COMPILE_TEST_SOURCES}") - endif() - set_target_properties(${test_target_name} - PROPERTIES - OUTPUT_NAME ${test_name} - EXPORT_NAME sol2::${test_name}) - target_link_libraries(${test_target_name} - PUBLIC Threads::Threads ${LUA_LIBRARIES} ${target_sol} ${CMAKE_DL_LIBS}) - target_compile_definitions(${test_target_name} - PRIVATE - SOL_ENABLE_INTEROP=1 - SOL_ALL_SAFETIES_ON=1) - if (MSVC) - target_compile_options(${test_target_name} - PRIVATE /std:c++latest /EHsc "$<$:/MDd>" - "$<$:/MD>" - "$<$:/MD>" - "$<$:/MD>") - target_compile_definitions(${test_target_name} - PRIVATE UNICODE _UNICODE - _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE) - else() - target_compile_options(${test_target_name} - PRIVATE -std=c++1z - -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors - -Wno-noexcept-type) +set(target-variants + "SOL_ALL_SAFETIES_ON" + "SOL_USE_INTEROP" + "SOL_STRINGS_ARE_NUMBERS") - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # For another day, when C++ is not so crap - # and we have time to audit the entire lib - # for all uses of `detail::swallow`... - #target_compile_options(${test_target_name} - # PRIVATE -Wcomma) - endif() - endif() +function(CREATE_TEST test_target_name target_sol) + set(test_sources ${ARGN}) + add_executable(${test_target_name} ${test_sources}) + sol2_add_test_properties(${test_target_name}) + target_link_libraries(${test_target_name} + PRIVATE ${target_sol}) +endfunction() + +foreach(variant ${target-variants}) + set(target-name "sol2.tests.inclusion.${variant}") + set(single-target-name "sol2.single.tests.inclusion.${variant}") - if (MSVC) - if (NOT CMAKE_COMPILER_ID MATCHES "Clang") - target_compile_options(${test_target_name} - PRIVATE /bigobj /W4) - endif() - else() - if (IS_X86) - if(MINGW) - set_target_properties(${test_target_name} - PROPERTIES - LINK_FLAGS -static-libstdc++) - endif() - endif() - endif() - if (SOL2_CI) - target_compile_definitions(${test_target_name} - PRIVATE SOL2_CI) - endif() + CREATE_TEST(${target-name} sol2::sol2 ${sources}) + target_compile_definitions(${target-name} PRIVATE ${variant}=1) - add_test(NAME ${test_name} COMMAND ${test_target_name}) - if(SOL2_ENABLE_INSTALL) - install(TARGETS ${test_target_name} RUNTIME DESTINATION bin) + if (SOL2_TESTS_SINGLE) + CREATE_TEST(${single-target-name} sol2::sol2::single ${sources-single}) + target_compile_definitions(${single-target-name} PRIVATE ${variant}=1) endif() -endfunction(CREATE_TEST) - -if (SOL2_TESTS) - CREATE_TEST(compile_tests "sol2.compile_tests" sol2::sol2) -endif() -if (SOL2_TESTS_SINGLE) - CREATE_TEST(compile_tests_single "sol2.compile_tests.single" sol2::sol2::single) -endif() +endforeach() diff --git a/tests/numerics/CMakeLists.txt b/tests/numerics/CMakeLists.txt new file mode 100644 index 000000000..31ed7d0b9 --- /dev/null +++ b/tests/numerics/CMakeLists.txt @@ -0,0 +1,34 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 tests - environment + +file(GLOB sources + LIST_DIRECTORIES FALSE + CONFIGURE_DEPENDS + source/*.cpp) +source_group(test_sources FILES ${sources}) + +sol2_create_basic_test(sol2.tests.numerics sol2::sol2) +sol2_create_basic_test(sol2.tests.numerics.SOL_ALL_SAFETIES_ON sol2::sol2) +target_compile_definitions(sol2.tests.numerics.SOL_ALL_SAFETIES_ON PRIVATE + SOL_ALL_SAFETIES_ON=1) diff --git a/tests/runtime_tests/source/large_integer.cpp b/tests/numerics/source/large.cpp similarity index 95% rename from tests/runtime_tests/source/large_integer.cpp rename to tests/numerics/source/large.cpp index 010959cf7..b18dbc9e6 100644 --- a/tests/runtime_tests/source/large_integer.cpp +++ b/tests/numerics/source/large.cpp @@ -1,168 +1,168 @@ -// sol2 - -// The MIT License (MIT) - -// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_test.hpp" - -#include - -#include -#include - -inline namespace sol2_test_large_integer { - inline bool bool_roundtrip(bool num) { - REQUIRE(num == true); - return num; - } - - inline void trigger_passthrough_crash(sol::state& lua) { - sol::protected_function pf = lua["f"]; - auto result = pf(0xFFFFFFFFFFFFFFFFull); - (void)result; - } - - template - inline T intT_passthrough(T num) { - return num; - } - - template - inline T intT_roundtrip(T num) { - REQUIRE(num == std::numeric_limits::max()); - return num; - } - - inline std::uint64_t int53_roundtrip(std::uint64_t num) { - REQUIRE(num == 0x1FFFFFFFFFFFFFull); - return num; - } -} // namespace sol2_test_large_integer - -TEST_CASE("large_integer/bool", "pass bool integral value to and from lua") { - sol::state lua; - lua.open_libraries(); - lua.set_function("f", bool_roundtrip); - sol::optional result1 = lua.safe_script( - "x = f(true)\n" - "assert(x == true)", - sol::script_pass_on_error); - REQUIRE_FALSE(result1.has_value()); - sol::object x = lua["x"]; - REQUIRE(x.is()); - REQUIRE(x.as() == true); - REQUIRE_FALSE(x.is()); - { - auto result = lua.safe_script("f(1)", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } -} - -TEST_CASE("large_integers/unsigned32", "pass large unsigned 32bit values to and from lua") { - using T = std::uint32_t; - sol::state lua; - lua.open_libraries(); - lua.set_function("f", intT_roundtrip); - auto result1 = lua.safe_script( - "x = f(0xFFFFFFFF)\n" - "assert(x == 0xFFFFFFFF)", - sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::object x = lua["x"]; - REQUIRE(x.is()); - REQUIRE(x.as() == 0xFFFFFFFF); -} - -TEST_CASE("large_integer/unsigned53", "pass large unsigned 53bit value to and from lua") { - using T = std::uint64_t; - sol::state lua; - lua.open_libraries(); - lua.set_function("f", int53_roundtrip); - auto result1 = lua.safe_script( - "x = f(0x1FFFFFFFFFFFFF)\n" - "assert(x == 0x1FFFFFFFFFFFFF)"); - REQUIRE(result1.valid()); - sol::object x = lua["x"]; - REQUIRE(x.is()); - REQUIRE(x.as() == 0x1FFFFFFFFFFFFFull); -} - -TEST_CASE("large_integer/unsigned64", "pass too large unsigned 64bit value to lua") { - using T = std::int64_t; - sol::state lua; - lua.set_function("f", intT_passthrough); - REQUIRE_THROWS(trigger_passthrough_crash(lua)); -} - -TEST_CASE("large_integer/double", "pass negative and large positive values as signed and unsigned from and to lua") { - sol::state lua; - lua.open_libraries(); - lua.set_function("s32", intT_passthrough); - lua.set_function("s64", intT_passthrough); - lua.set_function("u32", intT_passthrough); - lua.set_function("u64", intT_passthrough); - { - // signed 32bit - auto result1 = lua.safe_script("x = s32(-1)", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); - REQUIRE(result2.valid()); - auto result3 = lua.safe_script("x = s32(0xFFFFFFFF)", sol::script_pass_on_error); - REQUIRE(result3.valid()); - auto result4 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); - REQUIRE(result4.valid()); - - sol::object x = lua["x"]; - REQUIRE(x.is()); - REQUIRE(x.as() == -1); - REQUIRE(x.is()); - REQUIRE(x.as() == 0xFFFFFFFF); - } - - // unsigned 32bit - { - auto result1 = lua.safe_script("x = u32(0xFFFFFFFF)", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); - REQUIRE(result2.valid()); - auto result3 = lua.safe_script("x = u32(-1)", sol::script_pass_on_error); - REQUIRE(result3.valid()); - auto result4 = lua.safe_script("assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); - REQUIRE(result4.valid()); - sol::object x = lua["x"]; - REQUIRE(x.is()); - REQUIRE(x.as() == -1); - REQUIRE(x.is()); - REQUIRE(x.as() == 0xFFFFFFFF); - } - // signed 64bit - { - auto result1 = lua.safe_script("x = s64(-1)", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); - REQUIRE(result2.valid()); - sol::object x = lua["x"]; - REQUIRE(x.is()); - REQUIRE(x.as() == -1); - REQUIRE(x.is()); - REQUIRE(x.as() == 0xFFFFFFFFFFFFFFFFull); - } -} +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +#include +#include + +inline namespace sol2_tests_large_integer { + inline bool bool_roundtrip(bool num) { + REQUIRE(num == true); + return num; + } + + inline void trigger_passthrough_crash(sol::state& lua) { + sol::protected_function pf = lua["f"]; + auto result = pf(0xFFFFFFFFFFFFFFFFull); + (void)result; + } + + template + inline T intT_passthrough(T num) { + return num; + } + + template + inline T intT_roundtrip(T num) { + REQUIRE(num == std::numeric_limits::max()); + return num; + } + + inline std::uint64_t int53_roundtrip(std::uint64_t num) { + REQUIRE(num == 0x1FFFFFFFFFFFFFull); + return num; + } +} // namespace sol2_tests_large_integer + +TEST_CASE("large_integer/bool", "pass bool integral value to and from lua") { + sol::state lua; + lua.open_libraries(); + lua.set_function("f", bool_roundtrip); + sol::optional result1 = lua.safe_script( + "x = f(true)\n" + "assert(x == true)", + sol::script_pass_on_error); + REQUIRE_FALSE(result1.has_value()); + sol::object x = lua["x"]; + REQUIRE(x.is()); + REQUIRE(x.as() == true); + REQUIRE_FALSE(x.is()); + { + auto result = lua.safe_script("f(1)", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } +} + +TEST_CASE("large_integers/unsigned32", "pass large unsigned 32bit values to and from lua") { + using T = std::uint32_t; + sol::state lua; + lua.open_libraries(); + lua.set_function("f", intT_roundtrip); + auto result1 = lua.safe_script( + "x = f(0xFFFFFFFF)\n" + "assert(x == 0xFFFFFFFF)", + sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::object x = lua["x"]; + REQUIRE(x.is()); + REQUIRE(x.as() == 0xFFFFFFFF); +} + +TEST_CASE("large_integer/unsigned53", "pass large unsigned 53bit value to and from lua") { + using T = std::uint64_t; + sol::state lua; + lua.open_libraries(); + lua.set_function("f", int53_roundtrip); + auto result1 = lua.safe_script( + "x = f(0x1FFFFFFFFFFFFF)\n" + "assert(x == 0x1FFFFFFFFFFFFF)"); + REQUIRE(result1.valid()); + sol::object x = lua["x"]; + REQUIRE(x.is()); + REQUIRE(x.as() == 0x1FFFFFFFFFFFFFull); +} + +TEST_CASE("large_integer/unsigned64", "pass too large unsigned 64bit value to lua") { + using T = std::int64_t; + sol::state lua; + lua.set_function("f", intT_passthrough); + REQUIRE_THROWS(trigger_passthrough_crash(lua)); +} + +TEST_CASE("large_integer/double", "pass negative and large positive values as signed and unsigned from and to lua") { + sol::state lua; + lua.open_libraries(); + lua.set_function("s32", intT_passthrough); + lua.set_function("s64", intT_passthrough); + lua.set_function("u32", intT_passthrough); + lua.set_function("u64", intT_passthrough); + { + // signed 32bit + auto result1 = lua.safe_script("x = s32(-1)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("x = s32(0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); + REQUIRE(result4.valid()); + + sol::object x = lua["x"]; + REQUIRE(x.is()); + REQUIRE(x.as() == -1); + REQUIRE(x.is()); + REQUIRE(x.as() == 0xFFFFFFFF); + } + + // unsigned 32bit + { + auto result1 = lua.safe_script("x = u32(0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("x = u32(-1)", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result4.valid()); + sol::object x = lua["x"]; + REQUIRE(x.is()); + REQUIRE(x.as() == -1); + REQUIRE(x.is()); + REQUIRE(x.as() == 0xFFFFFFFF); + } + // signed 64bit + { + auto result1 = lua.safe_script("x = s64(-1)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + sol::object x = lua["x"]; + REQUIRE(x.is()); + REQUIRE(x.as() == -1); + REQUIRE(x.is()); + REQUIRE(x.as() == 0xFFFFFFFFFFFFFFFFull); + } +} diff --git a/tests/numerics/source/main.cpp b/tests/numerics/source/main.cpp new file mode 100644 index 000000000..c1cd70f05 --- /dev/null +++ b/tests/numerics/source/main.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#define CATCH_CONFIG_RUNNER +#include + +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/tests/run_time/CMakeLists.txt b/tests/run_time/CMakeLists.txt new file mode 100644 index 000000000..f8fbeb085 --- /dev/null +++ b/tests/run_time/CMakeLists.txt @@ -0,0 +1,33 @@ +# # # # sol2 +# The MIT License (MIT) +# +# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# # # # sol2 tests - runtime tests + +file(GLOB sources + LIST_DIRECTORIES FALSE + CONFIGURE_DEPENDS + source/*.cpp) + +sol2_create_basic_test("sol2.tests.run_time" sol2::sol2) +if (SOL2_TESTS_SINGLE) + sol2_create_basic_test("sol2.single.tests.run_time" sol2::sol2::single) +endif() diff --git a/tests/runtime_tests/source/basic.cpp b/tests/run_time/source/basic.cpp similarity index 100% rename from tests/runtime_tests/source/basic.cpp rename to tests/run_time/source/basic.cpp diff --git a/tests/runtime_tests/source/common_classes.hpp b/tests/run_time/source/common_classes.hpp similarity index 100% rename from tests/runtime_tests/source/common_classes.hpp rename to tests/run_time/source/common_classes.hpp diff --git a/tests/runtime_tests/source/container.usertype_check.cpp b/tests/run_time/source/container.usertype_check.cpp similarity index 100% rename from tests/runtime_tests/source/container.usertype_check.cpp rename to tests/run_time/source/container.usertype_check.cpp diff --git a/tests/runtime_tests/source/container_semantics.cpp b/tests/run_time/source/container_semantics.cpp similarity index 100% rename from tests/runtime_tests/source/container_semantics.cpp rename to tests/run_time/source/container_semantics.cpp diff --git a/tests/runtime_tests/source/container_semantics.custom.cpp b/tests/run_time/source/container_semantics.custom.cpp similarity index 100% rename from tests/runtime_tests/source/container_semantics.custom.cpp rename to tests/run_time/source/container_semantics.custom.cpp diff --git a/tests/runtime_tests/source/container_semantics.ordered.cpp b/tests/run_time/source/container_semantics.ordered.cpp similarity index 96% rename from tests/runtime_tests/source/container_semantics.ordered.cpp rename to tests/run_time/source/container_semantics.ordered.cpp index d62f24848..ffd4bfeb9 100644 --- a/tests/runtime_tests/source/container_semantics.ordered.cpp +++ b/tests/run_time/source/container_semantics.ordered.cpp @@ -257,7 +257,7 @@ void associative_ordered_container_key_value_check(sol::state& lua, T& data, T& typedef typename T::mapped_type V; lua["collect"] = [&reflect](K k, V v) { reflect.insert({ k, v }); }; -#if SOL_LUA_VERSION > 502 +#if SOL_LUA_VERSION_I_ > 502 lua["val"] = data; auto r = lua.safe_script(R"( for k, v in pairs(val) do diff --git a/tests/runtime_tests/source/container_semantics.unordered.cpp b/tests/run_time/source/container_semantics.unordered.cpp similarity index 100% rename from tests/runtime_tests/source/container_semantics.unordered.cpp rename to tests/run_time/source/container_semantics.unordered.cpp diff --git a/tests/runtime_tests/source/container_shims.cpp b/tests/run_time/source/container_shims.cpp similarity index 95% rename from tests/runtime_tests/source/container_shims.cpp rename to tests/run_time/source/container_shims.cpp index f2686e24f..9377a6859 100644 --- a/tests/runtime_tests/source/container_shims.cpp +++ b/tests/run_time/source/container_shims.cpp @@ -255,7 +255,7 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al not_really_a_container c; lua["c"] = &c; -#if SOL_LUA_VERSION > 502 +#if SOL_LUA_VERSION_I_ > 502 auto result0 = lua.safe_script(R"lua( for k, v in pairs(c) do assert((k - 1) == v:val()) diff --git a/tests/runtime_tests/source/container_table.cpp b/tests/run_time/source/container_table.cpp similarity index 100% rename from tests/runtime_tests/source/container_table.cpp rename to tests/run_time/source/container_table.cpp diff --git a/tests/runtime_tests/source/containers.cpp b/tests/run_time/source/containers.cpp similarity index 100% rename from tests/runtime_tests/source/containers.cpp rename to tests/run_time/source/containers.cpp diff --git a/tests/runtime_tests/source/containers.roundtrip.cpp b/tests/run_time/source/containers.roundtrip.cpp similarity index 100% rename from tests/runtime_tests/source/containers.roundtrip.cpp rename to tests/run_time/source/containers.roundtrip.cpp diff --git a/tests/runtime_tests/source/containers.table.cpp b/tests/run_time/source/containers.table.cpp similarity index 100% rename from tests/runtime_tests/source/containers.table.cpp rename to tests/run_time/source/containers.table.cpp diff --git a/tests/runtime_tests/source/coroutines.cpp b/tests/run_time/source/coroutines.cpp similarity index 99% rename from tests/runtime_tests/source/coroutines.cpp rename to tests/run_time/source/coroutines.cpp index 36dda247d..afc71bc78 100644 --- a/tests/runtime_tests/source/coroutines.cpp +++ b/tests/run_time/source/coroutines.cpp @@ -65,7 +65,8 @@ inline namespace sol2_test_coroutines { mThread = sol::thread::create(luaContext); sol::state_view luaThreadState = mThread.state(); mThreadEnvironment = sol::environment(luaThreadState, sol::create, luaThreadState.globals()); - sol::set_environment(mThreadEnvironment, mThread); + bool thread_environment_set_successfully = sol::set_environment(mThreadEnvironment, mThread); + REQUIRE(thread_environment_set_successfully); sol::optional actionTable = luaThreadState["aTable"]; if (actionTable) { diff --git a/tests/runtime_tests/source/customizations.cpp b/tests/run_time/source/customizations.cpp similarity index 100% rename from tests/runtime_tests/source/customizations.cpp rename to tests/run_time/source/customizations.cpp diff --git a/tests/runtime_tests/source/customizations_private.cpp b/tests/run_time/source/customizations_private.cpp similarity index 100% rename from tests/runtime_tests/source/customizations_private.cpp rename to tests/run_time/source/customizations_private.cpp diff --git a/tests/runtime_tests/source/dump.cpp b/tests/run_time/source/dump.cpp similarity index 100% rename from tests/runtime_tests/source/dump.cpp rename to tests/run_time/source/dump.cpp diff --git a/tests/runtime_tests/source/functions.cpp b/tests/run_time/source/functions.cpp similarity index 96% rename from tests/runtime_tests/source/functions.cpp rename to tests/run_time/source/functions.cpp index 30cc225ed..cb34bdd79 100644 --- a/tests/runtime_tests/source/functions.cpp +++ b/tests/run_time/source/functions.cpp @@ -105,10 +105,6 @@ struct fer { } }; -static int raw_noexcept_function(lua_State* L) noexcept { - return sol::stack::push(L, 0x63); -} - TEST_CASE("functions/tuple returns", "Make sure tuple returns are ordered properly") { sol::state lua; auto result1 = lua.safe_script("function f() return '3', 4 end", sol::script_pass_on_error); @@ -1438,58 +1434,3 @@ TEST_CASE("functions/lua style default arguments", "allow default arguments usin REQUIRE(10 == v2nd); REQUIRE(10 == v3nd); } - -#if !defined(_MSC_VER) || !(defined(_WIN32) && !defined(_WIN64)) - -TEST_CASE("functions/noexcept", "allow noexcept functions to be serialized properly into Lua using sol2") { - struct T { - static int noexcept_function() noexcept { - return 0x61; - } - - int noexcept_method() noexcept { - return 0x62; - } - } t; - - lua_CFunction ccall = sol::c_call; - - sol::state lua; - - lua.set_function("f", &T::noexcept_function); - lua.set_function("g", &T::noexcept_method); - lua.set_function("h", &T::noexcept_method, T()); - lua.set_function("i", &T::noexcept_method, std::ref(t)); - lua.set_function("j", &T::noexcept_method, &t); - lua.set_function("k", &T::noexcept_method, t); - lua.set_function("l", &raw_noexcept_function); - lua.set_function("m", ccall); - - lua["t"] = T(); - lua.safe_script("v1 = f()"); - lua.safe_script("v2 = g(t)"); - lua.safe_script("v3 = h()"); - lua.safe_script("v4 = i()"); - lua.safe_script("v5 = j()"); - lua.safe_script("v6 = k()"); - lua.safe_script("v7 = l()"); - lua.safe_script("v8 = m()"); - int v1 = lua["v1"]; - int v2 = lua["v2"]; - int v3 = lua["v3"]; - int v4 = lua["v4"]; - int v5 = lua["v5"]; - int v6 = lua["v6"]; - int v7 = lua["v7"]; - int v8 = lua["v8"]; - REQUIRE(v1 == 0x61); - REQUIRE(v2 == 0x62); - REQUIRE(v3 == 0x62); - REQUIRE(v4 == 0x62); - REQUIRE(v5 == 0x62); - REQUIRE(v6 == 0x62); - REQUIRE(v7 == 0x63); - REQUIRE(v8 == 0x63); -} - -#endif // Strange VC++ stuff diff --git a/tests/runtime_tests/source/functions.std.cpp b/tests/run_time/source/functions.std.cpp similarity index 100% rename from tests/runtime_tests/source/functions.std.cpp rename to tests/run_time/source/functions.std.cpp diff --git a/tests/runtime_tests/source/gc.cpp b/tests/run_time/source/gc.cpp similarity index 100% rename from tests/runtime_tests/source/gc.cpp rename to tests/run_time/source/gc.cpp diff --git a/tests/runtime_tests/source/lua_value.cpp b/tests/run_time/source/lua_value.cpp similarity index 100% rename from tests/runtime_tests/source/lua_value.cpp rename to tests/run_time/source/lua_value.cpp diff --git a/tests/run_time/source/main.cpp b/tests/run_time/source/main.cpp new file mode 100644 index 000000000..c1cd70f05 --- /dev/null +++ b/tests/run_time/source/main.cpp @@ -0,0 +1,30 @@ +// sol2 + +// The MIT License (MIT) + +// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#define CATCH_CONFIG_RUNNER +#include + +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/tests/runtime_tests/source/operators.cpp b/tests/run_time/source/operators.cpp similarity index 99% rename from tests/runtime_tests/source/operators.cpp rename to tests/run_time/source/operators.cpp index efa6a840d..7fac1bde1 100644 --- a/tests/runtime_tests/source/operators.cpp +++ b/tests/run_time/source/operators.cpp @@ -282,7 +282,7 @@ TEST_CASE("operators/default with pointers", "test that default operations still REQUIRE(ptr_test); REQUIRE(unique_test); -#if SOL_LUA_VERSION > 502 +#if SOL_LUA_VERSION_I_ > 502 lua.script("ptr_unique_test = t1 == t3"); bool ptr_unique_test = lua["ptr_unique_test"]; @@ -419,7 +419,7 @@ TEST_CASE("operators/member_stringable", "test member to_string stringability") } TEST_CASE("operators/container-like", "test that generic begin/end and iterator are automatically bound") { -#if SOL_LUA_VERSION > 501 +#if SOL_LUA_VERSION_I_ > 501 struct container { typedef int* iterator; typedef int value_type; diff --git a/tests/runtime_tests/source/overflow.cpp b/tests/run_time/source/overflow.cpp similarity index 100% rename from tests/runtime_tests/source/overflow.cpp rename to tests/run_time/source/overflow.cpp diff --git a/tests/runtime_tests/source/plain_types.cpp b/tests/run_time/source/plain_types.cpp similarity index 99% rename from tests/runtime_tests/source/plain_types.cpp rename to tests/run_time/source/plain_types.cpp index 5b6a23c09..5d0cf3d73 100644 --- a/tests/runtime_tests/source/plain_types.cpp +++ b/tests/run_time/source/plain_types.cpp @@ -88,7 +88,7 @@ TEST_CASE("plain/indestructible", "test that we error for types that are innatel lua["i"] = *i; lua.safe_script("i = nil"); auto result = lua.safe_script("collectgarbage() collectgarbage()", sol::script_pass_on_error); -#if SOL_LUA_VERSION > 503 +#if SOL_LUA_VERSION_I_ > 503 REQUIRE(result.valid()); #else REQUIRE_FALSE(result.valid()); diff --git a/tests/runtime_tests/source/policies.cpp b/tests/run_time/source/policies.cpp similarity index 100% rename from tests/runtime_tests/source/policies.cpp rename to tests/run_time/source/policies.cpp diff --git a/tests/runtime_tests/source/proxies.cpp b/tests/run_time/source/proxies.cpp similarity index 100% rename from tests/runtime_tests/source/proxies.cpp rename to tests/run_time/source/proxies.cpp diff --git a/tests/runtime_tests/source/sol_test.hpp b/tests/run_time/source/sol_test.hpp similarity index 100% rename from tests/runtime_tests/source/sol_test.hpp rename to tests/run_time/source/sol_test.hpp diff --git a/tests/runtime_tests/source/state.cpp b/tests/run_time/source/state.cpp similarity index 100% rename from tests/runtime_tests/source/state.cpp rename to tests/run_time/source/state.cpp diff --git a/tests/runtime_tests/source/storage.cpp b/tests/run_time/source/storage.cpp similarity index 100% rename from tests/runtime_tests/source/storage.cpp rename to tests/run_time/source/storage.cpp diff --git a/tests/runtime_tests/source/strings.cpp b/tests/run_time/source/strings.cpp similarity index 100% rename from tests/runtime_tests/source/strings.cpp rename to tests/run_time/source/strings.cpp diff --git a/tests/runtime_tests/source/tables.checks.cpp b/tests/run_time/source/tables.checks.cpp similarity index 100% rename from tests/runtime_tests/source/tables.checks.cpp rename to tests/run_time/source/tables.checks.cpp diff --git a/tests/runtime_tests/source/tables.clear.cpp b/tests/run_time/source/tables.clear.cpp similarity index 100% rename from tests/runtime_tests/source/tables.clear.cpp rename to tests/run_time/source/tables.clear.cpp diff --git a/tests/runtime_tests/source/tables.cpp b/tests/run_time/source/tables.cpp similarity index 100% rename from tests/runtime_tests/source/tables.cpp rename to tests/run_time/source/tables.cpp diff --git a/tests/runtime_tests/source/tables.enums.cpp b/tests/run_time/source/tables.enums.cpp similarity index 100% rename from tests/runtime_tests/source/tables.enums.cpp rename to tests/run_time/source/tables.enums.cpp diff --git a/tests/runtime_tests/source/tables.indexing.cpp b/tests/run_time/source/tables.indexing.cpp similarity index 100% rename from tests/runtime_tests/source/tables.indexing.cpp rename to tests/run_time/source/tables.indexing.cpp diff --git a/tests/runtime_tests/source/tables.insertion.cpp b/tests/run_time/source/tables.insertion.cpp similarity index 100% rename from tests/runtime_tests/source/tables.insertion.cpp rename to tests/run_time/source/tables.insertion.cpp diff --git a/tests/runtime_tests/source/tables.traversal.cpp b/tests/run_time/source/tables.traversal.cpp similarity index 100% rename from tests/runtime_tests/source/tables.traversal.cpp rename to tests/run_time/source/tables.traversal.cpp diff --git a/tests/runtime_tests/source/usertypes.auxiliary_keys.cpp b/tests/run_time/source/usertypes.auxiliary_keys.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.auxiliary_keys.cpp rename to tests/run_time/source/usertypes.auxiliary_keys.cpp diff --git a/tests/runtime_tests/source/usertypes.basic.cpp b/tests/run_time/source/usertypes.basic.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.basic.cpp rename to tests/run_time/source/usertypes.basic.cpp diff --git a/tests/runtime_tests/source/usertypes.constructors.cpp b/tests/run_time/source/usertypes.constructors.cpp similarity index 68% rename from tests/runtime_tests/source/usertypes.constructors.cpp rename to tests/run_time/source/usertypes.constructors.cpp index cd245c622..bdb03c3bf 100644 --- a/tests/runtime_tests/source/usertypes.constructors.cpp +++ b/tests/run_time/source/usertypes.constructors.cpp @@ -59,6 +59,85 @@ inline namespace sol2_test_usertypes_constructors { constexpr constructor_cheat(int val_) noexcept : val(val_) { } }; + + namespace Helpers { + class vector2 { + public: + vector2() : x(0), y(0) { + } + vector2(float x, float y) : x(x), y(y) { + } + vector2(const vector2& _vector2) : x(_vector2.x), y(_vector2.y) { + } + + float x, y; + + vector2& operator+=(const vector2& _vector2); + + vector2& operator-=(const vector2& _vector2); + + vector2& operator*=(const float scalar); + + vector2& operator*=(const vector2& _vector2); + + /*std::shared_ptr operator^=(const std::shared_ptr _vector2) + { + this->x *= _vector2->y; + this->y *= _vector2->x; + + return std::make_shared(*this); + }*/ + + friend float operator*(const vector2& _vector, const vector2& _vector2) { + return _vector.x * _vector2.x + _vector.y * _vector2.y; + } + + friend float operator^(const vector2& _vector, const vector2& _vector2) { + return _vector.x * _vector2.y + _vector2.x * _vector.y; + } + + vector2& operator=(const vector2& _vector2) noexcept; + }; + } // namespace Helpers + + namespace Helpers { + class vector3 { + public: + vector3() : x(0), y(0), z(0) { + } + vector3(float x, float y, float z) : x(x), y(y), z(z) { + } + vector3(const vector2& _vector2, float z) : x(_vector2.x), y(_vector2.y), z(z) { + } + float x, y, z; + + float GetX() { + return x; + } + + void SetX(float new_x) { + x = new_x; + } + + vector3& operator+=(const vector3& _vector2); + + vector3& operator-=(const vector3& _vector2); + + vector3& operator*=(const float scalar); + + vector3& operator*=(const vector3& _vector2); + + friend float operator*(const vector3& _vector, const vector3& _vector2) { + return _vector.x * _vector2.x + _vector.y * _vector2.y + _vector.z * _vector2.z; + } + + friend float operator^(const vector3& _vector, const vector3& _vector2) { + return _vector.x * _vector2.y + _vector2.x * _vector.y; + } + + vector3& operator=(const vector3& _vector2) noexcept; + }; + } // namespace Helpers } // namespace sol2_test_usertypes_constructors TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") { @@ -228,3 +307,31 @@ TEST_CASE("usertype/no_constructor linking time", "make sure if no constructor i sol::optional maybe_error = lua.safe_script("assert(heck.val == 1)", &sol::script_pass_on_error); REQUIRE_FALSE(maybe_error.has_value()); } + +TEST_CASE("usertypes/constructors_match", "Ensure that objects are properly constructed even in the case of multi-match, stack-cleaning constructors") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::table Lnamespace = lua["Helpers"].get_or_create(); + + Lnamespace.new_usertype("vector2", + sol::constructors(), + "x", + &Helpers::vector2::x, + "y", + &Helpers::vector2::y); + + Lnamespace.new_usertype("vector3", + sol::constructors(), + "x", + &Helpers::vector3::x, + "y", + &Helpers::vector3::y, + "z", + &Helpers::vector3::z); + + auto result = lua.safe_script(R"(local obj = Helpers.vector3.new(5,7,2) + assert(obj.x == 5) + )", + sol::script_pass_on_error); + REQUIRE(result.valid()); +} diff --git a/tests/runtime_tests/source/usertypes.cpp b/tests/run_time/source/usertypes.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.cpp rename to tests/run_time/source/usertypes.cpp diff --git a/tests/runtime_tests/source/usertypes.inheritance.cpp b/tests/run_time/source/usertypes.inheritance.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.inheritance.cpp rename to tests/run_time/source/usertypes.inheritance.cpp diff --git a/tests/runtime_tests/source/usertypes.inheritance.multi.cpp b/tests/run_time/source/usertypes.inheritance.multi.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.inheritance.multi.cpp rename to tests/run_time/source/usertypes.inheritance.multi.cpp diff --git a/tests/runtime_tests/source/usertypes.member_variables.cpp b/tests/run_time/source/usertypes.member_variables.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.member_variables.cpp rename to tests/run_time/source/usertypes.member_variables.cpp diff --git a/tests/runtime_tests/source/usertypes.overload.cpp b/tests/run_time/source/usertypes.overload.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.overload.cpp rename to tests/run_time/source/usertypes.overload.cpp diff --git a/tests/runtime_tests/source/usertypes.properties.cpp b/tests/run_time/source/usertypes.properties.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.properties.cpp rename to tests/run_time/source/usertypes.properties.cpp diff --git a/tests/runtime_tests/source/usertypes.runtime.cpp b/tests/run_time/source/usertypes.runtime.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.runtime.cpp rename to tests/run_time/source/usertypes.runtime.cpp diff --git a/tests/runtime_tests/source/usertypes.unique.cpp b/tests/run_time/source/usertypes.unique.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.unique.cpp rename to tests/run_time/source/usertypes.unique.cpp diff --git a/tests/runtime_tests/source/usertypes.unregister.cpp b/tests/run_time/source/usertypes.unregister.cpp similarity index 100% rename from tests/runtime_tests/source/usertypes.unregister.cpp rename to tests/run_time/source/usertypes.unregister.cpp diff --git a/tests/runtime_tests/source/utility.cpp b/tests/run_time/source/utility.cpp similarity index 100% rename from tests/runtime_tests/source/utility.cpp rename to tests/run_time/source/utility.cpp diff --git a/tests/runtime_tests/source/variadics.cpp b/tests/run_time/source/variadics.cpp similarity index 100% rename from tests/runtime_tests/source/variadics.cpp rename to tests/run_time/source/variadics.cpp diff --git a/tests/runtime_tests/CMakeLists.txt b/tests/runtime_tests/CMakeLists.txt deleted file mode 100644 index abb8bb371..000000000 --- a/tests/runtime_tests/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -# # # # sol2 -# The MIT License (MIT) -# -# Copyright (c) 2013-2021 Rapptz, ThePhD, and contributors -# -# Permission is hereby granted, free of charge, to any person obtaining a copy of -# this software and associated documentation files (the "Software"), to deal in -# the Software without restriction, including without limitation the rights to -# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -# the Software, and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -# # # # sol2 tests - runtime tests - -file(GLOB SOL2_RUNTIME_TEST_SOURCES - LIST_DIRECTORIES FALSE - CONFIGURE_DEPENDS - source/*.cpp) -source_group(test_sources FILES ${SOL2_RUNTIME_TEST_SOURCES}) - -function(CREATE_TEST test_target_name test_name target_sol) - set(test_target_name ${test_target_name}) - add_executable(${test_target_name} ${SOL2_RUNTIME_TEST_SOURCES}) - set_target_properties(${test_target_name} - PROPERTIES - OUTPUT_NAME ${test_name}) - target_link_libraries(${test_target_name} - PUBLIC Threads::Threads ${LUA_LIBRARIES} Catch2::Catch2 ${target_sol} ${CMAKE_DL_LIBS}) - target_compile_definitions(${test_target_name} - PUBLIC SOL_ALL_SAFETIES_ON=1 SOL_PRINT_ERRORS=1 SOL_ENABLE_INTEROP=1) - if (MSVC) - if (NOT CMAKE_COMPILER_ID MATCHES "Clang") - target_compile_options(${test_target_name} - PRIVATE /bigobj /W4 /w44800) - else() - target_compile_options(${test_target_name} - PRIVATE -ftemplate-backtrace-limit=0) - endif() - else() - target_compile_options(${test_target_name} - PRIVATE -std=c++1z -pthread - -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wpedantic -Werror -pedantic -pedantic-errors - -Wno-noexcept-type) - - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(${test_target_name} - PRIVATE -Wno-microsoft-cast) - endif() - - if (IS_X86) - if(MINGW) - set_target_properties(${test_target_name} - PROPERTIES - LINK_FLAGS -static-libstdc++) - endif() - endif() - endif() - if (MSVC) - target_compile_options(${test_target_name} - PRIVATE /EHsc /std:c++latest) - target_compile_definitions(${test_target_name} - PRIVATE UNICODE _UNICODE - _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE) - else() - target_compile_options(${test_target_name} - PRIVATE -std=c++1z -Wno-unknown-warning -Wno-unknown-warning-option - -Wall -Wextra -Wpedantic -pedantic -pedantic-errors) - endif() - - if (SOL2_CI) - target_compile_definitions(${test_target_name} - PRIVATE SOL2_CI) - endif() - - add_test(NAME ${test_name} COMMAND ${test_target_name}) - if(SOL2_ENABLE_INSTALL) - install(TARGETS ${test_target_name} RUNTIME DESTINATION bin) - endif() -endfunction(CREATE_TEST) - -if (SOL2_TESTS) - CREATE_TEST(runtime_tests "sol2.runtime_tests" sol2::sol2) -endif() -if (SOL2_TESTS_SINGLE) - CREATE_TEST(runtime_tests_single "sol2.single.runtime_tests" sol2::sol2::single) -endif() diff --git a/tests/runtime_tests/source/environments.cpp b/tests/runtime_tests/source/environments.cpp deleted file mode 100644 index 19dfc8d24..000000000 --- a/tests/runtime_tests/source/environments.cpp +++ /dev/null @@ -1,312 +0,0 @@ -// sol2 - -// The MIT License (MIT) - -// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_test.hpp" - -#include - -#include - -inline namespace sol2_test_environments { - struct check_g_env { - sol::state* plua; - sol::environment* penv_g; - - check_g_env(sol::state& lua, sol::environment& env_g) : plua(&lua), penv_g(&env_g) { - } - - void operator()(sol::function target) const { - sol::state& lua = *plua; - sol::environment& env_g = *penv_g; - sol::stack_guard luasg(lua); - sol::environment target_env = sol::get_environment(target); - int test_env_g = env_g["test"]; - int test_target_env = target_env["test"]; - REQUIRE(test_env_g == test_target_env); - REQUIRE(test_env_g == 5); - REQUIRE(env_g == target_env); - } - }; - - struct check_f_env { - sol::state* plua; - sol::environment* penv_f; - - check_f_env(sol::state& lua, sol::environment& env_f) : plua(&lua), penv_f(&env_f) { - } - - void operator()(sol::function target) const { - sol::state& lua = *plua; - sol::environment& env_f = *penv_f; - sol::stack_guard luasg(lua); - sol::environment target_env(sol::env_key, target); - int test_env_f = env_f["test"]; - int test_target_env = target_env["test"]; - REQUIRE(test_env_f == test_target_env); - REQUIRE(test_env_f == 31); - REQUIRE(env_f == target_env); - } - }; - - struct check_h_env { - sol::state* plua; - - check_h_env(sol::state& lua) : plua(&lua) { - } - - void operator()(sol::function target) const { - sol::state& lua = *plua; - sol::stack_guard luasg(lua); - sol::environment target_env = sol::get_environment(target); - // cannot strictly test - // if it's the global table, because different lua runtimes - // give different envs when there is no env - } - }; -} // namespace sol2_test_environments - -TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") { - sol::state lua; - sol::stack_guard luasg(lua); - - lua.open_libraries(sol::lib::base); - - auto result1 = lua.safe_script("f = function() return test end", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::function f = lua["f"]; - - sol::environment env_f(lua, sol::create); - env_f["test"] = 31; - sol::set_environment(env_f, f); - - int result = f(); - REQUIRE(result == 31); - - auto result2 = lua.safe_script("g = function() test = 5 end", sol::script_pass_on_error); - REQUIRE(result2.valid()); - sol::function g = lua["g"]; - sol::environment env_g(lua, sol::create); - env_g.set_on(g); - - g(); - - int test = env_g["test"]; - REQUIRE(test == 5); - - sol::object global_test = lua["test"]; - REQUIRE(!global_test.valid()); - - auto result3 = lua.safe_script("h = function() end", sol::script_pass_on_error); - REQUIRE(result3.valid()); - - lua.set_function("check_f_env", check_f_env(lua, env_f)); - lua.set_function("check_g_env", check_g_env(lua, env_g)); - lua.set_function("check_h_env", check_h_env(lua)); - - auto checkf = lua.safe_script("check_f_env(f)", sol::script_pass_on_error); - REQUIRE(checkf.valid()); - auto checkg = lua.safe_script("check_g_env(g)", sol::script_pass_on_error); - REQUIRE(checkg.valid()); - auto checkh = lua.safe_script("check_h_env(h)", sol::script_pass_on_error); - REQUIRE(checkh.valid()); -} - -TEST_CASE("environments/shadowing", "Environments can properly shadow and fallback on variables") { - - sol::state lua; - sol::stack_guard luasg(lua); - - lua["b"] = 2142; - - SECTION("no fallback") { - sol::environment plain_env(lua, sol::create); - auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::optional maybe_env_a = plain_env["a"]; - sol::optional maybe_global_a = lua["a"]; - sol::optional maybe_env_b = plain_env["b"]; - sol::optional maybe_global_b = lua["b"]; - - REQUIRE(maybe_env_a != sol::nullopt); - REQUIRE(maybe_env_a.value() == 24); - REQUIRE(maybe_env_b == sol::nullopt); - - REQUIRE(maybe_global_a == sol::nullopt); - REQUIRE(maybe_global_b != sol::nullopt); - REQUIRE(maybe_global_b.value() == 2142); - } - SECTION("fallback") { - sol::environment env_with_fallback(lua, sol::create, lua.globals()); - auto result1 = lua.safe_script("a = 56", env_with_fallback, sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::optional maybe_env_a = env_with_fallback["a"]; - sol::optional maybe_global_a = lua["a"]; - sol::optional maybe_env_b = env_with_fallback["b"]; - sol::optional maybe_global_b = lua["b"]; - - REQUIRE(maybe_env_a != sol::nullopt); - REQUIRE(maybe_env_a.value() == 56); - REQUIRE(maybe_env_b != sol::nullopt); - REQUIRE(maybe_env_b.value() == 2142); - - REQUIRE(maybe_global_a == sol::nullopt); - REQUIRE(maybe_global_b != sol::nullopt); - REQUIRE(maybe_global_b.value() == 2142); - } - SECTION("from name") { - sol::environment env_with_fallback(lua, sol::create, lua.globals()); - lua["env"] = env_with_fallback; - sol::environment env = lua["env"]; - auto result1 = lua.safe_script("a = 56", env, sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::optional maybe_env_a = env["a"]; - sol::optional maybe_global_a = lua["a"]; - sol::optional maybe_env_b = env["b"]; - sol::optional maybe_global_b = lua["b"]; - - REQUIRE(maybe_env_a != sol::nullopt); - REQUIRE(maybe_env_a.value() == 56); - REQUIRE(maybe_env_b != sol::nullopt); - REQUIRE(maybe_env_b.value() == 2142); - - REQUIRE(maybe_global_a == sol::nullopt); - REQUIRE(maybe_global_b != sol::nullopt); - REQUIRE(maybe_global_b.value() == 2142); - } - SECTION("name with newtable") { - lua["blank_env"] = sol::new_table(0, 1); - sol::environment plain_env = lua["blank_env"]; - auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); - REQUIRE(result1.valid()); - - sol::optional maybe_env_a = plain_env["a"]; - sol::optional maybe_global_a = lua["a"]; - sol::optional maybe_env_b = plain_env["b"]; - sol::optional maybe_global_b = lua["b"]; - - REQUIRE(maybe_env_a != sol::nullopt); - REQUIRE(maybe_env_a.value() == 24); - REQUIRE(maybe_env_b == sol::nullopt); - - REQUIRE(maybe_global_a == sol::nullopt); - REQUIRE(maybe_global_b != sol::nullopt); - REQUIRE(maybe_global_b.value() == 2142); - } -} - -TEST_CASE("environments/functions", "see if environments on functions are working properly") { - - SECTION("basic") { - sol::state lua; - sol::stack_guard luasg(lua); - - auto result1 = lua.safe_script("a = function() return 5 end", sol::script_pass_on_error); - REQUIRE(result1.valid()); - - sol::function a = lua["a"]; - - int result0 = a(); - REQUIRE(result0 == 5); - - sol::environment env(lua, sol::create); - sol::set_environment(env, a); - - int value = a(); - REQUIRE(value == 5); - } - SECTION("return environment value") { - sol::state lua; - sol::stack_guard luasg(lua); - - auto result1 = lua.safe_script("a = function() return test end", sol::script_pass_on_error); - REQUIRE(result1.valid()); - - sol::function a = lua["a"]; - sol::environment env(lua, sol::create); - env["test"] = 5; - env.set_on(a); - - // the function returns the value from the environment table - int result = a(); - REQUIRE(result == 5); - } - - SECTION("set environment value") { - sol::state lua; - sol::stack_guard luasg(lua); - - auto result1 = lua.safe_script("a = function() test = 5 end", sol::script_pass_on_error); - REQUIRE(result1.valid()); - - sol::function a = lua["a"]; - sol::environment env(lua, sol::create); - sol::set_environment(env, a); - - a(); - - // the value can be retrieved from the env table - int result = env["test"]; - REQUIRE(result == 5); - - // the global environment is not polluted - auto gtest = lua["test"]; - REQUIRE(!gtest.valid()); - } -} - -TEST_CASE("environments/this_environment", "test various situations of pulling out an environment") { - static std::string code = "return (f(10))"; - - sol::state lua; - sol::stack_guard luasg(lua); - - lua["f"] = [](sol::this_environment te, int x, sol::this_state ts) { - if (te) { - sol::environment& env = te; - return x + static_cast(env["x"]); - } - sol::state_view lua = ts; - return x + static_cast(lua["x"]); - }; - - sol::environment e(lua, sol::create, lua.globals()); - lua["x"] = 5; - e["x"] = 20; - SECTION("from Lua script") { - auto result1 = lua.safe_script(code, e, sol::script_pass_on_error); - REQUIRE(result1.valid()); - int value = result1; - REQUIRE(value == 30); - } - SECTION("from C++") { - sol::function f = lua["f"]; - e.set_on(f); - int value = f(10); - REQUIRE(value == 30); - } - SECTION("from C++, with no env") { - sol::function f = lua["f"]; - int value = f(10); - REQUIRE(value == 15); - } -} diff --git a/tests/runtime_tests/source/main.cpp b/tests/runtime_tests/source/main.cpp deleted file mode 100644 index ecfa2606a..000000000 --- a/tests/runtime_tests/source/main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#define CATCH_CONFIG_RUNNER -#include - -int main(int argc, char* argv[]) { - int result = Catch::Session().run(argc, argv); - return result; -}