diff --git a/README.md b/README.md index df9fcb8..c83db54 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more inform This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. # Usage of Third Party Libraries -This project makes use of the [Catch](https://github.com/philsquared/catch) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Catch. +This project makes use of the [Google Test](https://github.com/google/gooletest) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Google Test. # Quick Start ## Supported Platforms diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index ebf7b6e..552b254 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -2,38 +2,40 @@ THIRD-PARTY SOFTWARE NOTICES AND INFORMATION Do Not Translate or Localize -GSL: Guidelines Support Library incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. +GSL: Guidelines Support Library incorporates third party material from the projects listed below. +------------------------------------------------------------------------------- +Software: Google Test +Owner: Google Inc. +Source URL: github.com/google/googletest +License: BSD 3 - Clause +Text: + Copyright 2008, Google Inc. + All rights reserved. -1. Catch (https://github.com/philsquared/Catch) - - -%% Catch NOTICES, INFORMATION, AND LICENSE BEGIN HERE -========================================= -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -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, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -========================================= -END OF Catch NOTICES, INFORMATION, AND LICENSE + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------------- diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index c704633..7a9e8ad 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -18,7 +18,6 @@ #define GSL_CONTRACTS_H #include -#include // for logic_error // // make suppress attributes parse for some compilers @@ -50,19 +49,6 @@ #endif -// -// There are three configuration options for this GSL implementation's behavior -// when pre/post conditions on the GSL types are violated: -// -// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default) -// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown -// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens -// -#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \ - defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)) -#define GSL_TERMINATE_ON_CONTRACT_VIOLATION -#endif - #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) @@ -94,10 +80,6 @@ namespace gsl { -struct fail_fast : public std::logic_error -{ - explicit fail_fast(char const* const message) : std::logic_error(message) {} -}; namespace details { @@ -128,45 +110,21 @@ namespace details #endif } -#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) - template + [[deprecated("GSL no longer supports throwing for contract violations. Use gsl::details::terminate() instead.")]] [[noreturn]] void throw_exception(Exception&&) noexcept { gsl::details::terminate(); } -#else - - template - [[noreturn]] void throw_exception(Exception&& exception) - { - throw std::forward(exception); - } - -#endif // GSL_TERMINATE_ON_CONTRACT_VIOLATION } // namespace details } // namespace gsl -#if defined(GSL_THROW_ON_CONTRACT_VIOLATION) - -#define GSL_CONTRACT_CHECK(type, cond) \ - (GSL_LIKELY(cond) ? static_cast(0) \ - : gsl::details::throw_exception(gsl::fail_fast( \ - "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)))) - -#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) #define GSL_CONTRACT_CHECK(type, cond) \ (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate()) -#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) - -#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond) - -#endif // GSL_THROW_ON_CONTRACT_VIOLATION - #define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) #define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util index e4b2daa..d1f7f33 100644 --- a/include/gsl/gsl_util +++ b/include/gsl/gsl_util @@ -21,7 +21,6 @@ #include #include // for ptrdiff_t, size_t -#include // for exception #include // for initializer_list #include // for is_signed, integral_constant #include // for exchange, forward @@ -97,10 +96,6 @@ constexpr T narrow_cast(U&& u) noexcept return static_cast(std::forward(u)); } -struct narrowing_error : public std::exception -{ -}; - namespace details { template @@ -120,9 +115,9 @@ constexpr T narrow(U u) noexcept(false) { T t = narrow_cast(u); - if (static_cast(t) != u) gsl::details::throw_exception(narrowing_error()); + if (static_cast(t) != u) gsl::details::terminate(); if (!details::is_same_signedness::value && ((t < T{}) != (u < U{}))) - gsl::details::throw_exception(narrowing_error()); + gsl::details::terminate(); return t; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 832513f..5c93a9a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,27 +5,33 @@ project(GSLTests CXX) # will make visual studio generated project group files set_property(GLOBAL PROPERTY USE_FOLDERS ON) -list(APPEND CATCH_CMAKE_ARGS - "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/external" - "-DNO_SELFTEST=true" +configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) +execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) - -if(GIT_FOUND) - # add catch - ExternalProject_Add( - catch - PREFIX ${CMAKE_BINARY_DIR}/catch - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v2.0.1 - CMAKE_ARGS ${CATCH_CMAKE_ARGS} - LOG_DOWNLOAD 1 - UPDATE_DISCONNECTED 1 - ) -else() - # assume catch is installed in a system directory - add_custom_target(catch) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") endif() +execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download +) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() + +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +add_subdirectory( + ${CMAKE_CURRENT_BINARY_DIR}/googletest-src + ${CMAKE_CURRENT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL +) + if (MSVC AND (GSL_CXX_STANDARD EQUAL 17)) set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-) endif() @@ -78,37 +84,23 @@ else() ) endif(MSVC) -# for tests to find the catch header -target_include_directories(gsl_tests_config INTERFACE - ${CMAKE_BINARY_DIR}/external/include +# for tests to find the gtest header +target_include_directories(gsl_tests_config SYSTEM INTERFACE + googletest/googletest/include ) -# set definitions for tests -target_compile_definitions(gsl_tests_config INTERFACE - GSL_THROW_ON_CONTRACT_VIOLATION -) - -# create the main executable for each test. this reduces the compile time -# of each test by pre-compiling catch. -add_library(test_catch STATIC test.cpp) -target_link_libraries(test_catch - GSL - gsl_tests_config -) -add_dependencies(test_catch catch) -set_property(TARGET test_catch PROPERTY FOLDER "GSL_tests") +set_property(TARGET PROPERTY FOLDER "GSL_tests") function(add_gsl_test name) add_executable(${name} ${name}.cpp) target_link_libraries(${name} GSL - test_catch gsl_tests_config + gtest_main ) - add_dependencies(${name} catch) add_test( - ${name} - ${name} + ${name} + ${name} ) # group all tests under GSL_tests set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests") @@ -141,11 +133,9 @@ endforeach(flag_var) # please try to keep entries ordered =) add_library(gsl_tests_config_noexcept INTERFACE) if(MSVC) # MSVC or simulating MSVC - target_compile_definitions(gsl_tests_config_noexcept INTERFACE - _HAS_EXCEPTIONS=0 - ) target_compile_options(gsl_tests_config_noexcept INTERFACE ${GSL_CPLUSPLUS_OPT} + /EHsc /W4 /WX $<$: @@ -184,16 +174,12 @@ else() ) endif(MSVC) -# set definitions for tests -target_compile_definitions(gsl_tests_config_noexcept INTERFACE - GSL_TERMINATE_ON_CONTRACT_VIOLATION -) - function(add_gsl_test_noexcept name) add_executable(${name} ${name}.cpp) target_link_libraries(${name} GSL gsl_tests_config_noexcept + gtest_main ) add_test( ${name} diff --git a/tests/CMakeLists.txt.in b/tests/CMakeLists.txt.in new file mode 100644 index 0000000..50c041d --- /dev/null +++ b/tests/CMakeLists.txt.in @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.0.2) +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG master + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/tests/algorithm_tests.cpp b/tests/algorithm_tests.cpp index 368b53d..c88a120 100644 --- a/tests/algorithm_tests.cpp +++ b/tests/algorithm_tests.cpp @@ -20,24 +20,38 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK, CHE... +#if __clang__ || __GNUC__ +// disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for copy #include // for span - #include // for array #include // for size_t -namespace gsl { +namespace +{ + static constexpr char deathstring[] = "Expected Death"; +} + +namespace gsl +{ struct fail_fast; -} // namespace gsl +} // namespace gsl using namespace std; using namespace gsl; -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("same_type") +TEST(algorithm_tests, same_type) { // dynamic source and destination span { @@ -50,9 +64,10 @@ TEST_CASE("same_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } @@ -67,9 +82,10 @@ TEST_CASE("same_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } @@ -84,9 +100,10 @@ TEST_CASE("same_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } @@ -101,17 +118,15 @@ TEST_CASE("same_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } } - -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("compatible_type") +TEST(algorithm_tests, compatible_type) { // dynamic source and destination span { @@ -124,9 +139,10 @@ TEST_CASE("compatible_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } @@ -141,9 +157,10 @@ TEST_CASE("compatible_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } @@ -158,9 +175,10 @@ TEST_CASE("compatible_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } @@ -175,15 +193,16 @@ TEST_CASE("compatible_type") copy(src_span, dst_span); copy(src_span, dst_span.subspan(src_span.size())); - for (std::size_t i = 0; i < src.size(); ++i) { - CHECK(dst[i] == src[i]); - CHECK(dst[i + src.size()] == src[i]); + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); } } } #ifdef CONFIRM_COMPILATION_ERRORS -TEST_CASE("incompatible_type") +TEST(algorithm_tests, incompatible_type) { std::array src{1, 2, 3, 4}; std::array dst{}; @@ -201,8 +220,13 @@ TEST_CASE("incompatible_type") } #endif -TEST_CASE("small_destination_span") +TEST(algorithm_tests, small_destination_span) { + std::set_terminate([] { + std::cerr << "Expected Death. small_destination_span"; + std::abort(); + }); + std::array src{1, 2, 3, 4}; std::array dst{}; @@ -211,11 +235,15 @@ TEST_CASE("small_destination_span") const span dst_span_dyn(dst); const span dst_span_static(dst); - CHECK_THROWS_AS(copy(src_span_dyn, dst_span_dyn), fail_fast); - CHECK_THROWS_AS(copy(src_span_dyn, dst_span_static), fail_fast); - CHECK_THROWS_AS(copy(src_span_static, dst_span_dyn), fail_fast); + EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), deathstring); + EXPECT_DEATH(copy(src_span_dyn, dst_span_static), deathstring); + EXPECT_DEATH(copy(src_span_static, dst_span_dyn), deathstring); #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); #endif } + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp index 0c509ad..a42c209 100644 --- a/tests/assertion_tests.cpp +++ b/tests/assertion_tests.cpp @@ -20,33 +20,64 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK, CHECK... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for fail_fast (ptr only), Ensures, Expects using namespace gsl; +namespace +{ +static constexpr char deathstring[] = "Expected Death"; + int f(int i) { Expects(i > 0 && i < 10); return i; } -TEST_CASE("expects") -{ - CHECK(f(2) == 2); - CHECK_THROWS_AS(f(10), fail_fast); -} - int g(int i) { i++; Ensures(i > 0 && i < 10); return i; } +} // namespace -TEST_CASE("ensures") +TEST(assertion_tests, expects) { - CHECK(g(2) == 3); - CHECK_THROWS_AS(g(9), fail_fast); + std::set_terminate([] { + std::cerr << "Expected Death. expects"; + std::abort(); + }); + + EXPECT_TRUE(f(2) == 2); + EXPECT_DEATH(f(10), deathstring); } + + +TEST(assertion_tests, ensures) +{ + std::set_terminate([] { + std::cerr << "Expected Death. ensures"; + std::abort(); + }); + + EXPECT_TRUE(g(2) == 3); + EXPECT_DEATH(g(9), deathstring); +} + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 7f07be0..b43d06c 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -20,7 +20,19 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK_THROW... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for at @@ -29,88 +41,95 @@ #include // for initializer_list #include // for vector +namespace +{ + static constexpr char deathstring[] = "Expected Death"; +} -namespace gsl { -struct fail_fast; -} // namespace gsl - -using gsl::fail_fast; - -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("static_array") +TEST(at_tests, static_array) { int a[4] = {1, 2, 3, 4}; const int(&c_a)[4] = a; for (int i = 0; i < 4; ++i) { - CHECK(&gsl::at(a, i) == &a[i]); - CHECK(&gsl::at(c_a, i) == &a[i]); + EXPECT_TRUE(&gsl::at(a, i) == &a[i]); + EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]); } - CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); - CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); + std::set_terminate([] { + std::cerr << "Expected Death. static_array"; + std::abort(); + }); + + EXPECT_DEATH(gsl::at(a, -1), deathstring); + EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at(c_a, -1), deathstring); + EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("std_array") +TEST(at_tests, std_array) { std::array a = {1, 2, 3, 4}; const std::array& c_a = a; for (int i = 0; i < 4; ++i) { - CHECK(&gsl::at(a, i) == &a[static_cast(i)]); - CHECK(&gsl::at(c_a, i) == &a[static_cast(i)]); + EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); + EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } - CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); - CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); + std::set_terminate([] { + std::cerr << "Expected Death. std_array"; + std::abort(); + }); + + EXPECT_DEATH(gsl::at(a, -1), deathstring); + EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at(c_a, -1), deathstring); + EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("StdVector") +TEST(at_tests, std_vector) { std::vector a = {1, 2, 3, 4}; const std::vector& c_a = a; for (int i = 0; i < 4; ++i) { - CHECK(&gsl::at(a, i) == &a[static_cast(i)]); - CHECK(&gsl::at(c_a, i) == &a[static_cast(i)]); + EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); + EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); } - CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); - CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); + std::set_terminate([] { + std::cerr << "Expected Death. std_vector"; + std::abort(); + }); + + EXPECT_DEATH(gsl::at(a, -1), deathstring); + EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at(c_a, -1), deathstring); + EXPECT_DEATH(gsl::at(c_a, 4), deathstring); } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("InitializerList") +TEST(at_tests, InitializerList) { const std::initializer_list a = {1, 2, 3, 4}; for (int i = 0; i < 4; ++i) { - CHECK(gsl::at(a, i) == i + 1); - CHECK(gsl::at({1, 2, 3, 4}, i) == i + 1); + EXPECT_TRUE(gsl::at(a, i) == i + 1); + EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1); } - CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); - CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); - CHECK_THROWS_AS(gsl::at({1, 2, 3, 4}, -1), fail_fast); - CHECK_THROWS_AS(gsl::at({1, 2, 3, 4}, 4), fail_fast); + std::set_terminate([] { + std::cerr << "Expected Death. InitializerList"; + std::abort(); + }); + + EXPECT_DEATH(gsl::at(a, -1), deathstring); + EXPECT_DEATH(gsl::at(a, 4), deathstring); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), deathstring); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), deathstring); } #if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910 -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute static constexpr bool test_constexpr() { int a1[4] = {1, 2, 3, 4}; @@ -133,3 +152,6 @@ static constexpr bool test_constexpr() static_assert(test_constexpr(), "FAIL"); #endif +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp index d72e31a..629e5d1 100644 --- a/tests/bounds_tests.cpp +++ b/tests/bounds_tests.cpp @@ -24,18 +24,23 @@ #if __clang__ || __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -#include // for AssertionHandler, StringRef, TEST_CASE +//disable warnings from gtest +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for static_bounds, static_bounds_dynamic_range_t #include // for ptrdiff_t, size_t -namespace gsl { -struct fail_fast; -} // namespace gsl - using namespace std; using namespace gsl; @@ -44,8 +49,7 @@ namespace void use(std::ptrdiff_t&) {} } -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute -TEST_CASE("basic_bounds") +TEST(bounds_tests, basic_bounds) { for (auto point : static_bounds{2}) { for (decltype(point)::size_type j = 0; @@ -57,9 +61,7 @@ TEST_CASE("basic_bounds") } } -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("bounds_basic") +TEST(bounds_tests, bounds_basic) { static_bounds<3, 4, 5> b; const auto a = b.slice(); @@ -68,9 +70,7 @@ TEST_CASE("bounds_basic") x.slice().slice(); } -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("arrayview_iterator") +TEST(bounds_tests, arrayview_iterator) { static_bounds<4, dynamic_range, 2> bounds{3}; @@ -88,8 +88,7 @@ TEST_CASE("arrayview_iterator") #endif } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("bounds_convertible") +TEST(bounds_tests, bounds_convertible) { static_bounds<7, 4, 2> b1; static_bounds<7, dynamic_range, 2> b2 = b1; @@ -102,18 +101,21 @@ TEST_CASE("bounds_convertible") static_bounds<7, 4, 2> b4 = b3; (void) b4; - static_bounds b11; - static_bounds b5; static_bounds<34> b6; + std::set_terminate([] { + std::cerr << "Expected Death. bounds_convertible"; + std::abort(); + }); + b5 = static_bounds<20>(); - CHECK_THROWS_AS(b6 = b5, fail_fast); + EXPECT_DEATH(b6 = b5, ".*"); b5 = static_bounds<34>(); b6 = b5; - CHECK(b5 == b6); - CHECK(b5.size() == b6.size()); + EXPECT_TRUE(b5 == b6); + EXPECT_TRUE(b5.size() == b6.size()); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -122,4 +124,4 @@ copy(src_span_static, dst_span_static); #if __clang__ || __GNUC__ #pragma GCC diagnostic pop -#endif +#endif // __clang__ || __GNUC__ diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp index d6634bb..bf22556 100644 --- a/tests/byte_tests.cpp +++ b/tests/byte_tests.cpp @@ -17,10 +17,22 @@ #ifdef _MSC_VER // blanket turn off warnings from CppCoreCheck from catch // so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#endif +#pragma warning(disable : 26440 26426) +#endif // _MSC_VER -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for to_byte, to_integer, byte, operator&, ope... @@ -29,104 +41,103 @@ using namespace gsl; namespace { -TEST_CASE("construction") -{ - { - const byte b = static_cast(4); - CHECK(static_cast(b) == 4); - } - - GSL_SUPPRESS(es.49) - { - const byte b = byte(12); - CHECK(static_cast(b) == 12); - } - - { - const byte b = to_byte<12>(); - CHECK(static_cast(b) == 12); - } - { - const unsigned char uc = 12; - const byte b = to_byte(uc); - CHECK(static_cast(b) == 12); - } - -#if defined(__cplusplus) && (__cplusplus >= 201703L) - { - const byte b { 14 }; - CHECK(static_cast(b) == 14); - } -#endif -} - -TEST_CASE("bitwise_operations") -{ - const byte b = to_byte<0xFF>(); - - byte a = to_byte<0x00>(); - CHECK((b | a) == to_byte<0xFF>()); - CHECK(a == to_byte<0x00>()); - - a |= b; - CHECK(a == to_byte<0xFF>()); - - a = to_byte<0x01>(); - CHECK((b & a) == to_byte<0x01>()); - - a &= b; - CHECK(a == to_byte<0x01>()); - - CHECK((b ^ a) == to_byte<0xFE>()); - - CHECK(a == to_byte<0x01>()); - a ^= b; - CHECK(a == to_byte<0xFE>()); - - a = to_byte<0x01>(); - CHECK(~a == to_byte<0xFE>()); - - a = to_byte<0xFF>(); - CHECK((a << 4) == to_byte<0xF0>()); - CHECK((a >> 4) == to_byte<0x0F>()); - - a <<= 4; - CHECK(a == to_byte<0xF0>()); - a >>= 4; - CHECK(a == to_byte<0x0F>()); -} - -TEST_CASE("to_integer") -{ - const byte b = to_byte<0x12>(); - - CHECK(0x12 == gsl::to_integer(b)); - CHECK(0x12 == gsl::to_integer(b)); - CHECK(0x12 == gsl::to_integer(b)); - CHECK(0x12 == gsl::to_integer(b)); - - CHECK(0x12 == gsl::to_integer(b)); - CHECK(0x12 == gsl::to_integer(b)); - CHECK(0x12 == gsl::to_integer(b)); - CHECK(0x12 == gsl::to_integer(b)); - - // CHECK(0x12 == gsl::to_integer(b)); // expect compile-time error - // CHECK(0x12 == gsl::to_integer(b)); // expect compile-time error -} - -int modify_both(gsl::byte & b, int& i) +int modify_both(gsl::byte& b, int& i) { i = 10; b = to_byte<5>(); return i; } -GSL_SUPPRESS(type.1) -TEST_CASE("aliasing") +TEST(byte_tests, construction) +{ + { + const byte b = static_cast(4); + EXPECT_TRUE(static_cast(b) == 4); + } + + GSL_SUPPRESS(es.49) + { + const byte b = byte(12); + EXPECT_TRUE(static_cast(b) == 12); + } + + { + const byte b = to_byte<12>(); + EXPECT_TRUE(static_cast(b) == 12); + } + { + const unsigned char uc = 12; + const byte b = to_byte(uc); + EXPECT_TRUE(static_cast(b) == 12); + } + +#if defined(__cplusplus) && (__cplusplus >= 201703L) + { + const byte b { 14 }; + EXPECT_TRUE(static_cast(b) == 14); + } +#endif +} + +TEST(byte_tests, bitwise_operations) +{ + const byte b = to_byte<0xFF>(); + + byte a = to_byte<0x00>(); + EXPECT_TRUE((b | a) == to_byte<0xFF>()); + EXPECT_TRUE(a == to_byte<0x00>()); + + a |= b; + EXPECT_TRUE(a == to_byte<0xFF>()); + + a = to_byte<0x01>(); + EXPECT_TRUE((b & a) == to_byte<0x01>()); + + a &= b; + EXPECT_TRUE(a == to_byte<0x01>()); + + EXPECT_TRUE((b ^ a) == to_byte<0xFE>()); + + EXPECT_TRUE(a == to_byte<0x01>()); + a ^= b; + EXPECT_TRUE(a == to_byte<0xFE>()); + + a = to_byte<0x01>(); + EXPECT_TRUE(~a == to_byte<0xFE>()); + + a = to_byte<0xFF>(); + EXPECT_TRUE((a << 4) == to_byte<0xF0>()); + EXPECT_TRUE((a >> 4) == to_byte<0x0F>()); + + a <<= 4; + EXPECT_TRUE(a == to_byte<0xF0>()); + a >>= 4; + EXPECT_TRUE(a == to_byte<0x0F>()); +} + +TEST(byte_tests, to_integer) +{ + const byte b = to_byte<0x12>(); + + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + + // EXPECT_TRUE(0x12 == gsl::to_integer(b)); // expect compile-time error + // EXPECT_TRUE(0x12 == gsl::to_integer(b)); // expect compile-time error +} + +TEST(byte_tests, aliasing) { int i{0}; const int res = modify_both(reinterpret_cast(i), i); - CHECK(res == i); + EXPECT_TRUE(res == i); } } @@ -134,3 +145,7 @@ TEST_CASE("aliasing") #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); #endif + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/multi_span_tests.cpp b/tests/multi_span_tests.cpp index 0aa0ff9..891bee3 100644 --- a/tests/multi_span_tests.cpp +++ b/tests/multi_span_tests.cpp @@ -17,17 +17,26 @@ #ifdef _MSC_VER // blanket turn off warnings from CppCoreCheck from catch // so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426) // from catch -#pragma warning(disable : 4996) // multi_span is in the process of being deprecated. +#pragma warning(disable : 26440 26426) // from catch +#pragma warning(disable : 4996) // multi_span is in the process of being deprecated. // Suppressing warnings until it is completely removed #endif #if __clang__ || __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -#include // for AssertionHandler, StringRef, CHECK, CHECK... +//disable warnings from gtest +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for byte #include // for narrow_cast @@ -52,155 +61,254 @@ using namespace gsl; namespace { +static constexpr char deathstring[] = "Expected Death"; struct BaseClass { }; struct DerivedClass : BaseClass { }; + +void overloaded_func(multi_span exp, int expected_value) +{ + for (auto val : exp) { EXPECT_TRUE(val == expected_value); } +} + +void overloaded_func(multi_span exp, char expected_value) +{ + for (auto val : exp) { EXPECT_TRUE(val == expected_value); } +} + +void iterate_second_column(multi_span av) +{ + auto length = av.size() / 2; + + // view to the second column + auto section = av.section({0, 1}, {length, 1}); + + EXPECT_TRUE(section.size() == length); + for (auto i = 0; i < section.size(); ++i) { EXPECT_TRUE(section[i][0] == av[i][1]); } + + for (auto i = 0; i < section.size(); ++i) + { + auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro + EXPECT_TRUE(section[idx] == av[i][1]); + } + + EXPECT_TRUE(section.bounds().index_bounds()[0] == length); + EXPECT_TRUE(section.bounds().index_bounds()[1] == 1); + for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) + { + for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) + { + auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro + EXPECT_TRUE(section[idx] == av[i][1]); + } + } + + auto check_sum = 0; + for (auto i = 0; i < length; ++i) { check_sum += av[i][1]; } + + { + auto idx = 0; + auto sum = 0; + for (auto num : section) + { + EXPECT_TRUE(num == av[idx][1]); + sum += num; + idx++; + } + + EXPECT_TRUE(sum == check_sum); + } + { + auto idx = length - 1; + auto sum = 0; + for (auto iter = section.rbegin(); iter != section.rend(); ++iter) + { + EXPECT_TRUE(*iter == av[idx][1]); + sum += *iter; + idx--; + } + + EXPECT_TRUE(sum == check_sum); + } +} +template +void fn(const Bounds&) +{ + static_assert(Bounds::static_size == 60, "static bounds is wrong size"); +} + } // namespace -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("default_constructor") +TEST(multi_span_test, default_constructor) { { multi_span s; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { multi_span s; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s; - CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == nullptr); // explains why it can't compile #endif } { multi_span s{}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs{}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_nullptr_constructor") +TEST(multi_span_test, from_nullptr_constructor) { { multi_span s = nullptr; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs = nullptr; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { multi_span s = nullptr; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs = nullptr; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s = nullptr; - CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == nullptr); // explains why it can't compile #endif } { multi_span s{nullptr}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs{nullptr}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { multi_span s{nullptr}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs{nullptr}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_nullptr_length_constructor") { +TEST(multi_span_test, from_nullptr_length_constructor) { { multi_span s{nullptr, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs{nullptr, 0}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { multi_span s{nullptr, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs{nullptr, 0}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } + std::set_terminate([] { + std::cerr << "Expected Death. from_nullptr_length_constructor"; + std::abort(); + }); + { auto workaround_macro = []() { const multi_span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); auto const_workaround_macro = []() { const multi_span cs{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + EXPECT_DEATH(const_workaround_macro(), deathstring); } { auto workaround_macro = []() { const multi_span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); auto const_workaround_macro = []() { const multi_span s{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + EXPECT_DEATH(const_workaround_macro(), deathstring); } { multi_span s{nullptr, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); multi_span cs{nullptr, 0}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.length() == 0); + EXPECT_TRUE(cs.data() == nullptr); } { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s{nullptr, 0}; - CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == nullptr); // explains why it can't compile #endif } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_element_constructor") +TEST(multi_span_test, from_element_constructor) { int i = 5; { multi_span s = i; - CHECK((s.length() == 1 && s.data() == &i)); - CHECK(s[0] == 5); + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == &i); + EXPECT_TRUE(s[0] == 5); multi_span cs = i; - CHECK((cs.length() == 1 && cs.data() == &i)); - CHECK(cs[0] == 5); + EXPECT_TRUE(cs.length() == 1); + EXPECT_TRUE(cs.data() == &i); + EXPECT_TRUE(cs[0] == 5); } { @@ -213,20 +321,23 @@ TEST_CASE("from_element_constructor") { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s = i; - CHECK((s.length() == 0 && s.data() == &i)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &i); #endif } { multi_span s = i; - CHECK((s.length() == 1 && s.data() == &i)); - CHECK(s[0] == 5); + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == &i); + EXPECT_TRUE(s[0] == 5); } { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s = i; - CHECK((s.length() == 2 && s.data() == &i)); + EXPECT_TRUE(s.length() == 2); + EXPECT_TRUE(s.data() == &i); #endif } @@ -239,101 +350,121 @@ TEST_CASE("from_element_constructor") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_pointer_length_constructor") +TEST(multi_span_test, from_pointer_length_constructor) { int arr[4] = {1, 2, 3, 4}; { multi_span s{&arr[0], 2}; - CHECK((s.length() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.length() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { multi_span s{&arr[0], 2}; - CHECK((s.length() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.length() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { int* p = nullptr; multi_span s{p, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == nullptr); } + std::set_terminate([] { + std::cerr << "Expected Death. from_pointer_length_constructor"; + std::abort(); + }); + { int* p = nullptr; auto workaround_macro = [=]() { const multi_span s{p, 2}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_pointer_pointer_constructor") +TEST(multi_span_test, from_pointer_pointer_constructor) { int arr[4] = {1, 2, 3, 4}; { multi_span s{&arr[0], &arr[2]}; - CHECK((s.length() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.length() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { multi_span s{&arr[0], &arr[2]}; - CHECK((s.length() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.length() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { multi_span s{&arr[0], &arr[0]}; - CHECK((s.length() == 0 && s.data() == &arr[0])); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &arr[0]); } { multi_span s{&arr[0], &arr[0]}; - CHECK((s.length() == 0 && s.data() == &arr[0])); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &arr[0]); } + + std::set_terminate([] { + std::cerr << "Expected Death. from_pointer_pointer_constructor"; + std::abort(); + }); + { auto workaround_macro = [&]() { const multi_span s{&arr[1], &arr[0]}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { int* p = nullptr; auto workaround_macro = [&]() { const multi_span s{&arr[0], p}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { int* p = nullptr; auto workaround_macro = [&]() { const multi_span s{p, p}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { int* p = nullptr; auto workaround_macro = [&]() { const multi_span s{&arr[0], p}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -TEST_CASE("from_array_constructor") +TEST(multi_span_test, from_array_constructor) { int arr[5] = {1, 2, 3, 4, 5}; { multi_span s{arr}; - CHECK((s.length() == 5 && s.data() == &arr[0])); + EXPECT_TRUE(s.length() == 5); + EXPECT_TRUE(s.data() == &arr[0]); } { multi_span s{arr}; - CHECK((s.length() == 5 && s.data() == &arr[0])); + EXPECT_TRUE(s.length() == 5); + EXPECT_TRUE(s.data() == &arr[0]); } { @@ -344,20 +475,24 @@ TEST_CASE("from_array_constructor") { multi_span s{arr}; - CHECK((s.length() == 0 && s.data() == &arr[0])); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &arr[0]); } int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; { multi_span s{arr2d}; - CHECK((s.length() == 6 && s.data() == &arr2d[0][0])); - CHECK((s[0] == 1 && s[5] == 6)); + EXPECT_TRUE(s.length() == 6); + EXPECT_TRUE(s.data() == &arr2d[0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); } { multi_span s{arr2d}; - CHECK((s.length() == 0 && s.data() == &arr2d[0][0])); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &arr2d[0][0]); } { @@ -368,8 +503,10 @@ TEST_CASE("from_array_constructor") { multi_span s{arr2d}; - CHECK((s.length() == 6 && s.data() == &arr2d[0][0])); - CHECK((s[0] == 1 && s[5] == 6)); + EXPECT_TRUE(s.length() == 6); + EXPECT_TRUE(s.data() == &arr2d[0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); } { @@ -380,14 +517,16 @@ TEST_CASE("from_array_constructor") { multi_span s{arr2d[0]}; - CHECK((s.length() == 1 && s.data() == &arr2d[0])); + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == &arr2d[0]); } { multi_span s{arr2d}; - CHECK((s.length() == 6 && s.data() == &arr2d[0][0])); + EXPECT_TRUE(s.length() == 6); + EXPECT_TRUE(s.data() == &arr2d[0][0]); auto workaround_macro = [&]() { return s[{1, 2}] == 6; }; - CHECK(workaround_macro()); + EXPECT_TRUE(workaround_macro()); } { @@ -400,13 +539,16 @@ TEST_CASE("from_array_constructor") { multi_span s{arr3d}; - CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0])); - CHECK((s[0] == 1 && s[11] == 12)); + EXPECT_TRUE(s.length() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[11] == 12); } { multi_span s{arr3d}; - CHECK((s.length() == 0 && s.data() == &arr3d[0][0][0])); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); } { @@ -417,8 +559,10 @@ TEST_CASE("from_array_constructor") { multi_span s{arr3d}; - CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0])); - CHECK((s[0] == 1 && s[5] == 6)); + EXPECT_TRUE(s.length() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); } { @@ -429,14 +573,16 @@ TEST_CASE("from_array_constructor") { multi_span s{arr3d[0]}; - CHECK((s.length() == 1 && s.data() == &arr3d[0])); + EXPECT_TRUE(s.length() == 1); + EXPECT_TRUE(s.data() == &arr3d[0]); } { multi_span s{arr3d}; - CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0])); + EXPECT_TRUE(s.length() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); auto workaround_macro = [&]() { return s[{2, 1, 0}] == 11; }; - CHECK(workaround_macro()); + EXPECT_TRUE(workaround_macro()); } { @@ -446,81 +592,93 @@ TEST_CASE("from_array_constructor") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(i.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -TEST_CASE("from_dynamic_array_constructor") +TEST(multi_span_test, from_dynamic_array_constructor) { double(*arr)[3][4] = new double[100][3][4]; + std::set_terminate([] { + std::cerr << "Expected Death. from_nullptr_length_constructor"; + std::abort(); + }); + { multi_span s(arr, 10); - CHECK((s.length() == 120 && s.data() == &arr[0][0][0])); - CHECK_THROWS_AS(s[10][3][4], fail_fast); + EXPECT_TRUE(s.length() == 120); + EXPECT_TRUE(s.data() == &arr[0][0][0]); + EXPECT_DEATH(s[10][3][4], deathstring); } { multi_span s(arr, 10); - CHECK((s.length() == 120 && s.data() == &arr[0][0][0])); + EXPECT_TRUE(s.length() == 120); + EXPECT_TRUE(s.data() == &arr[0][0][0]); } { multi_span s(arr, 10); - CHECK((s.length() == 120 && s.data() == &arr[0][0][0])); + EXPECT_TRUE(s.length() == 120); + EXPECT_TRUE(s.data() == &arr[0][0][0]); } { multi_span s(arr, 0); - CHECK((s.length() == 0 && s.data() == &arr[0][0][0])); + EXPECT_TRUE(s.length() == 0); + EXPECT_TRUE(s.data() == &arr[0][0][0]); } delete[] arr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: Attribute -TEST_CASE("from_std_array_constructor") +TEST(multi_span_test, from_std_array_constructor) { std::array arr = {1, 2, 3, 4}; { multi_span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); multi_span cs{arr}; - CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); + EXPECT_TRUE(cs.size() == narrow_cast(arr.size())); + EXPECT_TRUE(cs.data() == arr.data()); } { multi_span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); multi_span cs{arr}; - CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); + EXPECT_TRUE(cs.size() == narrow_cast(arr.size())); + EXPECT_TRUE(cs.data() == arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); multi_span cs{arr}; - CHECK((cs.size() == 2 && cs.data() == arr.data())); + EXPECT_TRUE(cs.size() == 2); + EXPECT_TRUE(cs.data() == arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); multi_span cs{arr}; - CHECK((cs.size() == 0 && cs.data() == arr.data())); + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == arr.data()); } // TODO This is currently an unsupported scenario. We will come back to it as we revise // the multidimensional interface and what transformations between dimensionality look like //{ // multi_span s{arr}; - // CHECK(s.size() == narrow_cast(arr.size()) && s.data() == arr.data()); + // EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + // EXPECT_TRUE(s.data() == arr.data()); //} { @@ -539,36 +697,40 @@ TEST_CASE("from_std_array_constructor") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_const_std_array_constructor") +TEST(multi_span_test, from_const_std_array_constructor) { const std::array arr = {1, 2, 3, 4}; { multi_span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); } { multi_span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); } // TODO This is currently an unsupported scenario. We will come back to it as we revise // the multidimensional interface and what transformations between dimensionality look like //{ // multi_span s{arr}; - // CHECK(s.size() == narrow_cast(arr.size()) && s.data() == arr.data()); + // EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + // EXPECT_TRUE(s.data() == arr.data()); //} { @@ -587,18 +749,19 @@ TEST_CASE("from_const_std_array_constructor") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_container_constructor") +TEST(multi_span_test, from_container_constructor) { std::vector v = {1, 2, 3}; const std::vector cv = v; { multi_span s{v}; - CHECK((s.size() == narrow_cast(v.size()) && s.data() == v.data())); + EXPECT_TRUE(s.size() == narrow_cast(v.size())); + EXPECT_TRUE(s.data() == v.data()); multi_span cs{v}; - CHECK((cs.size() == narrow_cast(v.size()) && cs.data() == v.data())); + EXPECT_TRUE(cs.size() == narrow_cast(v.size())); + EXPECT_TRUE(cs.data() == v.data()); } std::string str = "hello"; @@ -607,10 +770,12 @@ TEST_CASE("from_container_constructor") { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s{str}; - CHECK((s.size() == narrow_cast(str.size()) && s.data() == str.data())); + EXPECT_TRUE(s.size() == narrow_cast(str.size())); + EXPECT_TRUE(s.data() == str.data()); #endif multi_span cs{str}; - CHECK((cs.size() == narrow_cast(str.size()) && cs.data() == str.data())); + EXPECT_TRUE(cs.size() == narrow_cast(str.size())); + EXPECT_TRUE(cs.data() == str.data()); } { @@ -618,7 +783,8 @@ TEST_CASE("from_container_constructor") multi_span s{cstr}; #endif multi_span cs{cstr}; - CHECK((cs.size() == narrow_cast(cstr.size()) && cs.data() == cstr.data())); + EXPECT_TRUE(cs.size() == narrow_cast(cstr.size())); + EXPECT_TRUE(cs.data() == cstr.data()); } { @@ -661,15 +827,18 @@ TEST_CASE("from_container_constructor") } } -GSL_SUPPRESS(f.4) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_convertible_span_constructor") +TEST(multi_span_test, from_convertible_span_constructor) { #ifdef CONFIRM_COMPILATION_ERRORS multi_span av1(nullptr, b1); + std::set_terminate([] { + std::cerr << "Expected Death. from_convertible_span_constructor"; + std::abort(); + }); + auto f = [&]() { multi_span av1(nullptr); }; - CHECK_THROWS_AS(f(), fail_fast); + EXPECT_DEATH(f(), deathstring); #endif #ifdef CONFIRM_COMPILATION_ERRORS @@ -690,38 +859,33 @@ TEST_CASE("from_convertible_span_constructor") (void) avcd; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("copy_move_and_assignment") +TEST(multi_span_test, copy_move_and_assignment) { multi_span s1; - CHECK(s1.empty()); + EXPECT_TRUE(s1.empty()); int arr[] = {3, 4, 5}; multi_span s2 = arr; - CHECK((s2.length() == 3 && s2.data() == &arr[0])); + EXPECT_TRUE(s2.length() == 3); + EXPECT_TRUE(s2.data() == &arr[0]); s2 = s1; - CHECK(s2.empty()); + EXPECT_TRUE(s2.empty()); auto get_temp_span = [&]() -> multi_span { return {&arr[1], 2}; }; auto use_span = [&](multi_span s) { - CHECK((s.length() == 2 && s.data() == &arr[1])); + EXPECT_TRUE(s.length() == 2); + EXPECT_TRUE(s.data() == &arr[1]); }; use_span(get_temp_span()); s1 = get_temp_span(); - CHECK((s1.length() == 2 && s1.data() == &arr[1])); + EXPECT_TRUE(s1.length() == 2); + EXPECT_TRUE(s1.data() == &arr[1]); } -template -void fn(const Bounds&) -{ - static_assert(Bounds::static_size == 60, "static bounds is wrong size"); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("as_multi_span_reshape") +TEST(multi_span_test, as_multi_span_reshape) { int a[3][4][5]; auto av = as_multi_span(a); @@ -738,315 +902,337 @@ TEST_CASE("as_multi_span_reshape") auto av8 = as_multi_span(av7); - CHECK(av8.size() == av6.size()); - for (auto i = 0; i < av8.size(); i++) { CHECK(av8[i] == 1); } + EXPECT_TRUE(av8.size() == av6.size()); + for (auto i = 0; i < av8.size(); i++) { EXPECT_TRUE(av8[i] == 1); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("first") +TEST(multi_span_test, first) { int arr[5] = {1, 2, 3, 4, 5}; { multi_span av = arr; - CHECK((av.first<2>().bounds() == static_bounds<2>())); - CHECK(av.first<2>().length() == 2); - CHECK(av.first(2).length() == 2); + EXPECT_TRUE(av.first<2>().bounds() == static_bounds<2>()); + EXPECT_TRUE(av.first<2>().length() == 2); + EXPECT_TRUE(av.first(2).length() == 2); } { multi_span av = arr; - CHECK((av.first<0>().bounds() == static_bounds<0>())); - CHECK(av.first<0>().length() == 0); - CHECK(av.first(0).length() == 0); + EXPECT_TRUE(av.first<0>().bounds() == static_bounds<0>()); + EXPECT_TRUE(av.first<0>().length() == 0); + EXPECT_TRUE(av.first(0).length() == 0); } { multi_span av = arr; - CHECK((av.first<5>().bounds() == static_bounds<5>())); - CHECK(av.first<5>().length() == 5); - CHECK(av.first(5).length() == 5); + EXPECT_TRUE(av.first<5>().bounds() == static_bounds<5>()); + EXPECT_TRUE(av.first<5>().length() == 5); + EXPECT_TRUE(av.first(5).length() == 5); } { multi_span av = arr; #ifdef CONFIRM_COMPILATION_ERRORS - CHECK(av.first<6>().bounds() == static_bounds<6>()); - CHECK(av.first<6>().length() == 6); - CHECK(av.first<-1>().length() == -1); + EXPECT_TRUE(av.first<6>().bounds() == static_bounds<6>()); + EXPECT_TRUE(av.first<6>().length() == 6); + EXPECT_TRUE(av.first<-1>().length() == -1); #endif - CHECK_THROWS_AS(av.first(6).length(), fail_fast); + + std::set_terminate([] { + std::cerr << "Expected Death. first"; + std::abort(); + }); + + EXPECT_DEATH(av.first(6).length(), deathstring); } { multi_span av; - CHECK((av.first<0>().bounds() == static_bounds<0>())); - CHECK(av.first<0>().length() == 0); - CHECK(av.first(0).length() == 0); + EXPECT_TRUE(av.first<0>().bounds() == static_bounds<0>()); + EXPECT_TRUE(av.first<0>().length() == 0); + EXPECT_TRUE(av.first(0).length() == 0); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("last") +TEST(multi_span_test, last) { int arr[5] = {1, 2, 3, 4, 5}; { multi_span av = arr; - CHECK((av.last<2>().bounds() == static_bounds<2>())); - CHECK(av.last<2>().length() == 2); - CHECK(av.last(2).length() == 2); + EXPECT_TRUE(av.last<2>().bounds() == static_bounds<2>()); + EXPECT_TRUE(av.last<2>().length() == 2); + EXPECT_TRUE(av.last(2).length() == 2); } { multi_span av = arr; - CHECK((av.last<0>().bounds() == static_bounds<0>())); - CHECK(av.last<0>().length() == 0); - CHECK(av.last(0).length() == 0); + EXPECT_TRUE(av.last<0>().bounds() == static_bounds<0>()); + EXPECT_TRUE(av.last<0>().length() == 0); + EXPECT_TRUE(av.last(0).length() == 0); } { multi_span av = arr; - CHECK((av.last<5>().bounds() == static_bounds<5>())); - CHECK(av.last<5>().length() == 5); - CHECK(av.last(5).length() == 5); + EXPECT_TRUE(av.last<5>().bounds() == static_bounds<5>()); + EXPECT_TRUE(av.last<5>().length() == 5); + EXPECT_TRUE(av.last(5).length() == 5); } { multi_span av = arr; #ifdef CONFIRM_COMPILATION_ERRORS - CHECK((av.last<6>().bounds() == static_bounds<6>())); - CHECK(av.last<6>().length() == 6); + EXPECT_TRUE(av.last<6>().bounds() == static_bounds<6>()); + EXPECT_TRUE(av.last<6>().length() == 6); #endif - CHECK_THROWS_AS(av.last(6).length(), fail_fast); + + std::set_terminate([] { + std::cerr << "Expected Death. last"; + std::abort(); + }); + + EXPECT_DEATH(av.last(6).length(), deathstring); } { multi_span av; - CHECK((av.last<0>().bounds() == static_bounds<0>())); - CHECK(av.last<0>().length() == 0); - CHECK(av.last(0).length() == 0); + EXPECT_TRUE(av.last<0>().bounds() == static_bounds<0>()); + EXPECT_TRUE(av.last<0>().length() == 0); + EXPECT_TRUE(av.last(0).length() == 0); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("subspan") +TEST(multi_span_test, subspan) { int arr[5] = {1, 2, 3, 4, 5}; { multi_span av = arr; - CHECK((av.subspan<2, 2>().bounds() == static_bounds<2>())); - CHECK((av.subspan<2, 2>().length() == 2)); - CHECK(av.subspan(2, 2).length() == 2); - CHECK(av.subspan(2, 3).length() == 3); + EXPECT_TRUE((av.subspan<2, 2>().bounds()) == static_bounds<2>()); + EXPECT_TRUE((av.subspan<2, 2>().length()) == 2); + EXPECT_TRUE(av.subspan(2, 2).length() == 2); + EXPECT_TRUE(av.subspan(2, 3).length() == 3); } { multi_span av = arr; - CHECK((av.subspan<0, 0>().bounds() == static_bounds<0>())); - CHECK((av.subspan<0, 0>().length() == 0)); - CHECK(av.subspan(0, 0).length() == 0); + EXPECT_TRUE((av.subspan<0, 0>().bounds()) == static_bounds<0>()); + EXPECT_TRUE((av.subspan<0, 0>().length()) == 0); + EXPECT_TRUE(av.subspan(0, 0).length() == 0); + } + + + std::set_terminate([] { + std::cerr << "Expected Death. subspan"; + std::abort(); + }); + { + multi_span av = arr; + EXPECT_TRUE((av.subspan<0, 5>().bounds()) == static_bounds<5>()); + EXPECT_TRUE((av.subspan<0, 5>().length()) == 5); + EXPECT_TRUE(av.subspan(0, 5).length() == 5); + EXPECT_DEATH(av.subspan(0, 6).length(), deathstring); + EXPECT_DEATH(av.subspan(1, 5).length(), deathstring); } { multi_span av = arr; - CHECK((av.subspan<0, 5>().bounds() == static_bounds<5>())); - CHECK((av.subspan<0, 5>().length() == 5)); - CHECK(av.subspan(0, 5).length() == 5); - CHECK_THROWS_AS(av.subspan(0, 6).length(), fail_fast); - CHECK_THROWS_AS(av.subspan(1, 5).length(), fail_fast); - } - - { - multi_span av = arr; - CHECK((av.subspan<5, 0>().bounds() == static_bounds<0>())); - CHECK((av.subspan<5, 0>().length() == 0)); - CHECK(av.subspan(5, 0).length() == 0); - CHECK_THROWS_AS(av.subspan(6, 0).length(), fail_fast); + EXPECT_TRUE((av.subspan<5, 0>().bounds()) == static_bounds<0>()); + EXPECT_TRUE((av.subspan<5, 0>().length()) == 0); + EXPECT_TRUE(av.subspan(5, 0).length() == 0); + EXPECT_DEATH(av.subspan(6, 0).length(), deathstring); } { multi_span av; - CHECK((av.subspan<0, 0>().bounds() == static_bounds<0>())); - CHECK((av.subspan<0, 0>().length() == 0)); - CHECK(av.subspan(0, 0).length() == 0); - CHECK_THROWS_AS((av.subspan<1, 0>().length()), fail_fast); + EXPECT_TRUE((av.subspan<0, 0>().bounds()) == static_bounds<0>()); + EXPECT_TRUE((av.subspan<0, 0>().length()) == 0); + EXPECT_TRUE(av.subspan(0, 0).length() == 0); + EXPECT_DEATH((av.subspan<1, 0>().length()), deathstring); } { multi_span av; - CHECK(av.subspan(0).length() == 0); - CHECK_THROWS_AS(av.subspan(1).length(), fail_fast); + EXPECT_TRUE(av.subspan(0).length() == 0); + EXPECT_DEATH(av.subspan(1).length(), deathstring); } { multi_span av = arr; - CHECK(av.subspan(0).length() == 5); - CHECK(av.subspan(1).length() == 4); - CHECK(av.subspan(4).length() == 1); - CHECK(av.subspan(5).length() == 0); - CHECK_THROWS_AS(av.subspan(6).length(), fail_fast); + EXPECT_TRUE(av.subspan(0).length() == 5); + EXPECT_TRUE(av.subspan(1).length() == 4); + EXPECT_TRUE(av.subspan(4).length() == 1); + EXPECT_TRUE(av.subspan(5).length() == 0); + EXPECT_DEATH(av.subspan(6).length(), deathstring); auto av2 = av.subspan(1); - for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2); + for (int i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); } { multi_span av = arr; - CHECK(av.subspan(0).length() == 5); - CHECK(av.subspan(1).length() == 4); - CHECK(av.subspan(4).length() == 1); - CHECK(av.subspan(5).length() == 0); - CHECK_THROWS_AS(av.subspan(6).length(), fail_fast); + EXPECT_TRUE(av.subspan(0).length() == 5); + EXPECT_TRUE(av.subspan(1).length() == 4); + EXPECT_TRUE(av.subspan(4).length() == 1); + EXPECT_TRUE(av.subspan(5).length() == 0); + EXPECT_DEATH(av.subspan(6).length(), deathstring); auto av2 = av.subspan(1); - for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2); + for (int i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("rank") +TEST(multi_span_test, rank) { int arr[2] = {1, 2}; { multi_span s; - CHECK(s.rank() == 1); + EXPECT_TRUE(s.rank() == static_cast(1)); } { multi_span s = arr; - CHECK(s.rank() == 1); + EXPECT_TRUE(s.rank() == static_cast(1)); } int arr2d[1][1] = {}; { multi_span s = arr2d; - CHECK(s.rank() == 2); + EXPECT_TRUE(s.rank() == static_cast(2)); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("extent") +TEST(multi_span_test, extent) { + std::set_terminate([] { + std::cerr << "Expected Death. extent"; + std::abort(); + }); + { multi_span s; - CHECK(s.extent() == 0); - CHECK(s.extent(0) == 0); - CHECK_THROWS_AS(s.extent(1), fail_fast); + EXPECT_TRUE(s.extent() == 0); + EXPECT_TRUE(s.extent(0) == 0); + EXPECT_DEATH(s.extent(1), deathstring); #ifdef CONFIRM_COMPILATION_ERRORS - CHECK(s.extent<1>() == 0); + EXPECT_TRUE(s.extent<1>() == 0); #endif } { multi_span s; - CHECK(s.extent() == 0); - CHECK(s.extent(0) == 0); - CHECK_THROWS_AS(s.extent(1), fail_fast); + EXPECT_TRUE(s.extent() == 0); + EXPECT_TRUE(s.extent(0) == 0); + EXPECT_DEATH(s.extent(1), deathstring); } { int arr2d[1][2] = {}; multi_span s = arr2d; - CHECK(s.extent() == 1); - CHECK(s.extent<0>() == 1); - CHECK(s.extent<1>() == 2); - CHECK(s.extent(0) == 1); - CHECK(s.extent(1) == 2); - CHECK_THROWS_AS(s.extent(3), fail_fast); + EXPECT_TRUE(s.extent() == 1); + EXPECT_TRUE(s.extent<0>() == 1); + EXPECT_TRUE(s.extent<1>() == 2); + EXPECT_TRUE(s.extent(0) == 1); + EXPECT_TRUE(s.extent(1) == 2); + EXPECT_DEATH(s.extent(3), deathstring); } { int arr2d[1][2] = {}; multi_span s = arr2d; - CHECK(s.extent() == 0); - CHECK(s.extent<0>() == 0); - CHECK(s.extent<1>() == 2); - CHECK(s.extent(0) == 0); - CHECK(s.extent(1) == 2); - CHECK_THROWS_AS(s.extent(3), fail_fast); + EXPECT_TRUE(s.extent() == 0); + EXPECT_TRUE(s.extent<0>() == 0); + EXPECT_TRUE(s.extent<1>() == 2); + EXPECT_TRUE(s.extent(0) == 0); + EXPECT_TRUE(s.extent(1) == 2); + EXPECT_DEATH(s.extent(3), deathstring); } } -TEST_CASE("operator_function_call") +TEST(multi_span_test, operator_function_call) { int arr[4] = {1, 2, 3, 4}; + std::set_terminate([] { + std::cerr << "Expected Death. operator_function_call"; + std::abort(); + }); + { multi_span s = arr; - CHECK(s(0) == 1); - CHECK_THROWS_AS(s(5), fail_fast); + EXPECT_TRUE(s(0) == 1); + EXPECT_DEATH(s(5), deathstring); } int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; { multi_span s = arr2d; - CHECK(s(0, 0) == 1); - CHECK(s(0, 1) == 2); - CHECK(s(1, 2) == 6); + EXPECT_TRUE(s(0, 0) == 1); + EXPECT_TRUE(s(0, 1) == 2); + EXPECT_TRUE(s(1, 2) == 6); } int arr3d[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8}; { multi_span s = arr3d; - CHECK(s(0, 0, 0) == 1); - CHECK(s(1, 1, 1) == 8); + EXPECT_TRUE(s(0, 0, 0) == 1); + EXPECT_TRUE(s(1, 1, 1) == 8); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("comparison_operators") +TEST(multi_span_test, comparison_operators) { { int arr[10][2]; auto s1 = as_multi_span(arr); multi_span s2 = s1; - CHECK(s1 == s2); + EXPECT_TRUE(s1 == s2); multi_span s3 = as_multi_span(s1, dim(20)); - CHECK((s3 == s2 && s3 == s1)); + EXPECT_TRUE(s3 == s2); + EXPECT_TRUE(s3 == s1); } - { multi_span s1 = nullptr; multi_span s2 = nullptr; - CHECK(s1 == s2); - CHECK(!(s1 != s2)); - CHECK(!(s1 < s2)); - CHECK(s1 <= s2); - CHECK(!(s1 > s2)); - CHECK(s1 >= s2); - CHECK(s2 == s1); - CHECK(!(s2 != s1)); - CHECK(!(s2 < s1)); - CHECK(s2 <= s1); - CHECK(!(s2 > s1)); - CHECK(s2 >= s1); + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); } + { int arr[] = {2, 1}; // bigger multi_span s1 = nullptr; multi_span s2 = arr; - CHECK(s1 != s2); - CHECK(s2 != s1); - CHECK(!(s1 == s2)); - CHECK(!(s2 == s1)); - CHECK(s1 < s2); - CHECK(!(s2 < s1)); - CHECK(s1 <= s2); - CHECK(!(s2 <= s1)); - CHECK(s2 > s1); - CHECK(!(s1 > s2)); - CHECK(s2 >= s1); - CHECK(!(s1 >= s2)); + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); } { @@ -1055,18 +1241,18 @@ TEST_CASE("comparison_operators") multi_span s1 = arr1; multi_span s2 = arr2; - CHECK(s1 == s2); - CHECK(!(s1 != s2)); - CHECK(!(s1 < s2)); - CHECK(s1 <= s2); - CHECK(!(s1 > s2)); - CHECK(s1 >= s2); - CHECK(s2 == s1); - CHECK(!(s2 != s1)); - CHECK(!(s2 < s1)); - CHECK(s2 <= s1); - CHECK(!(s2 > s1)); - CHECK(s2 >= s1); + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); } { @@ -1075,18 +1261,18 @@ TEST_CASE("comparison_operators") multi_span s1 = {&arr[0], 2}; // shorter multi_span s2 = arr; // longer - CHECK(s1 != s2); - CHECK(s2 != s1); - CHECK(!(s1 == s2)); - CHECK(!(s2 == s1)); - CHECK(s1 < s2); - CHECK(!(s2 < s1)); - CHECK(s1 <= s2); - CHECK(!(s2 <= s1)); - CHECK(s2 > s1); - CHECK(!(s1 > s2)); - CHECK(s2 >= s1); - CHECK(!(s1 >= s2)); + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); } { @@ -1096,36 +1282,31 @@ TEST_CASE("comparison_operators") multi_span s1 = arr1; multi_span s2 = arr2; - CHECK(s1 != s2); - CHECK(s2 != s1); - CHECK(!(s1 == s2)); - CHECK(!(s2 == s1)); - CHECK(s1 < s2); - CHECK(!(s2 < s1)); - CHECK(s1 <= s2); - CHECK(!(s2 <= s1)); - CHECK(s2 > s1); - CHECK(!(s1 > s2)); - CHECK(s2 >= s1); - CHECK(!(s1 >= s2)); + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(i.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -TEST_CASE("basics") +TEST(multi_span_test, basics) { auto ptr = as_multi_span(new int[10], 10); fill(ptr.begin(), ptr.end(), 99); - for (int num : ptr) { CHECK(num == 99); } + for (int num : ptr) { EXPECT_TRUE(num == 99); } delete[] ptr.data(); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -TEST_CASE("bounds_checks") +TEST(multi_span_test, bounds_checks) { int arr[10][2]; auto av = as_multi_span(arr); @@ -1135,66 +1316,46 @@ TEST_CASE("bounds_checks") av[2][0] = 1; av[1][1] = 3; + std::set_terminate([] { + std::cerr << "Expected Death. bounds_check"; + std::abort(); + }); + // out of bounds - CHECK_THROWS_AS(av[1][3] = 3, fail_fast); - CHECK_THROWS_AS((av[{1, 3}] = 3), fail_fast); + EXPECT_DEATH(av[1][3] = 3, deathstring); + EXPECT_DEATH((av[{1, 3}] = 3), deathstring); - CHECK_THROWS_AS(av[10][2], fail_fast); - CHECK_THROWS_AS((av[{10, 2}]), fail_fast); + EXPECT_DEATH(av[10][2], deathstring); + EXPECT_DEATH((av[{10, 2}]), deathstring); - CHECK_THROWS_AS(av[-1][0], fail_fast); - CHECK_THROWS_AS((av[{-1, 0}]), fail_fast); + EXPECT_DEATH(av[-1][0], deathstring); + EXPECT_DEATH((av[{-1, 0}]), deathstring); - CHECK_THROWS_AS(av[0][-1], fail_fast); - CHECK_THROWS_AS((av[{0, -1}]), fail_fast); + EXPECT_DEATH(av[0][-1], deathstring); + EXPECT_DEATH((av[{0, -1}]), deathstring); } -void overloaded_func(multi_span exp, int expected_value) -{ - for (auto val : exp) { CHECK(val == expected_value); } -} - -void overloaded_func(multi_span exp, char expected_value) -{ - for (auto val : exp) { CHECK(val == expected_value); } -} - -void fixed_func(multi_span exp, int expected_value) -{ - for (auto val : exp) { CHECK(val == expected_value); } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -TEST_CASE("span_parameter_test") +TEST(multi_span_test, span_parameter_test) { auto data = new int[4][3][5]; auto av = as_multi_span(data, 4); - CHECK(av.size() == 60); + EXPECT_TRUE(av.size() == 60); fill(av.begin(), av.end(), 34); int count = 0; for_each(av.rbegin(), av.rend(), [&](int val) { count += val; }); - CHECK(count == 34 * 60); + EXPECT_TRUE(count == 34 * 60); overloaded_func(av, 34); overloaded_func(as_multi_span(av, dim(4), dim(3), dim(5)), 34); - // fixed_func(av, 34); delete[] data; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // false positive, checker does not recognize multi_span yet -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -TEST_CASE("md_access") +TEST(multi_span_test, md_access) { auto width = 5, height = 20; @@ -1212,16 +1373,16 @@ TEST_CASE("md_access") { for (auto j = 0; j < width; j++) { - CHECK(expected + 1 == image_view[i][j][0]); - CHECK(expected + 2 == image_view[i][j][1]); - CHECK(expected + 3 == image_view[i][j][2]); + EXPECT_TRUE(expected + 1 == image_view[i][j][0]); + EXPECT_TRUE(expected + 2 == image_view[i][j][1]); + EXPECT_TRUE(expected + 3 == image_view[i][j][2]); auto val = image_view[{i, j, 0}]; - CHECK(expected + 1 == val); + EXPECT_TRUE(expected + 1 == val); val = image_view[{i, j, 1}]; - CHECK(expected + 2 == val); + EXPECT_TRUE(expected + 2 == val); val = image_view[{i, j, 2}]; - CHECK(expected + 3 == val); + EXPECT_TRUE(expected + 3 == val); expected += 3; } @@ -1230,12 +1391,7 @@ TEST_CASE("md_access") delete[] image_ptr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -GSL_SUPPRESS(i.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -TEST_CASE("as_multi_span") +TEST(multi_span_test, as_multi_span) { { int* arr = new int[150]; @@ -1275,7 +1431,7 @@ TEST_CASE("as_multi_span") b = a; auto bv = as_multi_span(b, 3); - CHECK(av == bv); + EXPECT_TRUE(av == bv); const std::array arr = {0.0, 0.0, 0.0}; auto cv = as_multi_span(arr); @@ -1288,47 +1444,46 @@ TEST_CASE("as_multi_span") #ifdef CONFIRM_COMPILATION_ERRORS auto dv2 = as_multi_span(std::move(vec)); #endif + } } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -TEST_CASE("empty_spans") +TEST(multi_span_test, empty_spans) { + std::set_terminate([] { + std::cerr << "Expected Death. empty_spans"; + std::abort(); + }); + { multi_span empty_av(nullptr); - CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0}); - CHECK_THROWS_AS(empty_av[0], fail_fast); - CHECK_THROWS_AS(empty_av.begin()[0], fail_fast); - CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast); + EXPECT_TRUE(empty_av.bounds().index_bounds() == multi_span_index<1>{0}); + EXPECT_DEATH(empty_av[0], deathstring); + EXPECT_DEATH(empty_av.begin()[0], deathstring); + EXPECT_DEATH(empty_av.cbegin()[0], deathstring); for (auto& v : empty_av) { (void) v; - CHECK(false); + EXPECT_TRUE(false); } } { multi_span empty_av = {}; - CHECK(empty_av.bounds().index_bounds() == multi_span_index<1>{0}); - CHECK_THROWS_AS(empty_av[0], fail_fast); - CHECK_THROWS_AS(empty_av.begin()[0], fail_fast); - CHECK_THROWS_AS(empty_av.cbegin()[0], fail_fast); + EXPECT_TRUE(empty_av.bounds().index_bounds() == multi_span_index<1>{0}); + EXPECT_DEATH(empty_av[0], deathstring); + EXPECT_DEATH(empty_av.begin()[0], deathstring); + EXPECT_DEATH(empty_av.cbegin()[0], deathstring); for (auto& v : empty_av) { (void) v; - CHECK(false); + EXPECT_TRUE(false); } } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -TEST_CASE("index_constructor") +TEST(multi_span_test, index_constructor) { auto arr = new int[8]; for (int i = 0; i < 4; ++i) @@ -1342,78 +1497,77 @@ TEST_CASE("index_constructor") ptrdiff_t a[1] = {0}; multi_span_index<1> i = a; - CHECK(av[i] == 4); + EXPECT_TRUE(av[i] == 4); auto av2 = as_multi_span(av, dim<4>(), dim(2)); ptrdiff_t a2[2] = {0, 1}; multi_span_index<2> i2 = a2; - CHECK(av2[i2] == 0); - CHECK(av2[0][i] == 4); + EXPECT_TRUE(av2[i2] == 0); + EXPECT_TRUE(av2[0][i] == 4); delete[] arr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("index_constructors") +TEST(multi_span_test, index_constructors) { { // components of the same type multi_span_index<3> i1(0, 1, 2); - CHECK(i1[0] == 0); + EXPECT_TRUE(i1[0] == 0); // components of different types std::size_t c0 = 0; std::size_t c1 = 1; multi_span_index<3> i2(c0, c1, 2); - CHECK(i2[0] == 0); + EXPECT_TRUE(i2[0] == 0); // from array multi_span_index<3> i3 = {0, 1, 2}; - CHECK(i3[0] == 0); + EXPECT_TRUE(i3[0] == 0); // from other index of the same size type multi_span_index<3> i4 = i3; - CHECK(i4[0] == 0); + EXPECT_TRUE(i4[0] == 0); // default multi_span_index<3> i7; - CHECK(i7[0] == 0); + EXPECT_TRUE(i7[0] == 0); // default multi_span_index<3> i9 = {}; - CHECK(i9[0] == 0); + EXPECT_TRUE(i9[0] == 0); } { // components of the same type multi_span_index<1> i1(0); - CHECK(i1[0] == 0); + EXPECT_TRUE(i1[0] == 0); // components of different types std::size_t c0 = 0; multi_span_index<1> i2(c0); - CHECK(i2[0] == 0); + EXPECT_TRUE(i2[0] == 0); // from array multi_span_index<1> i3 = {0}; - CHECK(i3[0] == 0); + EXPECT_TRUE(i3[0] == 0); // from int multi_span_index<1> i4 = 0; - CHECK(i4[0] == 0); + EXPECT_TRUE(i4[0] == 0); // from other index of the same size type multi_span_index<1> i5 = i3; - CHECK(i5[0] == 0); + EXPECT_TRUE(i5[0] == 0); // default multi_span_index<1> i8; - CHECK(i8[0] == 0); + EXPECT_TRUE(i8[0] == 0); // default multi_span_index<1> i9 = {}; - CHECK(i9[0] == 0); + EXPECT_TRUE(i9[0] == 0); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -1427,122 +1581,62 @@ TEST_CASE("index_constructors") #endif } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("index_operations") +TEST(multi_span_test, index_operations) { ptrdiff_t a[3] = {0, 1, 2}; ptrdiff_t b[3] = {3, 4, 5}; multi_span_index<3> i = a; multi_span_index<3> j = b; - CHECK(i[0] == 0); - CHECK(i[1] == 1); - CHECK(i[2] == 2); + EXPECT_TRUE(i[0] == 0); + EXPECT_TRUE(i[1] == 1); + EXPECT_TRUE(i[2] == 2); { multi_span_index<3> k = i + j; - CHECK(i[0] == 0); - CHECK(i[1] == 1); - CHECK(i[2] == 2); - CHECK(k[0] == 3); - CHECK(k[1] == 5); - CHECK(k[2] == 7); + EXPECT_TRUE(i[0] == 0); + EXPECT_TRUE(i[1] == 1); + EXPECT_TRUE(i[2] == 2); + EXPECT_TRUE(k[0] == 3); + EXPECT_TRUE(k[1] == 5); + EXPECT_TRUE(k[2] == 7); } { multi_span_index<3> k = i * 3; - CHECK(i[0] == 0); - CHECK(i[1] == 1); - CHECK(i[2] == 2); - CHECK(k[0] == 0); - CHECK(k[1] == 3); - CHECK(k[2] == 6); + EXPECT_TRUE(i[0] == 0); + EXPECT_TRUE(i[1] == 1); + EXPECT_TRUE(i[2] == 2); + EXPECT_TRUE(k[0] == 0); + EXPECT_TRUE(k[1] == 3); + EXPECT_TRUE(k[2] == 6); } { multi_span_index<3> k = 3 * i; - CHECK(i[0] == 0); - CHECK(i[1] == 1); - CHECK(i[2] == 2); - CHECK(k[0] == 0); - CHECK(k[1] == 3); - CHECK(k[2] == 6); + EXPECT_TRUE(i[0] == 0); + EXPECT_TRUE(i[1] == 1); + EXPECT_TRUE(i[2] == 2); + EXPECT_TRUE(k[0] == 0); + EXPECT_TRUE(k[1] == 3); + EXPECT_TRUE(k[2] == 6); } { multi_span_index<2> k = details::shift_left(i); - CHECK(i[0] == 0); - CHECK(i[1] == 1); - CHECK(i[2] == 2); - CHECK(k[0] == 1); - CHECK(k[1] == 2); + EXPECT_TRUE(i[0] == 0); + EXPECT_TRUE(i[1] == 1); + EXPECT_TRUE(i[2] == 2); + EXPECT_TRUE(k[0] == 1); + EXPECT_TRUE(k[1] == 2); } } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -void iterate_second_column(multi_span av) -{ - auto length = av.size() / 2; - - // view to the second column - auto section = av.section({0, 1}, {length, 1}); - - CHECK(section.size() == length); - for (auto i = 0; i < section.size(); ++i) { CHECK(section[i][0] == av[i][1]); } - - for (auto i = 0; i < section.size(); ++i) - { - auto idx = multi_span_index<2>{i, 0}; // avoid braces inside the CHECK macro - CHECK(section[idx] == av[i][1]); - } - - CHECK(section.bounds().index_bounds()[0] == length); - CHECK(section.bounds().index_bounds()[1] == 1); - for (auto i = 0; i < section.bounds().index_bounds()[0]; ++i) - { - for (auto j = 0; j < section.bounds().index_bounds()[1]; ++j) - { - auto idx = multi_span_index<2>{i, j}; // avoid braces inside the CHECK macro - CHECK(section[idx] == av[i][1]); - } - } - - auto check_sum = 0; - for (auto i = 0; i < length; ++i) { check_sum += av[i][1]; } - - { - auto idx = 0; - auto sum = 0; - for (auto num : section) - { - CHECK(num == av[idx][1]); - sum += num; - idx++; - } - - CHECK(sum == check_sum); - } - { - auto idx = length - 1; - auto sum = 0; - for (auto iter = section.rbegin(); iter != section.rend(); ++iter) - { - CHECK(*iter == av[idx][1]); - sum += *iter; - idx--; - } - - CHECK(sum == check_sum); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("span_section_iteration") +TEST(multi_span_test, span_section_iteration) { int arr[4][2] = {{4, 0}, {5, 1}, {6, 2}, {7, 3}}; @@ -1568,12 +1662,7 @@ TEST_CASE("span_section_iteration") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -TEST_CASE("dynamic_span_section_iteration") +TEST(multi_span_test, dynamic_span_section_iteration) { auto height = 4, width = 2; auto size = height * width; @@ -1603,11 +1692,7 @@ TEST_CASE("dynamic_span_section_iteration") delete[] arr; } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(i.11) // NO-FORMAT: attribute -TEST_CASE("span_structure_size") +TEST(multi_span_test, span_structure_size) { double(*arr)[3][4] = new double[100][3][4]; multi_span av1(arr, 10); @@ -1617,9 +1702,14 @@ TEST_CASE("span_structure_size") double* v1; ptrdiff_t v2; }; - CHECK(sizeof(av1) == sizeof(EffectiveStructure)); + EXPECT_TRUE(sizeof(av1) == sizeof(EffectiveStructure)); - CHECK_THROWS_AS(av1[10][3][4], fail_fast); + std::set_terminate([] { + std::cerr << "Expected Death. span_structure_size"; + std::abort(); + }); + + EXPECT_DEATH(av1[10][3][4], deathstring); multi_span av2 = as_multi_span(av1, dim(5), dim<6>(), dim<4>()); @@ -1628,14 +1718,13 @@ TEST_CASE("span_structure_size") delete[] arr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("fixed_size_conversions") +TEST(multi_span_test, fixed_size_conversions) { int arr[] = {1, 2, 3, 4}; // converting to an multi_span from an equal size array is ok multi_span av4 = arr; - CHECK(av4.length() == 4); + EXPECT_TRUE(av4.length() == 4); // converting to dynamic_range a_v is always ok { @@ -1674,7 +1763,7 @@ TEST_CASE("fixed_size_conversions") multi_span av = arr; multi_span av2 = as_multi_span(av, dim(2), dim(2)); auto workaround_macro = [&]() { return av2[{1, 0}] == 2; }; - CHECK(workaround_macro()); + EXPECT_TRUE(workaround_macro()); } // but doing so explicitly is ok @@ -1708,12 +1797,18 @@ TEST_CASE("fixed_size_conversions") multi_span av4 = av2; } #endif + + std::set_terminate([] { + std::cerr << "Expected Death. fixed_size_conversions"; + std::abort(); + }); + { auto f = [&]() { const multi_span av9 = {arr2, 2}; (void) av9; }; - CHECK_THROWS_AS(f(), fail_fast); + EXPECT_DEATH(f(), deathstring); } // this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one @@ -1722,11 +1817,10 @@ TEST_CASE("fixed_size_conversions") const multi_span av2 = av; (void) av2; }; - CHECK_THROWS_AS(f(), fail_fast); + EXPECT_DEATH(f(), deathstring); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("as_writeable_bytes") +TEST(multi_span_test, as_writeable_bytes) { int a[] = {1, 2, 3, 4}; @@ -1741,24 +1835,20 @@ TEST_CASE("as_writeable_bytes") { multi_span av; auto wav = as_writeable_bytes(av); - CHECK(wav.length() == av.length()); - CHECK(wav.length() == 0); - CHECK(wav.size_bytes() == 0); + EXPECT_TRUE(wav.length() == av.length()); + EXPECT_TRUE(wav.length() == 0); + EXPECT_TRUE(wav.size_bytes() == 0); } { multi_span av = a; auto wav = as_writeable_bytes(av); - CHECK(wav.data() == reinterpret_cast(&a[0])); - CHECK(static_cast(wav.length()) == sizeof(a)); + EXPECT_TRUE(wav.data() == reinterpret_cast(&a[0])); + EXPECT_TRUE(static_cast(wav.length()) == sizeof(a)); } } - -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("iterator") +TEST(multi_span_test, iterator) { int a[] = {1, 2, 3, 4}; @@ -1775,7 +1865,7 @@ TEST_CASE("iterator") } for (std::size_t i = 0; i < 4; ++i) { - CHECK(a[i] == 0); + EXPECT_TRUE(a[i] == 0); } } @@ -1785,7 +1875,7 @@ TEST_CASE("iterator") n = 1; } for (std::size_t i = 0; i < 4; ++i) { - CHECK(a[i] == 1); + EXPECT_TRUE(a[i] == 1); } } } @@ -1796,4 +1886,4 @@ copy(src_span_static, dst_span_static); #if __clang__ || __GNUC__ #pragma GCC diagnostic pop -#endif +#endif // __clang__ || __GNUC__ diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 010dd00..d9e0709 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -23,7 +23,19 @@ #pragma warning(disable : 4702) // unreachable code #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for not_null, operator<, operator<=, operator> @@ -34,13 +46,13 @@ #include // for basic_string, operator==, string, operator<< #include // for type_info -namespace gsl -{ -struct fail_fast; -} // namespace gsl - using namespace gsl; +namespace +{ +static constexpr char deathstring[] = "Expected Death"; +} //namespace + struct MyBase { }; @@ -133,10 +145,8 @@ GSL_SUPPRESS(f.4) // NO-FORMAT: attribute bool helper_const(not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } -const int* return_pointer_const() { return nullptr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestNotNullConstructors") +TEST(notnull_tests, TestNotNullConstructors) { { #ifdef CONFIRM_COMPILATION_ERRORS @@ -153,18 +163,22 @@ TEST_CASE("TestNotNullConstructors") #endif } + std::set_terminate([] { + std::cerr << "Expected Death. TestNotNullConstructors"; + std::abort(); + }); { // from shared pointer int i = 12; auto rp = RefCounted(&i); not_null p(rp); - CHECK(p.get() == &i); + EXPECT_TRUE(p.get() == &i); not_null> x( std::make_shared(10)); // shared_ptr is nullptr assignable int* pi = nullptr; - CHECK_THROWS_AS(not_null(pi), fail_fast); + EXPECT_DEATH((not_null(pi)), deathstring); } { @@ -175,7 +189,7 @@ TEST_CASE("TestNotNullConstructors") helper(&t); helper_const(&t); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -191,7 +205,7 @@ TEST_CASE("TestNotNullConstructors") helper(x); helper_const(x); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -205,7 +219,7 @@ TEST_CASE("TestNotNullConstructors") helper_const(cp); helper_const(x); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -215,19 +229,18 @@ TEST_CASE("TestNotNullConstructors") auto x = not_null{cp}; - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { // from returned pointer - CHECK_THROWS_AS(helper(return_pointer()), fail_fast); - CHECK_THROWS_AS(helper_const(return_pointer()), fail_fast); + EXPECT_DEATH(helper(return_pointer()), deathstring); + EXPECT_DEATH(helper_const(return_pointer()), deathstring); } } template -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute void ostream_helper(T v) { not_null p(&v); @@ -236,18 +249,18 @@ void ostream_helper(T v) std::ostringstream ref; os << static_cast(p); ref << static_cast(&v); - CHECK(os.str() == ref.str()); + EXPECT_TRUE(os.str() == ref.str()); } { std::ostringstream os; std::ostringstream ref; os << *p; ref << v; - CHECK(os.str() == ref.str()); + EXPECT_TRUE(os.str() == ref.str()); } } -TEST_CASE("TestNotNullostream") +TEST(notnull_tests, TestNotNullostream) { ostream_helper(17); ostream_helper(21.5f); @@ -258,9 +271,7 @@ TEST_CASE("TestNotNullostream") ostream_helper("string"); } -GSL_SUPPRESS(type.1) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestNotNullCasting") +TEST(notnull_tests, TestNotNullCasting) { MyBase base; MyDerived derived; @@ -270,7 +281,7 @@ TEST_CASE("TestNotNullCasting") not_null p{&derived}; not_null q(&base); q = p; // allowed with heterogeneous copy ctor - CHECK(q == p); + EXPECT_TRUE(q == p); #ifdef CONFIRM_COMPILATION_ERRORS q = u; // no viable conversion possible between MyBase* and Unrelated* @@ -280,20 +291,25 @@ TEST_CASE("TestNotNullCasting") not_null s = reinterpret_cast(p); #endif not_null t(reinterpret_cast(p.get())); - CHECK(reinterpret_cast(p.get()) == reinterpret_cast(t.get())); + EXPECT_TRUE(reinterpret_cast(p.get()) == reinterpret_cast(t.get())); } -TEST_CASE("TestNotNullAssignment") +TEST(notnull_tests, TestNotNullAssignment) { + std::set_terminate([] { + std::cerr << "Expected Death. TestNotNullAssignmentd"; + std::abort(); + }); + int i = 12; not_null p(&i); - CHECK(helper(p)); + EXPECT_TRUE(helper(p)); int* q = nullptr; - CHECK_THROWS_AS(p = not_null(q), fail_fast); + EXPECT_DEATH(p = not_null(q), deathstring); } -TEST_CASE("TestNotNullRawPointerComparison") +TEST(notnull_tests, TestNotNullRawPointerComparison) { int ints[2] = {42, 43}; int* p1 = &ints[0]; @@ -302,34 +318,33 @@ TEST_CASE("TestNotNullRawPointerComparison") using NotNull1 = not_null; using NotNull2 = not_null; - CHECK((NotNull1(p1) == NotNull1(p1)) == true); - CHECK((NotNull1(p1) == NotNull2(p2)) == false); + EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == true); + EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == false); - CHECK((NotNull1(p1) != NotNull1(p1)) == false); - CHECK((NotNull1(p1) != NotNull2(p2)) == true); + EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == false); + EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == true); - CHECK((NotNull1(p1) < NotNull1(p1)) == false); - CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); - CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); + EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == false); + EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); + EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); - CHECK((NotNull1(p1) > NotNull1(p1)) == false); - CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); - CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); + EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == false); + EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); + EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); - CHECK((NotNull1(p1) <= NotNull1(p1)) == true); - CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); - CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); + EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == true); + EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); + EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestNotNullDereferenceOperator") +TEST(notnull_tests, TestNotNullDereferenceOperator) { { auto sp1 = std::make_shared(); using NotNullSp1 = not_null; - CHECK(typeid(*sp1) == typeid(*NotNullSp1(sp1))); - CHECK(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1)); + EXPECT_TRUE(typeid(*sp1) == typeid(*NotNullSp1(sp1))); + EXPECT_TRUE(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1)); } { @@ -337,22 +352,22 @@ TEST_CASE("TestNotNullDereferenceOperator") CustomPtr p1(&ints[0]); using NotNull1 = not_null; - CHECK(typeid(*NotNull1(p1)) == typeid(*p1)); - CHECK(*NotNull1(p1) == 42); + EXPECT_TRUE(typeid(*NotNull1(p1)) == typeid(*p1)); + EXPECT_TRUE(*NotNull1(p1) == 42); *NotNull1(p1) = 43; - CHECK(ints[0] == 43); + EXPECT_TRUE(ints[0] == 43); } { int v = 42; gsl::not_null p(&v); - CHECK(typeid(*p) == typeid(*(&v))); + EXPECT_TRUE(typeid(*p) == typeid(*(&v))); *p = 43; - CHECK(v == 43); + EXPECT_TRUE(v == 43); } } -TEST_CASE("TestNotNullSharedPtrComparison") +TEST(notnull_tests, TestNotNullSharedPtrComparison) { auto sp1 = std::make_shared(42); auto sp2 = std::make_shared(43); @@ -360,31 +375,30 @@ TEST_CASE("TestNotNullSharedPtrComparison") using NotNullSp1 = not_null; using NotNullSp2 = not_null; - CHECK((NotNullSp1(sp1) == NotNullSp1(sp1)) == true); - CHECK((NotNullSp1(sp1) == NotNullSp2(sp2)) == false); + EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp1(sp1)) == true); + EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp2(sp2)) == false); - CHECK((NotNullSp1(sp1) != NotNullSp1(sp1)) == false); - CHECK((NotNullSp1(sp1) != NotNullSp2(sp2)) == true); + EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp1(sp1)) == false); + EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp2(sp2)) == true); - CHECK((NotNullSp1(sp1) < NotNullSp1(sp1)) == false); - CHECK((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2)); - CHECK((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1)); + EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp1(sp1)) == false); + EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2)); + EXPECT_TRUE((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1)); - CHECK((NotNullSp1(sp1) > NotNullSp1(sp1)) == false); - CHECK((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2)); - CHECK((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1)); + EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp1(sp1)) == false); + EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2)); + EXPECT_TRUE((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1)); - CHECK((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true); - CHECK((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2)); - CHECK((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1)); + EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true); + EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2)); + EXPECT_TRUE((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1)); - CHECK((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true); - CHECK((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2)); - CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1)); + EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true); + EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2)); + EXPECT_TRUE((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1)); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestNotNullCustomPtrComparison") +TEST(notnull_tests, TestNotNullCustomPtrComparison) { int ints[2] = {42, 43}; CustomPtr p1(&ints[0]); @@ -393,33 +407,32 @@ TEST_CASE("TestNotNullCustomPtrComparison") using NotNull1 = not_null; using NotNull2 = not_null; - CHECK((NotNull1(p1) == NotNull1(p1)) == "true"); - CHECK((NotNull1(p1) == NotNull2(p2)) == "false"); + EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == "true"); + EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == "false"); - CHECK((NotNull1(p1) != NotNull1(p1)) == "false"); - CHECK((NotNull1(p1) != NotNull2(p2)) == "true"); + EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == "false"); + EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == "true"); - CHECK((NotNull1(p1) < NotNull1(p1)) == "false"); - CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); - CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); + EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == "false"); + EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); + EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); - CHECK((NotNull1(p1) > NotNull1(p1)) == "false"); - CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); - CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); + EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == "false"); + EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); + EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); - CHECK((NotNull1(p1) <= NotNull1(p1)) == "true"); - CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); - CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); + EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == "true"); + EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); + EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); - CHECK((NotNull1(p1) >= NotNull1(p1)) == "true"); - CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2)); - CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1)); + EXPECT_TRUE((NotNull1(p1) >= NotNull1(p1)) == "true"); + EXPECT_TRUE((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2)); + EXPECT_TRUE((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1)); } #if defined(__cplusplus) && (__cplusplus >= 201703L) -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestNotNullConstructorTypeDeduction") +TEST(notnull_tests, TestNotNullConstructorTypeDeduction) { { int i = 42; @@ -428,7 +441,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") helper(not_null{&i}); helper_const(not_null{&i}); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -439,15 +452,20 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") helper(not_null{p}); helper_const(not_null{p}); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } + std::set_terminate([] { + std::cerr << "Expected Death. TestNotNullConstructorTypeDeduction"; + std::abort(); + }); + { auto workaround_macro = []() { int* p1 = nullptr; const not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { @@ -455,14 +473,14 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") const int* p1 = nullptr; const not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { int* p = nullptr; - CHECK_THROWS_AS(helper(not_null{p}), fail_fast); - CHECK_THROWS_AS(helper_const(not_null{p}), fail_fast); + EXPECT_DEATH(helper(not_null{p}), deathstring); + EXPECT_DEATH(helper_const(not_null{p}), deathstring); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -475,7 +493,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) -TEST_CASE("TestMakeNotNull") +TEST(notnull_tests, TestMakeNotNull) { { int i = 42; @@ -484,7 +502,7 @@ TEST_CASE("TestMakeNotNull") helper(make_not_null(&i)); helper_const(make_not_null(&i)); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -495,42 +513,51 @@ TEST_CASE("TestMakeNotNull") helper(make_not_null(p)); helper_const(make_not_null(p)); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } + std::set_terminate([] { + std::cerr << "Expected Death. TestMakeNotNull"; + std::abort(); + }); + { const auto workaround_macro = []() { int* p1 = nullptr; const auto x = make_not_null(p1); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { const auto workaround_macro = []() { const int* p1 = nullptr; const auto x = make_not_null(p1); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { int* p = nullptr; - CHECK_THROWS_AS(helper(make_not_null(p)), fail_fast); - CHECK_THROWS_AS(helper_const(make_not_null(p)), fail_fast); + EXPECT_DEATH(helper(make_not_null(p)), deathstring); + EXPECT_DEATH(helper_const(make_not_null(p)), deathstring); } #ifdef CONFIRM_COMPILATION_ERRORS { - CHECK_THROWS_AS(make_not_null(nullptr), fail_fast); - CHECK_THROWS_AS(helper(make_not_null(nullptr)), fail_fast); - CHECK_THROWS_AS(helper_const(make_not_null(nullptr)), fail_fast); + EXPECT_DEATH(make_not_null(nullptr), deathstring); + EXPECT_DEATH(helper(make_not_null(nullptr)), deathstring); + EXPECT_DEATH(helper_const(make_not_null(nullptr)), deathstring); } #endif } static_assert(std::is_nothrow_move_constructible>::value, "not_null must be no-throw move constructible"); + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 9fff184..6442033 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -21,7 +21,19 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for owner @@ -30,19 +42,16 @@ using namespace gsl; GSL_SUPPRESS(f.23) // NO-FORMAT: attribute void f(int* i) { *i += 1; } -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute // TODO: false positive -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -TEST_CASE("basic_test") +TEST(owner_tests, basic_test) { owner p = new int(120); - CHECK(*p == 120); + EXPECT_TRUE(*p == 120); f(p); - CHECK(*p == 121); + EXPECT_TRUE(*p == 121); delete p; } -TEST_CASE("check_pointer_constraint") +TEST(owner_tests, check_pointer_constraint) { #ifdef CONFIRM_COMPILATION_ERRORS { @@ -51,3 +60,7 @@ TEST_CASE("check_pointer_constraint") } #endif } + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index d22dc08..f619d48 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -17,11 +17,24 @@ #ifdef _MSC_VER // blanket turn off warnings from CppCoreCheck from catch // so people aren't annoyed by them when running the tool. -#pragma warning(disable : 26440 26426 26497) // from catch +#pragma warning(disable : 26440 26426 26497 4189) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for byte #include // for narrow_cast, at @@ -47,6 +60,8 @@ using namespace gsl; namespace { +static constexpr char deathstring[] = "Expected Death"; + struct BaseClass { }; @@ -58,142 +73,136 @@ struct AddressOverloaded #if (__cplusplus > 201402L) [[maybe_unused]] #endif - AddressOverloaded operator&() const { return {}; } + AddressOverloaded + operator&() const + { + return {}; + } }; } // namespace -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("default_constructor") +TEST(span_test, constructors) { - { - span s; - CHECK((s.size() == 0 && s.data() == nullptr)); + span s; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); - span cs; - CHECK((cs.size() == 0 && cs.data() == nullptr)); - } - - { - span s; - CHECK((s.size() == 0 && s.data() == nullptr)); - - span cs; - CHECK((cs.size() == 0 && cs.data() == nullptr)); - } - - { -#ifdef CONFIRM_COMPILATION_ERRORS - span s; - CHECK((s.size() == 1 && s.data() == nullptr)); // explains why it can't compile -#endif - } - - { - span s{}; - CHECK((s.size() == 0 && s.data() == nullptr)); - - span cs{}; - CHECK((cs.size() == 0 && cs.data() == nullptr)); - } + span cs; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("size_optimization") +TEST(span_test, constructors_with_extent) { - { - span s; - CHECK(sizeof(s) == sizeof(int*) + sizeof(ptrdiff_t)); - } + span s; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); - { - span s; - CHECK(sizeof(s) == sizeof(int*)); - } + span cs; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_nullptr_size_constructor") +TEST(span_test, constructors_with_bracket_init) { + span s{}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + + span cs{}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); +} + +TEST(span_test, size_optimization) +{ + span s; + EXPECT_TRUE(sizeof(s) == sizeof(int*) + sizeof(ptrdiff_t)); + + span se; + EXPECT_TRUE(sizeof(se) == sizeof(int*)); +} + +TEST(span_test, from_nullptr_size_constructor) +{ + std::set_terminate([] { + std::cerr << "Expected Death. from_nullptr_size_constructor"; + std::abort(); + }); { span s{nullptr, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); - span cs{nullptr, narrow_cast::index_type>(0)}; - CHECK((cs.size() == 0 && cs.data() == nullptr)); + span cs{nullptr, narrow_cast::index_type>(0)}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); } - - { - span s{nullptr, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); - - span cs{nullptr, narrow_cast::index_type>(0)}; - CHECK((cs.size() == 0 && cs.data() == nullptr)); - } - { auto workaround_macro = []() { const span s{nullptr, narrow_cast::index_type>(0)}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } - { auto workaround_macro = []() { const span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); - auto const_workaround_macro = []() { const span cs{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + auto const_workaround_macro = []() { const span s{nullptr, 1}; }; + EXPECT_DEATH(const_workaround_macro(), deathstring); } - { auto workaround_macro = []() { const span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); auto const_workaround_macro = []() { const span s{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + EXPECT_DEATH(const_workaround_macro(), deathstring); } - { span s{nullptr, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); span cs{nullptr, narrow_cast::index_type>(0)}; - CHECK((cs.size() == 0 && cs.data() == nullptr)); + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("from_pointer_length_constructor") +TEST(span_test, from_pointer_length_constructor) { + std::set_terminate([] { + std::cerr << "Expected Death. from_pointer_length_constructor"; + std::abort(); + }); int arr[4] = {1, 2, 3, 4}; { - for(int i = 0; i<4 ; ++i) + for (int i = 0; i < 4; ++i) { { - span s = { &arr[0], i }; - CHECK(s.size() == i); - CHECK(s.data() == &arr[0]); - CHECK(s.empty() == (i == 0)); + span s = {&arr[0], i}; + EXPECT_TRUE(s.size() == i); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s.empty() == (i == 0)); for (int j = 0; j < i; ++j) { - CHECK(arr[j] == s[j]); - CHECK(arr[j] == s.at(j)); - CHECK(arr[j] == s(j)); + EXPECT_TRUE(arr[j] == s[j]); + EXPECT_TRUE(arr[j] == s.at(j)); + EXPECT_TRUE(arr[j] == s(j)); } } { - span s = { &arr[i], 4-narrow_cast(i) }; - CHECK(s.size() == 4-i); - CHECK(s.data() == &arr[i]); - CHECK(s.empty() == (4-i == 0)); - for (int j = 0; j < 4-i; ++j) + span s = {&arr[i], 4 - narrow_cast(i)}; + EXPECT_TRUE(s.size() == 4 - i); + EXPECT_TRUE(s.data() == &arr[i]); + EXPECT_TRUE(s.empty() == ((4 - i) == 0)); + + for (int j = 0; j < 4 - i; ++j) { - CHECK(arr[j+i] == s[j]); - CHECK(arr[j+i] == s.at(j)); - CHECK(arr[j+i] == s(j)); + EXPECT_TRUE(arr[j + i] == s[j]); + EXPECT_TRUE(arr[j + i] == s.at(j)); + EXPECT_TRUE(arr[j + i] == s(j)); } } } @@ -201,1364 +210,1439 @@ TEST_CASE("from_pointer_length_constructor") { span s{&arr[0], 2}; - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { int* p = nullptr; span s{p, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); } { int* p = nullptr; auto workaround_macro = [=]() { const span s{p, 2}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { auto s = make_span(&arr[0], 2); - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { int* p = nullptr; auto s = make_span(p, narrow_cast::index_type>(0)); - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); } { int* p = nullptr; auto workaround_macro = [=]() { make_span(p, 2); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } } - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_pointer_pointer_constructor") +TEST(span_test, from_pointer_pointer_construction) { int arr[4] = {1, 2, 3, 4}; { span s{&arr[0], &arr[2]}; - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } - { span s{&arr[0], &arr[2]}; - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { span s{&arr[0], &arr[0]}; - CHECK((s.size() == 0 && s.data() == &arr[0])); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); } { span s{&arr[0], &arr[0]}; - CHECK((s.size() == 0 && s.data() == &arr[0])); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); } // this will fail the std::distance() precondition, which asserts on MSVC debug builds //{ // auto workaround_macro = [&]() { span s{&arr[1], &arr[0]}; }; - // CHECK_THROWS_AS(workaround_macro(), fail_fast); + // EXPECT_DEATH(workaround_macro(), deathstring); //} // this will fail the std::distance() precondition, which asserts on MSVC debug builds //{ // int* p = nullptr; // auto workaround_macro = [&]() { span s{&arr[0], p}; }; - // CHECK_THROWS_AS(workaround_macro(), fail_fast); + // EXPECT_DEATH(workaround_macro(), deathstring); //} { int* p = nullptr; span s{p, p}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); } { int* p = nullptr; span s{p, p}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); } // this will fail the std::distance() precondition, which asserts on MSVC debug builds //{ // int* p = nullptr; // auto workaround_macro = [&]() { span s{&arr[0], p}; }; - // CHECK_THROWS_AS(workaround_macro(), fail_fast); + // EXPECT_DEATH(workaround_macro(), deathstring); //} { auto s = make_span(&arr[0], &arr[2]); - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); } { auto s = make_span(&arr[0], &arr[0]); - CHECK((s.size() == 0 && s.data() == &arr[0])); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); } { int* p = nullptr; auto s = make_span(p, p); - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); } } -TEST_CASE("from_array_constructor") -{ - int arr[5] = {1, 2, 3, 4, 5}; - - { - const span s{arr}; - CHECK((s.size() == 5 && s.data() == &arr[0])); - } - - { - const span s{arr}; - CHECK((s.size() == 5 && s.data() == &arr[0])); - } - - int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; - -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s{arr}; - } - - { - span s{arr}; - CHECK((s.size() == 0 && s.data() == &arr[0])); - } - - { - span s{arr2d}; - CHECK((s.size() == 6 && s.data() == &arr2d[0][0])); - CHECK((s[0] == 1 && s[5] == 6)); - } - - { - span s{arr2d}; - CHECK((s.size() == 0 && s.data() == &arr2d[0][0])); - } - - { - span s{arr2d}; - } -#endif - { - const span s{std::addressof(arr2d[0]), 1}; - CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0]))); - } - - int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; - -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s{arr3d}; - CHECK((s.size() == 12 && s.data() == &arr3d[0][0][0])); - CHECK((s[0] == 1 && s[11] == 12)); - } - - { - span s{arr3d}; - CHECK((s.size() == 0 && s.data() == &arr3d[0][0][0])); - } - - { - span s{arr3d}; - } - - { - span s{arr3d}; - CHECK((s.size() == 12 && s.data() == &arr3d[0][0][0])); - CHECK((s[0] == 1 && s[5] == 6)); - } -#endif - { - const span s{std::addressof(arr3d[0]), 1}; - CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0]))); - } - - { - const auto s = make_span(arr); - CHECK((s.size() == 5 && s.data() == std::addressof(arr[0]))); - } - - { - const auto s = make_span(std::addressof(arr2d[0]), 1); - CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0]))); - } - - { - const auto s = make_span(std::addressof(arr3d[0]), 1); - CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0]))); - } - - AddressOverloaded ao_arr[5] = {}; - - { - const span s{ao_arr}; - CHECK((s.size() == 5 && s.data() == std::addressof(ao_arr[0]))); - } - -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(i.11) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("from_dynamic_array_constructor") -{ - double(*arr)[3][4] = new double[100][3][4]; - - { - span s(&arr[0][0][0], 10); - CHECK((s.size() == 10 && s.data() == &arr[0][0][0])); - } - - { - auto s = make_span(&arr[0][0][0], 10); - CHECK((s.size() == 10 && s.data() == &arr[0][0][0])); - } - - delete[] arr; -} - - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_std_array_constructor") -{ - std::array arr = {1, 2, 3, 4}; - - { - span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - - span cs{arr}; - CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); - } - - { - span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - - span cs{arr}; - CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); - } - - { - std::array empty_arr{}; - span s{empty_arr}; - CHECK((s.size() == 0 && s.empty())); - } - - std::array ao_arr{}; - - { - span fs{ao_arr}; - CHECK((fs.size() == narrow_cast(ao_arr.size()) && ao_arr.data() == fs.data())); - } - -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); - - span cs{arr}; - CHECK((cs.size() == 2 && cs.data() == arr.data())); - } - - { - span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); - - span cs{arr}; - CHECK((cs.size() == 0 && cs.data() == arr.data())); - } - - { - span s{arr}; - } - - { - auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; - auto take_a_span = [](span s) { static_cast(s); }; - // try to take a temporary std::array - take_a_span(get_an_array()); - } -#endif - - { - auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; - auto take_a_span = [](span s) { static_cast(s); }; - // try to take a temporary std::array - take_a_span(get_an_array()); - } - - { - auto s = make_span(arr); - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } - - // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590 - { - span s1 = make_span(arr); - - static span s2; - s2 = s1; - - #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \ - __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__) - // Known to be broken in gcc 6.4 and 6.5 with optimizations - // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 - CHECK(s1.size() == 4); - CHECK(s2.size() == 0); - #else - CHECK(s1.size() == s2.size()); - #endif - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_const_std_array_constructor") -{ - const std::array arr = {1, 2, 3, 4}; - - { - span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } - - { - span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } - - const std::array ao_arr{}; - - { - span s{ao_arr}; - CHECK((s.size() == narrow_cast(ao_arr.size()) && s.data() == ao_arr.data())); - } - -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); - } - - { - span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); - } - - { - span s{arr}; - } -#endif - - { - auto get_an_array = []() -> const std::array { return {1, 2, 3, 4}; }; - auto take_a_span = [](span s) { static_cast(s); }; - // try to take a temporary std::array - take_a_span(get_an_array()); - } - - { - auto s = make_span(arr); - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_std_array_const_constructor") -{ - std::array arr = {1, 2, 3, 4}; - - { - span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } - - { - span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } - -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); - } - - { - span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); - } - - { - span s{arr}; - } - - { - span s{arr}; - } -#endif - - { - auto s = make_span(arr); - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_container_constructor") -{ - std::vector v = {1, 2, 3}; - const std::vector cv = v; - - { - span s{v}; - CHECK((s.size() == narrow_cast(v.size()) && s.data() == v.data())); - - span cs{v}; - CHECK((cs.size() == narrow_cast(v.size()) && cs.data() == v.data())); - } - - std::string str = "hello"; - const std::string cstr = "hello"; - - { -#ifdef CONFIRM_COMPILATION_ERRORS - span s{str}; - CHECK((s.size() == narrow_cast(str.size()) && s.data() == str.data())); -#endif - span cs{str}; - CHECK((cs.size() == narrow_cast(str.size()) && cs.data() == str.data())); - } - - { -#ifdef CONFIRM_COMPILATION_ERRORS - span s{cstr}; -#endif - span cs{cstr}; - CHECK((cs.size() == narrow_cast(cstr.size()) && - cs.data() == cstr.data())); - } - - { -#ifdef CONFIRM_COMPILATION_ERRORS - auto get_temp_vector = []() -> std::vector { return {}; }; - auto use_span = [](span s) { static_cast(s); }; - use_span(get_temp_vector()); -#endif - } - - { - auto get_temp_vector = []() -> std::vector { return {}; }; - auto use_span = [](span s) { static_cast(s); }; - use_span(get_temp_vector()); - } - - { -#ifdef CONFIRM_COMPILATION_ERRORS - auto get_temp_string = []() -> std::string { return {}; }; - auto use_span = [](span s) { static_cast(s); }; - use_span(get_temp_string()); -#endif - } - - { - auto get_temp_string = []() -> std::string { return {}; }; - auto use_span = [](span s) { static_cast(s); }; - use_span(get_temp_string()); - } - - { -#ifdef CONFIRM_COMPILATION_ERRORS - auto get_temp_vector = []() -> const std::vector { return {}; }; - auto use_span = [](span s) { static_cast(s); }; - use_span(get_temp_vector()); -#endif - } - - { - auto get_temp_string = []() -> const std::string { return {}; }; - auto use_span = [](span s) { static_cast(s); }; - use_span(get_temp_string()); - } - - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::map m; - span s{m}; -#endif - } - - { - auto s = make_span(v); - CHECK((s.size() == narrow_cast(v.size()) && s.data() == v.data())); - - auto cs = make_span(cv); - CHECK((cs.size() == narrow_cast(cv.size()) && cs.data() == cv.data())); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("from_convertible_span_constructor") -{ - { - span avd; - span avcd = avd; - static_cast(avcd); - } - - { - #ifdef CONFIRM_COMPILATION_ERRORS - span avd; - span avb = avd; - static_cast(avb); - #endif - } - - #ifdef CONFIRM_COMPILATION_ERRORS - { - span s; - span s2 = s; - static_cast(s2); - } - - { - span s; - span s2 = s; - static_cast(s2); - } - - { - span s; - span s2 = s; - static_cast(s2); - } - #endif -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("copy_move_and_assignment") -{ - span s1; - CHECK(s1.empty()); - - int arr[] = {3, 4, 5}; - - span s2 = arr; - CHECK((s2.size() == 3 && s2.data() == &arr[0])); - - s2 = s1; - CHECK(s2.empty()); - - auto get_temp_span = [&]() -> span { return {&arr[1], 2}; }; - auto use_span = [&](span s) { CHECK((s.size() == 2 && s.data() == &arr[1])); }; - use_span(get_temp_span()); - - s1 = get_temp_span(); - CHECK((s1.size() == 2 && s1.data() == &arr[1])); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("first") -{ - int arr[5] = {1, 2, 3, 4, 5}; - - { - span av = arr; - CHECK(av.first<2>().size() == 2); - CHECK(av.first(2).size() == 2); - } - - { - span av = arr; - CHECK(av.first<0>().size() == 0); - CHECK(av.first(0).size() == 0); - } - - { - span av = arr; - CHECK(av.first<5>().size() == 5); - CHECK(av.first(5).size() == 5); - } - - { - span av = arr; -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(av.first<6>().size() == 6); - CHECK(av.first<-1>().size() == -1); -#endif - CHECK_THROWS_AS(av.first(6).size(), fail_fast); - } - - { - span av; - CHECK(av.first<0>().size() == 0); - CHECK(av.first(0).size() == 0); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("last") -{ - int arr[5] = {1, 2, 3, 4, 5}; - - { - span av = arr; - CHECK(av.last<2>().size() == 2); - CHECK(av.last(2).size() == 2); - } - - { - span av = arr; - CHECK(av.last<0>().size() == 0); - CHECK(av.last(0).size() == 0); - } - - { - span av = arr; - CHECK(av.last<5>().size() == 5); - CHECK(av.last(5).size() == 5); - } - - { - span av = arr; -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(av.last<6>().size() == 6); -#endif - CHECK_THROWS_AS(av.last(6).size(), fail_fast); - } - - { - span av; - CHECK(av.last<0>().size() == 0); - CHECK(av.last(0).size() == 0); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("subspan") -{ - int arr[5] = {1, 2, 3, 4, 5}; - - { - span av = arr; - CHECK((av.subspan<2, 2>().size() == 2)); - CHECK(decltype(av.subspan<2, 2>())::extent == 2); - CHECK(av.subspan(2, 2).size() == 2); - CHECK(av.subspan(2, 3).size() == 3); - } - - { - span av = arr; - CHECK((av.subspan<0, 0>().size() == 0)); - CHECK(decltype(av.subspan<0,0>())::extent == 0); - CHECK(av.subspan(0, 0).size() == 0); - } - - { - span av = arr; - CHECK((av.subspan<0, 5>().size() == 5)); - CHECK(decltype(av.subspan<0, 5>())::extent == 5); - CHECK(av.subspan(0, 5).size() == 5); - - CHECK_THROWS_AS(av.subspan(0, 6).size(), fail_fast); - CHECK_THROWS_AS(av.subspan(1, 5).size(), fail_fast); - } - - { - span av = arr; - CHECK((av.subspan<4, 0>().size() == 0)); - CHECK(decltype(av.subspan<4, 0>())::extent == 0); - CHECK(av.subspan(4, 0).size() == 0); - CHECK(av.subspan(5, 0).size() == 0); - CHECK_THROWS_AS(av.subspan(6, 0).size(), fail_fast); - } - - { - span av = arr; - CHECK((av.subspan<1>().size() == 4)); - CHECK(decltype(av.subspan<1>())::extent == 4); - } - - { - span av; - CHECK((av.subspan<0, 0>().size() == 0)); - CHECK((decltype(av.subspan<0, 0>())::extent == 0)); - CHECK(av.subspan(0, 0).size() == 0); - CHECK_THROWS_AS((av.subspan<1, 0>().size()), fail_fast); - } - - { - span av; - CHECK(av.subspan(0).size() == 0); - CHECK_THROWS_AS(av.subspan(1).size(), fail_fast); - } - - { - span av = arr; - CHECK(av.subspan(0).size() == 5); - CHECK(av.subspan(1).size() == 4); - CHECK(av.subspan(4).size() == 1); - CHECK(av.subspan(5).size() == 0); - CHECK_THROWS_AS(av.subspan(6).size(), fail_fast); - const auto av2 = av.subspan(1); - for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2); - } - - { - span av = arr; - CHECK(av.subspan(0).size() == 5); - CHECK(av.subspan(1).size() == 4); - CHECK(av.subspan(4).size() == 1); - CHECK(av.subspan(5).size() == 0); - CHECK_THROWS_AS(av.subspan(6).size(), fail_fast); - const auto av2 = av.subspan(1); - for (int i = 0; i < 4; ++i) CHECK(av2[i] == i + 2); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("at_call") -{ - int arr[4] = {1, 2, 3, 4}; - - { - span s = arr; - CHECK(s.at(0) == 1); - CHECK_THROWS_AS(s.at(5), fail_fast); - } - - { - int arr2d[2] = {1, 6}; - span s = arr2d; - CHECK(s.at(0) == 1); - CHECK(s.at(1) == 6); - CHECK_THROWS_AS(s.at(2), fail_fast); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("operator_function_call") -{ - int arr[4] = {1, 2, 3, 4}; - - { - span s = arr; - CHECK(s(0) == 1); - CHECK_THROWS_AS(s(5), fail_fast); - } - - { - int arr2d[2] = {1, 6}; - span s = arr2d; - CHECK(s(0) == 1); - CHECK(s(1) == 6); - CHECK_THROWS_AS(s(2), fail_fast); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("iterator_default_init") -{ - span::iterator it1; - span::iterator it2; - CHECK(it1 == it2); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("const_iterator_default_init") -{ - span::const_iterator it1; - span::const_iterator it2; - CHECK(it1 == it2); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("iterator_conversions") -{ - span::iterator badIt; - span::const_iterator badConstIt; - CHECK(badIt == badConstIt); - - int a[] = {1, 2, 3, 4}; - span s = a; - - auto it = s.begin(); - auto cit = s.cbegin(); - - CHECK(it == cit); - CHECK(cit == it); - - span::const_iterator cit2 = it; - CHECK(cit2 == cit); - - span::const_iterator cit3 = it + 4; - CHECK(cit3 == s.cend()); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("iterator_comparisons") -{ - int a[] = {1, 2, 3, 4}; - { - span s = a; - span::iterator it = s.begin(); - auto it2 = it + 1; - span::const_iterator cit = s.cbegin(); - - CHECK(it == cit); - CHECK(cit == it); - CHECK(it == it); - CHECK(cit == cit); - CHECK(cit == s.begin()); - CHECK(s.begin() == cit); - CHECK(s.cbegin() == cit); - CHECK(it == s.begin()); - CHECK(s.begin() == it); - - CHECK(it != it2); - CHECK(it2 != it); - CHECK(it != s.end()); - CHECK(it2 != s.end()); - CHECK(s.end() != it); - CHECK(it2 != cit); - CHECK(cit != it2); - - CHECK(it < it2); - CHECK(it <= it2); - CHECK(it2 <= s.end()); - CHECK(it < s.end()); - CHECK(it <= cit); - CHECK(cit <= it); - CHECK(cit < it2); - CHECK(cit <= it2); - CHECK(cit < s.end()); - CHECK(cit <= s.end()); - - CHECK(it2 > it); - CHECK(it2 >= it); - CHECK(s.end() > it2); - CHECK(s.end() >= it2); - CHECK(it2 > cit); - CHECK(it2 >= cit); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("begin_end") -{ - { - int a[] = {1, 2, 3, 4}; - span s = a; - - span::iterator it = s.begin(); - span::iterator it2 = std::begin(s); - CHECK(it == it2); - - it = s.end(); - it2 = std::end(s); - CHECK(it == it2); - } - - { - int a[] = {1, 2, 3, 4}; - span s = a; - - auto it = s.begin(); - auto first = it; - CHECK(it == first); - CHECK(*it == 1); - - auto beyond = s.end(); - CHECK(it != beyond); - CHECK_THROWS_AS(*beyond, fail_fast); - - CHECK(beyond - first == 4); - CHECK(first - first == 0); - CHECK(beyond - beyond == 0); - - ++it; - CHECK(it - first == 1); - CHECK(*it == 2); - *it = 22; - CHECK(*it == 22); - CHECK(beyond - it == 3); - - it = first; - CHECK(it == first); - while (it != s.end()) { - *it = 5; - ++it; - } - - CHECK(it == beyond); - CHECK(it - beyond == 0); - - for (const auto& n : s) { - CHECK(n == 5); - } - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("cbegin_cend") -{ - { - int a[] = {1, 2, 3, 4}; - span s = a; - - span::const_iterator cit = s.cbegin(); - span::const_iterator cit2 = std::cbegin(s); - CHECK(cit == cit2); - - cit = s.cend(); - cit2 = std::cend(s); - CHECK(cit == cit2); - } - - { - int a[] = {1, 2, 3, 4}; - span s = a; - - auto it = s.cbegin(); - auto first = it; - CHECK(it == first); - CHECK(*it == 1); - - auto beyond = s.cend(); - CHECK(it != beyond); - CHECK_THROWS_AS(*beyond, fail_fast); - - CHECK(beyond - first == 4); - CHECK(first - first == 0); - CHECK(beyond - beyond == 0); - - ++it; - CHECK(it - first == 1); - CHECK(*it == 2); - CHECK(beyond - it == 3); - - int last = 0; - it = first; - CHECK(it == first); - while (it != s.cend()) { - CHECK(*it == last + 1); - - last = *it; - ++it; - } - - CHECK(it == beyond); - CHECK(it - beyond == 0); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("rbegin_rend") -{ - { - int a[] = {1, 2, 3, 4}; - span s = a; - - auto it = s.rbegin(); - auto first = it; - CHECK(it == first); - CHECK(*it == 4); - - auto beyond = s.rend(); - CHECK(it != beyond); - CHECK_THROWS_AS(*beyond, fail_fast); - - CHECK(beyond - first == 4); - CHECK(first - first == 0); - CHECK(beyond - beyond == 0); - - ++it; - CHECK(it - first == 1); - CHECK(*it == 3); - *it = 22; - CHECK(*it == 22); - CHECK(beyond - it == 3); - - it = first; - CHECK(it == first); - while (it != s.rend()) { - *it = 5; - ++it; - } - - CHECK(it == beyond); - CHECK(it - beyond == 0); - - for (const auto& n : s) { - CHECK(n == 5); - } - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("crbegin_crend") -{ - { - int a[] = {1, 2, 3, 4}; - span s = a; - - auto it = s.crbegin(); - auto first = it; - CHECK(it == first); - CHECK(*it == 4); - - auto beyond = s.crend(); - CHECK(it != beyond); - CHECK_THROWS_AS(*beyond, fail_fast); - - CHECK(beyond - first == 4); - CHECK(first - first == 0); - CHECK(beyond - beyond == 0); - - ++it; - CHECK(it - first == 1); - CHECK(*it == 3); - CHECK(beyond - it == 3); - - it = first; - CHECK(it == first); - int last = 5; - while (it != s.crend()) { - CHECK(*it == last - 1); - last = *it; - - ++it; - } - - CHECK(it == beyond); - CHECK(it - beyond == 0); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("comparison_operators") -{ - { - span s1; - span s2; - CHECK(s1 == s2); - CHECK(!(s1 != s2)); - CHECK(!(s1 < s2)); - CHECK(s1 <= s2); - CHECK(!(s1 > s2)); - CHECK(s1 >= s2); - CHECK(s2 == s1); - CHECK(!(s2 != s1)); - CHECK(!(s2 < s1)); - CHECK(s2 <= s1); - CHECK(!(s2 > s1)); - CHECK(s2 >= s1); - } - - { - int arr[] = {2, 1}; - span s1 = arr; - span s2 = arr; - - CHECK(s1 == s2); - CHECK(!(s1 != s2)); - CHECK(!(s1 < s2)); - CHECK(s1 <= s2); - CHECK(!(s1 > s2)); - CHECK(s1 >= s2); - CHECK(s2 == s1); - CHECK(!(s2 != s1)); - CHECK(!(s2 < s1)); - CHECK(s2 <= s1); - CHECK(!(s2 > s1)); - CHECK(s2 >= s1); - } - - { - int arr[] = {2, 1}; // bigger - - span s1; - span s2 = arr; - - CHECK(s1 != s2); - CHECK(s2 != s1); - CHECK(!(s1 == s2)); - CHECK(!(s2 == s1)); - CHECK(s1 < s2); - CHECK(!(s2 < s1)); - CHECK(s1 <= s2); - CHECK(!(s2 <= s1)); - CHECK(s2 > s1); - CHECK(!(s1 > s2)); - CHECK(s2 >= s1); - CHECK(!(s1 >= s2)); - } - - { - int arr1[] = {1, 2}; - int arr2[] = {1, 2}; - span s1 = arr1; - span s2 = arr2; - - CHECK(s1 == s2); - CHECK(!(s1 != s2)); - CHECK(!(s1 < s2)); - CHECK(s1 <= s2); - CHECK(!(s1 > s2)); - CHECK(s1 >= s2); - CHECK(s2 == s1); - CHECK(!(s2 != s1)); - CHECK(!(s2 < s1)); - CHECK(s2 <= s1); - CHECK(!(s2 > s1)); - CHECK(s2 >= s1); - } - - { - int arr[] = {1, 2, 3}; - - span s1 = {&arr[0], 2}; // shorter - span s2 = arr; // longer - - CHECK(s1 != s2); - CHECK(s2 != s1); - CHECK(!(s1 == s2)); - CHECK(!(s2 == s1)); - CHECK(s1 < s2); - CHECK(!(s2 < s1)); - CHECK(s1 <= s2); - CHECK(!(s2 <= s1)); - CHECK(s2 > s1); - CHECK(!(s1 > s2)); - CHECK(s2 >= s1); - CHECK(!(s1 >= s2)); - } - - { - int arr1[] = {1, 2}; // smaller - int arr2[] = {2, 1}; // bigger - - span s1 = arr1; - span s2 = arr2; - - CHECK(s1 != s2); - CHECK(s2 != s1); - CHECK(!(s1 == s2)); - CHECK(!(s2 == s1)); - CHECK(s1 < s2); - CHECK(!(s2 < s1)); - CHECK(s1 <= s2); - CHECK(!(s2 <= s1)); - CHECK(s2 > s1); - CHECK(!(s1 > s2)); - CHECK(s2 >= s1); - CHECK(!(s1 >= s2)); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("as_bytes") -{ - int a[] = {1, 2, 3, 4}; - - { - const span s = a; - CHECK(s.size() == 4); - const span bs = as_bytes(s); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.size() == s.size_bytes()); - } - - { - span s; - const auto bs = as_bytes(s); - CHECK(bs.size() == s.size()); - CHECK(bs.size() == 0); - CHECK(bs.size_bytes() == 0); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.data() == nullptr); - } - - { - span s = a; - const auto bs = as_bytes(s); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.size() == s.size_bytes()); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("as_writeable_bytes") -{ - int a[] = {1, 2, 3, 4}; - - { -#ifdef CONFIRM_COMPILATION_ERRORS - // you should not be able to get writeable bytes for const objects - span s = a; - CHECK(s.size() == 4); - span bs = as_writeable_bytes(s); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.size() == s.size_bytes()); -#endif - } - - { - span s; - const auto bs = as_writeable_bytes(s); - CHECK(bs.size() == s.size()); - CHECK(bs.size() == 0); - CHECK(bs.size_bytes() == 0); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.data() == nullptr); - } - - { - span s = a; - const auto bs = as_writeable_bytes(s); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.size() == s.size_bytes()); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("fixed_size_conversions") -{ - int arr[] = {1, 2, 3, 4}; - - // converting to an span from an equal size array is ok - span s4 = arr; - CHECK(s4.size() == 4); - - // converting to dynamic_range is always ok - { - span s = s4; - CHECK(s.size() == s4.size()); - static_cast(s); - } - -// initialization or assignment to static span that REDUCES size is NOT ok -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s = arr; - } - { - span s2 = s4; - static_cast(s2); - } -#endif - - // even when done dynamically - { - span s = arr; - auto f = [&]() { - const span s2 = s; - static_cast(s2); - }; - CHECK_THROWS_AS(f(), fail_fast); - } - - // but doing so explicitly is ok - - // you can convert statically - { - const span s2 = {&arr[0], 2}; - static_cast(s2); - } - { - const span s1 = s4.first<1>(); - static_cast(s1); - } - - // ...or dynamically - { - // NB: implicit conversion to span from span - span s1 = s4.first(1); - static_cast(s1); - } - - // initialization or assignment to static span that requires size INCREASE is not ok. - int arr2[2] = {1, 2}; - -#ifdef CONFIRM_COMPILATION_ERRORS - { - span s3 = arr2; - } - { - span s2 = arr2; - span s4a = s2; - } -#endif - { - auto f = [&]() { - const span _s4 = {arr2, 2}; - static_cast(_s4); - }; - CHECK_THROWS_AS(f(), fail_fast); - } - - // this should fail - we are trying to assign a small dynamic span to a fixed_size larger one - span av = arr2; - auto f = [&]() { - const span _s4 = av; - static_cast(_s4); - }; - CHECK_THROWS_AS(f(), fail_fast); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("interop_with_std_regex") -{ - char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'}; - span s = lat; - const auto f_it = s.begin() + 7; - - std::match_results::iterator> match; - - std::regex_match(s.begin(), s.end(), match, std::regex(".*")); - CHECK(match.ready()); - CHECK(!match.empty()); - CHECK(match[0].matched); - CHECK(match[0].first == s.begin()); - CHECK(match[0].second == s.end()); - - std::regex_search(s.begin(), s.end(), match, std::regex("F")); - CHECK(match.ready()); - CHECK(!match.empty()); - CHECK(match[0].matched); - CHECK(match[0].first == f_it); - CHECK(match[0].second == (f_it + 1)); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("interop_with_gsl_at") -{ - int arr[5] = {1, 2, 3, 4, 5}; - span s{arr}; - CHECK((at(s, 0) == 1 && at(s, 1) == 2)); -} - -TEST_CASE("default_constructible") -{ - CHECK((std::is_default_constructible>::value)); - CHECK((std::is_default_constructible>::value)); - CHECK((!std::is_default_constructible>::value)); -} - +TEST(span_test, from_array_constructor) + { + int arr[5] = {1, 2, 3, 4, 5}; + + { + const span s{arr}; + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + const span s{arr}; + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == &arr[0]); + } + + int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + span s{arr2d}; + EXPECT_TRUE(s.size() == 6); + EXPECT_TRUE(s.data() == &arr2d[0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); + } + + { + span s{arr2d}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr2d[0][0]); + } + + { + span s{arr2d}; + } + #endif + { + const span s{std::addressof(arr2d[0]), 1}; + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); + } + + int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr3d}; + EXPECT_TRUE(s.size() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[11] == 12); + } + + { + span s{arr3d}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + } + + { + span s{arr3d}; + } + + { + span s{arr3d}; + EXPECT_TRUE(s.size() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); + } + #endif + { + const span s{std::addressof(arr3d[0]), 1}; + EXPECT_TRUE(s.size() == 1); + } + + { + const auto s = make_span(arr); + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == std::addressof(arr[0])); + } + + { + const auto s = make_span(std::addressof(arr2d[0]), 1); + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); + } + + { + const auto s = make_span(std::addressof(arr3d[0]), 1); + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr3d[0])); + } + + AddressOverloaded ao_arr[5] = {}; + + { + const span s{ao_arr}; + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == std::addressof(ao_arr[0])); + } + } + + TEST(span_test, from_dynamic_array_constructor) + { + double(*arr)[3][4] = new double[100][3][4]; + + { + span s(&arr[0][0][0], 10); + EXPECT_TRUE(s.size() == 10); + EXPECT_TRUE(s.data() == &arr[0][0][0]); + } + + { + auto s = make_span(&arr[0][0][0], 10); + EXPECT_TRUE(s.size() == 10); + EXPECT_TRUE(s.data() == &arr[0][0][0]); + } + + delete[] arr; + } + + TEST(span_test, from_std_array_constructor) + { + std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == narrow_cast(arr.size())); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == narrow_cast(arr.size())); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + std::array empty_arr{}; + span s{empty_arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.empty()); + } + + std::array ao_arr{}; + + { + span fs{ao_arr}; + EXPECT_TRUE(fs.size() == narrow_cast(ao_arr.size())); + EXPECT_TRUE(ao_arr.data() == fs.data()); + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == 2); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + span s{arr}; + } + + { + auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; + auto take_a_span = [](span s) { static_cast(s); }; + // try to take a temporary std::array + take_a_span(get_an_array()); + } + #endif + + { + auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; + auto take_a_span = [](span s) { static_cast(s); }; + // try to take a temporary std::array + take_a_span(get_an_array()); + } + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + + // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590 + { + span s1 = make_span(arr); + + static span s2; + s2 = s1; + + #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \ + __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__) + // Known to be broken in gcc 6.4 and 6.5 with optimizations + // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 + EXPECT_TRUE(s1.size() == 4); + EXPECT_TRUE(s2.size() == 0); + #else + EXPECT_TRUE(s1.size() == s2.size()); + #endif + } + } + + TEST(span_test, from_const_std_array_constructor) + { + const std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + + const std::array ao_arr{}; + + { + span s{ao_arr}; + EXPECT_TRUE(s.size() == narrow_cast(ao_arr.size())); + EXPECT_TRUE(s.data() == ao_arr.data()); + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + } + #endif + + { + auto get_an_array = []() -> const std::array { return {1, 2, 3, 4}; }; + auto take_a_span = [](span s) { static_cast(s); }; + // try to take a temporary std::array + take_a_span(get_an_array()); + } + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + } + + TEST(span_test, from_std_array_const_constructor) + { + std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + } + + { + span s{arr}; + } + #endif + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == narrow_cast(arr.size())); + EXPECT_TRUE(s.data() == arr.data()); + } + } + + TEST(span_test, from_container_constructor) + { + std::vector v = {1, 2, 3}; + const std::vector cv = v; + + { + span s{v}; + EXPECT_TRUE(s.size() == narrow_cast(v.size())); + EXPECT_TRUE(s.data() == v.data()); + + span cs{v}; + EXPECT_TRUE(cs.size() == narrow_cast(v.size())); + EXPECT_TRUE(cs.data() == v.data()); + } + + std::string str = "hello"; + const std::string cstr = "hello"; + + { + #ifdef CONFIRM_COMPILATION_ERRORS + span s{str}; + EXPECT_TRUE(s.size() == narrow_cast(str.size())); + EXPECT_TRUE(s.data() == str.data())); + #endif + span cs{str}; + EXPECT_TRUE(cs.size() == narrow_cast(str.size())); + EXPECT_TRUE(cs.data() == str.data()); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + span s{cstr}; + #endif + span cs{cstr}; + EXPECT_TRUE(cs.size() == narrow_cast(cstr.size())); + EXPECT_TRUE(cs.data() == cstr.data()); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + auto get_temp_vector = []() -> std::vector { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_vector()); + #endif + } + + { + auto get_temp_vector = []() -> std::vector { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_vector()); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + auto get_temp_string = []() -> std::string { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_string()); + #endif + } + + { + auto get_temp_string = []() -> std::string { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_string()); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + auto get_temp_vector = []() -> const std::vector { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_vector()); + #endif + } + + { + auto get_temp_string = []() -> const std::string { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_string()); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + std::map m; + span s{m}; + #endif + } + + { + auto s = make_span(v); + EXPECT_TRUE(s.size() == narrow_cast(v.size())); + EXPECT_TRUE(s.data() == v.data()); + + auto cs = make_span(cv); + EXPECT_TRUE(cs.size() == narrow_cast(cv.size())); + EXPECT_TRUE(cs.data() == cv.data()); + } + } + + TEST(span_test, from_convertible_span_constructor){{span avd; + span avcd = avd; + static_cast(avcd); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + span avd; + span avb = avd; + static_cast(avb); + #endif + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s; + span s2 = s; + static_cast(s2); + } + + { + span s; + span s2 = s; + static_cast(s2); + } + + { + span s; + span s2 = s; + static_cast(s2); + } + #endif + } + + TEST(span_test, copy_move_and_assignment) + { + span s1; + EXPECT_TRUE(s1.empty()); + + int arr[] = {3, 4, 5}; + + span s2 = arr; + EXPECT_TRUE(s2.size() == 3); + EXPECT_TRUE(s2.data() == &arr[0]); + + s2 = s1; + EXPECT_TRUE(s2.empty()); + + auto get_temp_span = [&]() -> span { return {&arr[1], 2}; }; + auto use_span = [&](span s) { + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[1]); + }; use_span(get_temp_span()); + + s1 = get_temp_span(); + EXPECT_TRUE(s1.size() == 2); + EXPECT_TRUE(s1.data() == &arr[1]); + } + + TEST(span_test, first) + { + std::set_terminate([] { + std::cerr << "Expected Death. first"; + std::abort(); + }); + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_TRUE(av.first<2>().size() == 2); + EXPECT_TRUE(av.first(2).size() == 2); + } + + { + span av = arr; + EXPECT_TRUE(av.first<0>().size() == 0); + EXPECT_TRUE(av.first(0).size() == 0); + } + + { + span av = arr; + EXPECT_TRUE(av.first<5>().size() == 5); + EXPECT_TRUE(av.first(5).size() == 5); + } + + { + span av = arr; + #ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(av.first<6>().size() == 6); + EXPECT_TRUE(av.first<-1>().size() == -1); + #endif + EXPECT_DEATH(av.first(6).size(), deathstring); + } + + { + span av; + EXPECT_TRUE(av.first<0>().size() == 0); + EXPECT_TRUE(av.first(0).size() == 0); + } + } + + TEST(span_test, last) + { + std::set_terminate([] { + std::cerr << "Expected Death. last"; + std::abort(); + }); + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_TRUE(av.last<2>().size() == 2); + EXPECT_TRUE(av.last(2).size() == 2); + } + + { + span av = arr; + EXPECT_TRUE(av.last<0>().size() == 0); + EXPECT_TRUE(av.last(0).size() == 0); + } + + { + span av = arr; + EXPECT_TRUE(av.last<5>().size() == 5); + EXPECT_TRUE(av.last(5).size() == 5); + } + + { + span av = arr; + #ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(av.last<6>().size() == 6); + #endif + EXPECT_DEATH(av.last(6).size(), deathstring); + } + + { + span av; + EXPECT_TRUE(av.last<0>().size() == 0); + EXPECT_TRUE(av.last(0).size() == 0); + } + } + + TEST(span_test, subspan) + { + std::set_terminate([] { + std::cerr << "Expected Death. subspan"; + std::abort(); + }); + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_TRUE((av.subspan<2, 2>().size()) == 2); + EXPECT_TRUE(decltype(av.subspan<2, 2>())::extent == 2); + EXPECT_TRUE(av.subspan(2, 2).size() == 2); + EXPECT_TRUE(av.subspan(2, 3).size() == 3); + } + + { + span av = arr; + EXPECT_TRUE((av.subspan<0, 0>().size()) == 0); + EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0); + EXPECT_TRUE(av.subspan(0, 0).size() == 0); + } + + { + span av = arr; + EXPECT_TRUE((av.subspan<0, 5>().size()) == 5); + EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5); + EXPECT_TRUE(av.subspan(0, 5).size() == 5); + + EXPECT_DEATH(av.subspan(0, 6).size(), deathstring); + EXPECT_DEATH(av.subspan(1, 5).size(), deathstring); + } + + { + span av = arr; + EXPECT_TRUE((av.subspan<4, 0>().size()) == 0); + EXPECT_TRUE(decltype(av.subspan<4, 0>())::extent == 0); + EXPECT_TRUE(av.subspan(4, 0).size() == 0); + EXPECT_TRUE(av.subspan(5, 0).size() == 0); + EXPECT_DEATH(av.subspan(6, 0).size(), deathstring); + } + + { + span av = arr; + EXPECT_TRUE(av.subspan<1>().size() == 4); + EXPECT_TRUE(decltype(av.subspan<1>())::extent == 4); + } + + { + span av; + EXPECT_TRUE((av.subspan<0, 0>().size()) == 0); + EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0); + EXPECT_TRUE(av.subspan(0, 0).size() == 0); + EXPECT_DEATH((av.subspan<1, 0>().size()), deathstring); + } + + { + span av; + EXPECT_TRUE(av.subspan(0).size() == 0); + EXPECT_DEATH(av.subspan(1).size(), deathstring); + } + + { + span av = arr; + EXPECT_TRUE(av.subspan(0).size() == 5); + EXPECT_TRUE(av.subspan(1).size() == 4); + EXPECT_TRUE(av.subspan(4).size() == 1); + EXPECT_TRUE(av.subspan(5).size() == 0); + EXPECT_DEATH(av.subspan(6).size(), deathstring); + const auto av2 = av.subspan(1); + for (int i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); + } + + { + span av = arr; + EXPECT_TRUE(av.subspan(0).size() == 5); + EXPECT_TRUE(av.subspan(1).size() == 4); + EXPECT_TRUE(av.subspan(4).size() == 1); + EXPECT_TRUE(av.subspan(5).size() == 0); + EXPECT_DEATH(av.subspan(6).size(), deathstring); + const auto av2 = av.subspan(1); + for (int i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == i + 2); + } + } + + TEST(span_test, at_call) + { + std::set_terminate([] { + std::cerr << "Expected Death. at_call"; + std::abort(); + }); + int arr[4] = {1, 2, 3, 4}; + + { + span s = arr; + EXPECT_TRUE(s.at(0) == 1); + EXPECT_DEATH(s.at(5), deathstring); + } + + { + int arr2d[2] = {1, 6}; + span s = arr2d; + EXPECT_TRUE(s.at(0) == 1); + EXPECT_TRUE(s.at(1) == 6); + EXPECT_DEATH(s.at(2), deathstring); + } + } + + TEST(span_test, operator_function_call) + { + std::set_terminate([] { + std::cerr << "Expected Death. operator_function_call"; + std::abort(); + }); + int arr[4] = {1, 2, 3, 4}; + + { + span s = arr; + EXPECT_TRUE(s(0) == 1); + EXPECT_DEATH(s(5), deathstring); + } + + { + int arr2d[2] = {1, 6}; + span s = arr2d; + EXPECT_TRUE(s(0) == 1); + EXPECT_TRUE(s(1) == 6); + EXPECT_DEATH(s(2), deathstring); + } + } + + TEST(span_test, iterator_default_init) + { + span::iterator it1; + span::iterator it2; + EXPECT_TRUE(it1 == it2); + } + + TEST(span_test, const_iterator_default_init) + { + span::const_iterator it1; + span::const_iterator it2; + EXPECT_TRUE(it1 == it2); + } + + TEST(span_test, iterator_conversions) + { + span::iterator badIt; + span::const_iterator badConstIt; + EXPECT_TRUE(badIt == badConstIt); + + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.begin(); + auto cit = s.cbegin(); + + EXPECT_TRUE(it == cit); + EXPECT_TRUE(cit == it); + + span::const_iterator cit2 = it; + EXPECT_TRUE(cit2 == cit); + + span::const_iterator cit3 = it + 4; + EXPECT_TRUE(cit3 == s.cend()); + } + + TEST(span_test, iterator_comparisons) + { + int a[] = {1, 2, 3, 4}; + { + span s = a; + span::iterator it = s.begin(); + auto it2 = it + 1; + span::const_iterator cit = s.cbegin(); + + EXPECT_TRUE(it == cit); + EXPECT_TRUE(cit == it); + EXPECT_TRUE(it == it); + EXPECT_TRUE(cit == cit); + EXPECT_TRUE(cit == s.begin()); + EXPECT_TRUE(s.begin() == cit); + EXPECT_TRUE(s.cbegin() == cit); + EXPECT_TRUE(it == s.begin()); + EXPECT_TRUE(s.begin() == it); + + EXPECT_TRUE(it != it2); + EXPECT_TRUE(it2 != it); + EXPECT_TRUE(it != s.end()); + EXPECT_TRUE(it2 != s.end()); + EXPECT_TRUE(s.end() != it); + EXPECT_TRUE(it2 != cit); + EXPECT_TRUE(cit != it2); + + EXPECT_TRUE(it < it2); + EXPECT_TRUE(it <= it2); + EXPECT_TRUE(it2 <= s.end()); + EXPECT_TRUE(it < s.end()); + EXPECT_TRUE(it <= cit); + EXPECT_TRUE(cit <= it); + EXPECT_TRUE(cit < it2); + EXPECT_TRUE(cit <= it2); + EXPECT_TRUE(cit < s.end()); + EXPECT_TRUE(cit <= s.end()); + + EXPECT_TRUE(it2 > it); + EXPECT_TRUE(it2 >= it); + EXPECT_TRUE(s.end() > it2); + EXPECT_TRUE(s.end() >= it2); + EXPECT_TRUE(it2 > cit); + EXPECT_TRUE(it2 >= cit); + } + } + + TEST(span_test, begin_end) + { + std::set_terminate([] { + std::cerr << "Expected Death. begin_end"; + std::abort(); + }); + { + int a[] = {1, 2, 3, 4}; + span s = a; + + span::iterator it = s.begin(); + span::iterator it2 = std::begin(s); + EXPECT_TRUE(it == it2); + + it = s.end(); + it2 = std::end(s); + EXPECT_TRUE(it == it2); + } + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.begin(); + auto first = it; + EXPECT_TRUE(it == first); + EXPECT_TRUE(*it == 1); + + auto beyond = s.end(); + EXPECT_TRUE(it != beyond); + EXPECT_DEATH(*beyond, deathstring); + + EXPECT_TRUE(beyond - first == 4); + EXPECT_TRUE(first - first == 0); + EXPECT_TRUE(beyond - beyond == 0); + + ++it; + EXPECT_TRUE(it - first == 1); + EXPECT_TRUE(*it == 2); + *it = 22; + EXPECT_TRUE(*it == 22); + EXPECT_TRUE(beyond - it == 3); + + it = first; + EXPECT_TRUE(it == first); + while (it != s.end()) + { + *it = 5; + ++it; + } + + EXPECT_TRUE(it == beyond); + EXPECT_TRUE(it - beyond == 0); + + for (const auto& n : s) { EXPECT_TRUE(n == 5); } + } + } + + TEST(span_test, cbegin_cend) + { + std::set_terminate([] { + std::cerr << "Expected Death. cbegin_cend"; + std::abort(); + }); + { + int a[] = {1, 2, 3, 4}; + span s = a; + + span::const_iterator cit = s.cbegin(); + span::const_iterator cit2 = std::cbegin(s); + EXPECT_TRUE(cit == cit2); + + cit = s.cend(); + cit2 = std::cend(s); + EXPECT_TRUE(cit == cit2); + } + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.cbegin(); + auto first = it; + EXPECT_TRUE(it == first); + EXPECT_TRUE(*it == 1); + + auto beyond = s.cend(); + EXPECT_TRUE(it != beyond); + EXPECT_DEATH(*beyond, deathstring); + + EXPECT_TRUE(beyond - first == 4); + EXPECT_TRUE(first - first == 0); + EXPECT_TRUE(beyond - beyond == 0); + + ++it; + EXPECT_TRUE(it - first == 1); + EXPECT_TRUE(*it == 2); + EXPECT_TRUE(beyond - it == 3); + + int last = 0; + it = first; + EXPECT_TRUE(it == first); + while (it != s.cend()) + { + EXPECT_TRUE(*it == last + 1); + + last = *it; + ++it; + } + + EXPECT_TRUE(it == beyond); + EXPECT_TRUE(it - beyond == 0); + } + } + + TEST(span_test, rbegin_rend) + { + std::set_terminate([] { + std::cerr << "Expected Death. rbegin_rend"; + std::abort(); + }); + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.rbegin(); + auto first = it; + EXPECT_TRUE(it == first); + EXPECT_TRUE(*it == 4); + + auto beyond = s.rend(); + EXPECT_TRUE(it != beyond); + EXPECT_DEATH(auto _ = *beyond , deathstring); + + EXPECT_TRUE(beyond - first == 4); + EXPECT_TRUE(first - first == 0); + EXPECT_TRUE(beyond - beyond == 0); + + ++it; + EXPECT_TRUE(it - s.rbegin() == 1); + EXPECT_TRUE(*it == 3); + *it = 22; + EXPECT_TRUE(*it == 22); + EXPECT_TRUE(beyond - it == 3); + + it = first; + EXPECT_TRUE(it == first); + while (it != s.rend()) + { + *it = 5; + ++it; + } + + EXPECT_TRUE(it == beyond); + EXPECT_TRUE(it - beyond == 0); + + for (const auto& n : s) { EXPECT_TRUE(n == 5); } + } + } + + TEST(span_test, crbegin_crend) + { + std::set_terminate([] { + std::cerr << "Expected Death. crbegin_crend"; + std::abort(); + }); + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.crbegin(); + auto first = it; + EXPECT_TRUE(it == first); + EXPECT_TRUE(*it == 4); + + auto beyond = s.crend(); + EXPECT_TRUE(it != beyond); + EXPECT_DEATH(auto _ = *beyond, deathstring); + + EXPECT_TRUE(beyond - first == 4); + EXPECT_TRUE(first - first == 0); + EXPECT_TRUE(beyond - beyond == 0); + + std::cout << *first << std::endl; + ++it; + EXPECT_TRUE(it - s.crbegin() == 1); + EXPECT_TRUE(*it == 3); + EXPECT_TRUE(beyond - it == 3); + + it = first; + EXPECT_TRUE(it == first); + int last = 5; + while (it != s.crend()) + { + EXPECT_TRUE(*it == last - 1); + last = *it; + + ++it; + } + + EXPECT_TRUE(it == beyond); + EXPECT_TRUE(it - beyond == 0); + } + } + + TEST(span_test, comparison_operators) + { + { + span s1; + span s2; + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 != s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {2, 1}; + span s1 = arr; + span s2 = arr; + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {2, 1}; // bigger + + span s1; + span s2 = arr; + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; + int arr2[] = {1, 2}; + span s1 = arr1; + span s2 = arr2; + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {1, 2, 3}; + + span s1 = {&arr[0], 2}; // shorter + span s2 = arr; // longer + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; // smaller + int arr2[] = {2, 1}; // bigger + + span s1 = arr1; + span s2 = arr2; + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + } + + TEST(span_test, as_bytes) + { + int a[] = {1, 2, 3, 4}; + + { + const span s = a; + EXPECT_TRUE(s.size() == 4); + const span bs = as_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + } + + { + span s; + const auto bs = as_bytes(s); + EXPECT_TRUE(bs.size() == s.size()); + EXPECT_TRUE(bs.size() == 0); + EXPECT_TRUE(bs.size_bytes() == 0); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.data() == nullptr); + } + + { + span s = a; + const auto bs = as_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + } + } + + TEST(span_test, as_writeable_bytes) + { + int a[] = {1, 2, 3, 4}; + + { + #ifdef CONFIRM_COMPILATION_ERRORS + // you should not be able to get writeable bytes for const objects + span s = a; + EXPECT_TRUE(s.size() == 4); + span bs = as_writeable_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + #endif + } + + { + span s; + const auto bs = as_writeable_bytes(s); + EXPECT_TRUE(bs.size() == s.size()); + EXPECT_TRUE(bs.size() == 0); + EXPECT_TRUE(bs.size_bytes() == 0); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.data() == nullptr); + } + + { + span s = a; + const auto bs = as_writeable_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + } + } + + TEST(span_test, fixed_size_conversions) + { + std::set_terminate([] { + std::cerr << "Expected Death. fixed_size_conversions"; + std::abort(); + }); + int arr[] = {1, 2, 3, 4}; + + // converting to an span from an equal size array is ok + span s4 = arr; + EXPECT_TRUE(s4.size() == 4); + + // converting to dynamic_range is always ok + { + span s = s4; + EXPECT_TRUE(s.size() == s4.size()); + static_cast(s); + } + + // initialization or assignment to static span that REDUCES size is NOT ok + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s = arr; + } + { + span s2 = s4; + static_cast(s2); + } + #endif + + // even when done dynamically + { + span s = arr; + auto f = [&]() { + const span s2 = s; + static_cast(s2); + }; + EXPECT_DEATH(f(), deathstring); + } + + // but doing so explicitly is ok + + // you can convert statically + { + const span s2 = {&arr[0], 2}; + static_cast(s2); + } + { + const span s1 = s4.first<1>(); + static_cast(s1); + } + + // ...or dynamically + { + // NB: implicit conversion to span from span + span s1 = s4.first(1); + static_cast(s1); + } + + // initialization or assignment to static span that requires size INCREASE is not ok. + int arr2[2] = {1, 2}; + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s3 = arr2; + } + { + span s2 = arr2; + span s4a = s2; + } + #endif + { + auto f = [&]() { + const span _s4 = {arr2, 2}; + static_cast(_s4); + }; + EXPECT_DEATH(f(), deathstring); + } + + // this should fail - we are trying to assign a small dynamic span to a fixed_size larger one + span av = arr2; auto f = [&]() { + const span _s4 = av; + static_cast(_s4); + }; + EXPECT_DEATH(f(), deathstring); + } + + TEST(span_test, interop_with_std_regex) + { + char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'}; + span s = lat; + const auto f_it = s.begin() + 7; + + std::match_results::iterator> match; + + std::regex_match(s.begin(), s.end(), match, std::regex(".*")); + EXPECT_TRUE(match.ready()); + EXPECT_FALSE(match.empty()); + EXPECT_TRUE(match[0].matched); + EXPECT_TRUE(match[0].first == s.begin()); + EXPECT_TRUE(match[0].second == s.end()); + + std::regex_search(s.begin(), s.end(), match, std::regex("F")); + EXPECT_TRUE(match.ready()); + EXPECT_FALSE(match.empty()); + EXPECT_TRUE(match[0].matched); + EXPECT_TRUE(match[0].first == f_it); + EXPECT_TRUE(match[0].second == (f_it + 1)); + } + + TEST(span_test, interop_with_gsl_at) + { + int arr[5] = {1, 2, 3, 4, 5}; + span s{arr}; + EXPECT_TRUE(at(s, 0) == 1); + EXPECT_TRUE(at(s, 1) == 2); + } + + TEST(span_test, default_constructible) + { + EXPECT_TRUE((std::is_default_constructible>::value)); + EXPECT_TRUE((std::is_default_constructible>::value)); + EXPECT_FALSE((std::is_default_constructible>::value)); + } + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index 055afec..a8d438a 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -23,7 +23,19 @@ #pragma warning(disable : 4702) // unreachable code #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for not_null, operator<, operator<=, operator> namespace gsl @@ -35,19 +47,20 @@ using namespace gsl; GSL_SUPPRESS(f.4) // NO-FORMAT: attribute bool helper(not_null p) { return *p == 12; } + GSL_SUPPRESS(f.4) // NO-FORMAT: attribute bool helper_const(not_null p) { return *p == 12; } GSL_SUPPRESS(f.4) // NO-FORMAT: attribute bool strict_helper(strict_not_null p) { return *p == 12; } + GSL_SUPPRESS(f.4) // NO-FORMAT: attribute bool strict_helper_const(strict_not_null p) { return *p == 12; } int* return_pointer() { return nullptr; } const int* return_pointer_const() { return nullptr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestStrictNotNull") +TEST(strict_notnull_tests, TestStrictNotNull) { { // raw ptr <-> strict_not_null @@ -66,7 +79,7 @@ TEST_CASE("TestStrictNotNull") helper(snn1); helper_const(snn1); - CHECK(*snn1 == 42); + EXPECT_TRUE(*snn1 == 42); } { @@ -80,7 +93,7 @@ TEST_CASE("TestStrictNotNull") strict_helper_const(snn1); strict_helper_const(snn2); - CHECK(snn1 == snn2); + EXPECT_TRUE(snn1 == snn2); } { @@ -95,8 +108,8 @@ TEST_CASE("TestStrictNotNull") helper(snn); helper_const(snn); - CHECK(snn == nn1); - CHECK(snn == nn2); + EXPECT_TRUE(snn == nn1); + EXPECT_TRUE(snn == nn2); } { @@ -111,16 +124,16 @@ TEST_CASE("TestStrictNotNull") strict_helper(nn); strict_helper_const(nn); - CHECK(snn1 == nn); - CHECK(snn2 == nn); + EXPECT_TRUE(snn1 == nn); + EXPECT_TRUE(snn2 == nn); std::hash> hash_snn; std::hash> hash_nn; - CHECK(hash_nn(snn1) == hash_nn(nn)); - CHECK(hash_snn(snn1) == hash_nn(nn)); - CHECK(hash_nn(snn1) == hash_nn(snn2)); - CHECK(hash_snn(snn1) == hash_snn(nn)); + EXPECT_TRUE(hash_nn(snn1) == hash_nn(nn)); + EXPECT_TRUE(hash_snn(snn1) == hash_nn(nn)); + EXPECT_TRUE(hash_nn(snn1) == hash_nn(snn2)); + EXPECT_TRUE(hash_snn(snn1) == hash_snn(nn)); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -131,10 +144,18 @@ TEST_CASE("TestStrictNotNull") } #if defined(__cplusplus) && (__cplusplus >= 201703L) - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestStrictNotNullConstructorTypeDeduction") +namespace { +static constexpr char deathstring[] = "Expected Death"; +} + +TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) +{ + std::set_terminate([] { + std::cerr << "Expected Death. TestStrictNotNullConstructorTypeDeduction"; + std::abort(); + }); + { int i = 42; @@ -142,7 +163,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") helper(strict_not_null{&i}); helper_const(strict_not_null{&i}); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -153,7 +174,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") helper(strict_not_null{p}); helper_const(strict_not_null{p}); - CHECK(*x == 42); + EXPECT_TRUE(*x == 42); } { @@ -161,7 +182,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") int* p1 = nullptr; const strict_not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { @@ -169,14 +190,14 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") const int* p1 = nullptr; const strict_not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } { int* p = nullptr; - CHECK_THROWS_AS(helper(strict_not_null{p}), fail_fast); - CHECK_THROWS_AS(helper_const(strict_not_null{p}), fail_fast); + EXPECT_DEATH(helper(strict_not_null{p}), deathstring); + EXPECT_DEATH(helper_const(strict_not_null{p}), deathstring); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -191,3 +212,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") static_assert(std::is_nothrow_move_constructible>::value, "strict_not_null must be no-throw move constructible"); + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/strided_span_tests.cpp b/tests/strided_span_tests.cpp index f201df4..20f14ad 100644 --- a/tests/strided_span_tests.cpp +++ b/tests/strided_span_tests.cpp @@ -18,17 +18,24 @@ // blanket turn off warnings from CppCoreCheck from catch // so people aren't annoyed by them when running the tool. #pragma warning(disable : 26440 26426) // from catch deprecated -#pragma warning(disable : 4996) // strided_span is in the process of being deprecated. +#pragma warning(disable : 4996) // strided_span is in the process of being deprecated. // Suppressing warnings until it is completely removed #endif #if __clang__ || __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +//disable warnings from gtest +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ -#include // for AssertionHandler, StringRef, CHECK, CHECK... +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ +#include #include // for byte #include // for narrow_cast #include // for strided_span, index, multi_span, strided_... @@ -39,24 +46,80 @@ #include // for integral_constant<>::value, is_convertible #include // for vector -namespace gsl { -struct fail_fast; -} // namespace gsl - using namespace std; using namespace gsl; + namespace { +static constexpr char deathstring[] = "Expected Death"; + struct BaseClass { }; struct DerivedClass : BaseClass { }; + +GSL_SUPPRESS(con.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute +void iterate_every_other_element(multi_span av) +{ + // pick every other element + + auto length = av.size() / 2; +#if defined(_MSC_VER) && _MSC_VER > 1800 + auto bounds = strided_bounds<1>({length}, {2}); +#else + auto bounds = strided_bounds<1>(multi_span_index<1>{length}, multi_span_index<1>{2}); +#endif + strided_span strided(&av.data()[1], av.size() - 1, bounds); + + EXPECT_TRUE(strided.size() == length); + EXPECT_TRUE(strided.bounds().index_bounds()[0] == length); + for (auto i = 0; i < strided.size(); ++i) { + EXPECT_TRUE(strided[i] == av[2 * i + 1]); + } + + int idx = 0; + for (auto num : strided) { + EXPECT_TRUE(num == av[2 * idx + 1]); + idx++; + } } -TEST_CASE("span_section_test") +GSL_SUPPRESS(con.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // TODO: does not work +void iterate_second_slice(multi_span av) +{ + const int expected[6] = {2, 3, 10, 11, 18, 19}; + auto section = av.section({0, 1, 0}, {3, 1, 2}); + + for (auto i = 0; i < section.extent<0>(); ++i) { + for (auto j = 0; j < section.extent<1>(); ++j) + for (auto k = 0; k < section.extent<2>(); ++k) { + auto idx = multi_span_index<3>{i, j, k}; // avoid braces in the EXPECT_TRUE macro + EXPECT_TRUE(section[idx] == expected[2 * i + 2 * j + k]); + } + } + + for (auto i = 0; i < section.extent<0>(); ++i) { + for (auto j = 0; j < section.extent<1>(); ++j) + for (auto k = 0; k < section.extent<2>(); ++k) + EXPECT_TRUE(section[i][j][k] == expected[2 * i + 2 * j + k]); + } + + int i = 0; + for (const auto num : section) { + EXPECT_TRUE(num == expected[i]); + i++; + } +} + +} + +TEST(strided_span_tests, span_section_test) { int a[30][4][5]; @@ -66,51 +129,54 @@ TEST_CASE("span_section_test") (void) subsub; } -TEST_CASE("span_section") +TEST(strided_span_tests, span_section) { std::vector data(5 * 10); std::iota(begin(data), end(data), 0); const multi_span av = as_multi_span(multi_span{data}, dim<5>(), dim<10>()); const strided_span av_section_1 = av.section({1, 2}, {3, 4}); - CHECK(!av_section_1.empty()); - CHECK((av_section_1[{0, 0}] == 12)); - CHECK((av_section_1[{0, 1}] == 13)); - CHECK((av_section_1[{1, 0}] == 22)); - CHECK((av_section_1[{2, 3}] == 35)); + EXPECT_TRUE(!av_section_1.empty()); + EXPECT_TRUE((av_section_1[{0, 0}] == 12)); + EXPECT_TRUE((av_section_1[{0, 1}] == 13)); + EXPECT_TRUE((av_section_1[{1, 0}] == 22)); + EXPECT_TRUE((av_section_1[{2, 3}] == 35)); const strided_span av_section_2 = av_section_1.section({1, 2}, {2, 2}); - CHECK(!av_section_2.empty()); - CHECK((av_section_2[{0, 0}] == 24)); - CHECK((av_section_2[{0, 1}] == 25)); - CHECK((av_section_2[{1, 0}] == 34)); + EXPECT_TRUE(!av_section_2.empty()); + EXPECT_TRUE((av_section_2[{0, 0}] == 24)); + EXPECT_TRUE((av_section_2[{0, 1}] == 25)); + EXPECT_TRUE((av_section_2[{1, 0}] == 34)); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("strided_span_constructors") +TEST(strided_span_tests, strided_span_constructors) { - // Check stride constructor + // EXPECT_TRUE stride constructor { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; strided_span sav1{arr, {{9}, {1}}}; // T -> T - CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{9}); - CHECK(sav1.bounds().stride() == 1); - CHECK((sav1[0] == 1 && sav1[8] == 9)); + EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{9}); + EXPECT_TRUE(sav1.bounds().stride() == 1); + EXPECT_TRUE(sav1[0] == 1); + EXPECT_TRUE(sav1[8] == 9); strided_span sav2{carr, {{4}, {2}}}; // const T -> const T - CHECK(sav2.bounds().index_bounds() == multi_span_index<1>{4}); - CHECK(sav2.bounds().strides() == multi_span_index<1>{2}); - CHECK((sav2[0] == 1 && sav2[3] == 7)); + EXPECT_TRUE(sav2.bounds().index_bounds() == multi_span_index<1>{4}); + EXPECT_TRUE(sav2.bounds().strides() == multi_span_index<1>{2}); + EXPECT_TRUE(sav2[0] == 1); + EXPECT_TRUE(sav2[3] == 7); strided_span sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T - CHECK((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2})); - CHECK((sav3.bounds().strides() == multi_span_index<2>{6, 2})); - CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7)); + EXPECT_TRUE((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2})); + EXPECT_TRUE((sav3.bounds().strides() == multi_span_index<2>{6, 2})); + EXPECT_TRUE((sav3[{0, 0}]) == 1); + EXPECT_TRUE((sav3[{0, 1}]) == 3); + EXPECT_TRUE((sav3[{1, 0}]) == 7); } - // Check multi_span constructor + // EXPECT_TRUE multi_span constructor { int arr[] = {1, 2}; @@ -119,9 +185,9 @@ TEST_CASE("strided_span_constructors") const multi_span src = arr; strided_span sav{src, {2, 1}}; - CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav[1] == 2); + EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav[1] == 2); #if defined(_MSC_VER) && _MSC_VER > 1800 // strided_span sav_c{ {src}, {2, 1} }; @@ -131,9 +197,9 @@ TEST_CASE("strided_span_constructors") strided_span sav_c{multi_span{src}, strided_bounds<1>{2, 1}}; #endif - CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_c.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_c[1] == 2); + EXPECT_TRUE(sav_c.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_c.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_c[1] == 2); #if defined(_MSC_VER) && _MSC_VER > 1800 strided_span sav_v{src, {2, 1}}; @@ -141,9 +207,9 @@ TEST_CASE("strided_span_constructors") strided_span sav_v{multi_span{src}, strided_bounds<1>{2, 1}}; #endif - CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_v.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_v[1] == 2); + EXPECT_TRUE(sav_v.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_v.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_v[1] == 2); #if defined(_MSC_VER) && _MSC_VER > 1800 strided_span sav_cv{src, {2, 1}}; @@ -151,9 +217,9 @@ TEST_CASE("strided_span_constructors") strided_span sav_cv{multi_span{src}, strided_bounds<1>{2, 1}}; #endif - CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_cv[1] == 2); + EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_cv[1] == 2); } // From const-qualified source @@ -161,9 +227,9 @@ TEST_CASE("strided_span_constructors") const multi_span src{arr}; strided_span sav_c{src, {2, 1}}; - CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_c.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_c[1] == 2); + EXPECT_TRUE(sav_c.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_c.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_c[1] == 2); #if defined(_MSC_VER) && _MSC_VER > 1800 strided_span sav_cv{src, {2, 1}}; @@ -172,9 +238,9 @@ TEST_CASE("strided_span_constructors") strided_bounds<1>{2, 1}}; #endif - CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_cv[1] == 2); + EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_cv[1] == 2); } // From volatile-qualified source @@ -182,9 +248,9 @@ TEST_CASE("strided_span_constructors") const multi_span src{arr}; strided_span sav_v{src, {2, 1}}; - CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_v.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_v[1] == 2); + EXPECT_TRUE(sav_v.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_v.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_v[1] == 2); #if defined(_MSC_VER) && _MSC_VER > 1800 strided_span sav_cv{src, {2, 1}}; @@ -192,9 +258,9 @@ TEST_CASE("strided_span_constructors") strided_span sav_cv{multi_span{src}, strided_bounds<1>{2, 1}}; #endif - CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_cv[1] == 2); + EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_cv[1] == 2); } // From cv-qualified source @@ -202,19 +268,19 @@ TEST_CASE("strided_span_constructors") const multi_span src{arr}; strided_span sav_cv{src, {2, 1}}; - CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav_cv[1] == 2); + EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav_cv[1] == 2); } } - // Check const-casting constructor + // EXPECT_TRUE const-casting constructor { int arr[2] = {4, 5}; const multi_span av(arr, 2); multi_span av2{av}; - CHECK(av2[1] == 5); + EXPECT_TRUE(av2[1] == 5); static_assert( std::is_convertible, multi_span>::value, @@ -222,34 +288,35 @@ TEST_CASE("strided_span_constructors") const strided_span src{arr, {2, 1}}; strided_span sav{src}; - CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav.bounds().stride() == 1); - CHECK(sav[1] == 5); + EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav.bounds().stride() == 1); + EXPECT_TRUE(sav[1] == 5); static_assert( std::is_convertible, strided_span>::value, "ctor is not implicit!"); } - // Check copy constructor + // EXPECT_TRUE copy constructor { int arr1[2] = {3, 4}; const strided_span src1{arr1, {2, 1}}; strided_span sav1{src1}; - CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav1.bounds().stride() == 1); - CHECK(sav1[0] == 3); + EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav1.bounds().stride() == 1); + EXPECT_TRUE(sav1[0] == 3); int arr2[6] = {1, 2, 3, 4, 5, 6}; const strided_span src2{arr2, {{3, 2}, {2, 1}}}; strided_span sav2{src2}; - CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2})); - CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1})); - CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); + EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2})); + EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1})); + EXPECT_TRUE((sav2[{0, 0}]) == 1); + EXPECT_TRUE((sav2[{2, 0}]) == 5); } - // Check const-casting assignment operator + // EXPECT_TRUE const-casting assignment operator { int arr1[2] = {1, 2}; int arr2[6] = {3, 4, 5, 6, 7, 8}; @@ -257,38 +324,38 @@ TEST_CASE("strided_span_constructors") const strided_span src{arr1, {{2}, {1}}}; strided_span sav{arr2, {{3}, {2}}}; strided_span& sav_ref = (sav = src); - CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav[0] == 1); - CHECK(&sav_ref == &sav); + EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav[0] == 1); + EXPECT_TRUE(&sav_ref == &sav); } - // Check copy assignment operator + // EXPECT_TRUE copy assignment operator { int arr1[2] = {3, 4}; int arr1b[1] = {0}; const strided_span src1{arr1, {2, 1}}; strided_span sav1{arr1b, {1, 1}}; strided_span& sav1_ref = (sav1 = src1); - CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav1.bounds().strides() == multi_span_index<1>{1}); - CHECK(sav1[0] == 3); - CHECK(&sav1_ref == &sav1); + EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav1.bounds().strides() == multi_span_index<1>{1}); + EXPECT_TRUE(sav1[0] == 3); + EXPECT_TRUE(&sav1_ref == &sav1); const int arr2[6] = {1, 2, 3, 4, 5, 6}; const int arr2b[1] = {0}; const strided_span src2{arr2, {{3, 2}, {2, 1}}}; strided_span sav2{arr2b, {{1, 1}, {1, 1}}}; strided_span& sav2_ref = (sav2 = src2); - CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2})); - CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1})); - CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); - CHECK(&sav2_ref == &sav2); + EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2})); + EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1})); + EXPECT_TRUE((sav2[{0, 0}] == 1)); + EXPECT_TRUE((sav2[{2, 0}] == 5)); + EXPECT_TRUE(&sav2_ref == &sav2); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("strided_span_slice") +TEST(strided_span_tests, strided_span_slice) { std::vector data(5 * 10); std::iota(begin(data), end(data), 0); @@ -303,19 +370,18 @@ TEST_CASE("strided_span_slice") {{5, 10}, {10, 1}}}; strided_span sav_sl = sav[2]; - CHECK(sav_sl[0] == 20); - CHECK(sav_sl[9] == 29); + EXPECT_TRUE(sav_sl[0] == 20); + EXPECT_TRUE(sav_sl[9] == 29); strided_span csav_sl = sav[3]; - CHECK(csav_sl[0] == 30); - CHECK(csav_sl[9] == 39); + EXPECT_TRUE(csav_sl[0] == 30); + EXPECT_TRUE(csav_sl[9] == 39); - CHECK(sav[4][0] == 40); - CHECK(sav[4][9] == 49); + EXPECT_TRUE(sav[4][0] == 40); + EXPECT_TRUE(sav[4][9] == 49); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("strided_span_column_major") +TEST(strided_span_tests, strided_span_column_major) { // strided_span may be used to accommodate more peculiar // use cases, such as column-major multidimensional array @@ -325,119 +391,123 @@ TEST_CASE("strided_span_column_major") strided_span cm_sav{cm_array, {{5, 3}, {1, 5}}}; // Accessing elements - CHECK((cm_sav[{0, 0}] == 1)); - CHECK((cm_sav[{0, 1}] == 2)); - CHECK((cm_sav[{1, 0}] == 4)); - CHECK((cm_sav[{4, 2}] == 15)); + EXPECT_TRUE((cm_sav[{0, 0}] == 1)); + EXPECT_TRUE((cm_sav[{0, 1}] == 2)); + EXPECT_TRUE((cm_sav[{1, 0}] == 4)); + EXPECT_TRUE((cm_sav[{4, 2}] == 15)); // Slice strided_span cm_sl = cm_sav[3]; - CHECK(cm_sl[0] == 10); - CHECK(cm_sl[1] == 11); - CHECK(cm_sl[2] == 12); + EXPECT_TRUE(cm_sl[0] == 10); + EXPECT_TRUE(cm_sl[1] == 11); + EXPECT_TRUE(cm_sl[2] == 12); // Section strided_span cm_sec = cm_sav.section({2, 1}, {3, 2}); - CHECK((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2})); - CHECK((cm_sec[{0, 0}] == 8)); - CHECK((cm_sec[{0, 1}] == 9)); - CHECK((cm_sec[{1, 0}] == 11)); - CHECK((cm_sec[{2, 1}] == 15)); + EXPECT_TRUE((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2})); + EXPECT_TRUE((cm_sec[{0, 0}] == 8)); + EXPECT_TRUE((cm_sec[{0, 1}] == 9)); + EXPECT_TRUE((cm_sec[{1, 0}] == 11)); + EXPECT_TRUE((cm_sec[{2, 1}] == 15)); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("strided_span_bounds") +TEST(strided_span_tests, strided_span_bounds) { int arr[] = {0, 1, 2, 3}; multi_span av(arr); + std::set_terminate([] { + std::cerr << "Expected Death. strided_span_bounds"; + std::abort(); + }); + { // incorrect sections - CHECK_THROWS_AS(av.section(0, 0)[0], fail_fast); - CHECK_THROWS_AS(av.section(1, 0)[0], fail_fast); - CHECK_THROWS_AS(av.section(1, 1)[1], fail_fast); + EXPECT_DEATH(av.section(0, 0)[0], deathstring); + EXPECT_DEATH(av.section(1, 0)[0], deathstring); + EXPECT_DEATH(av.section(1, 1)[1], deathstring); - CHECK_THROWS_AS(av.section(2, 5), fail_fast); - CHECK_THROWS_AS(av.section(5, 2), fail_fast); - CHECK_THROWS_AS(av.section(5, 0), fail_fast); - CHECK_THROWS_AS(av.section(0, 5), fail_fast); - CHECK_THROWS_AS(av.section(5, 5), fail_fast); + EXPECT_DEATH(av.section(2, 5), deathstring); + EXPECT_DEATH(av.section(5, 2), deathstring); + EXPECT_DEATH(av.section(5, 0), deathstring); + EXPECT_DEATH(av.section(0, 5), deathstring); + EXPECT_DEATH(av.section(5, 5), deathstring); } { // zero stride strided_span sav{av, {{4}, {}}}; - CHECK(sav[0] == 0); - CHECK(sav[3] == 0); - CHECK_THROWS_AS(sav[4], fail_fast); + EXPECT_TRUE(sav[0] == 0); + EXPECT_TRUE(sav[3] == 0); + EXPECT_DEATH(sav[4], deathstring); } { // zero extent strided_span sav{av, {{}, {1}}}; - CHECK_THROWS_AS(sav[0], fail_fast); + EXPECT_DEATH(sav[0], deathstring); } { // zero extent and stride strided_span sav{av, {{}, {}}}; - CHECK_THROWS_AS(sav[0], fail_fast); + EXPECT_DEATH(sav[0], deathstring); } { // strided array ctor with matching strided bounds strided_span sav{arr, {4, 1}}; - CHECK(sav.bounds().index_bounds() == multi_span_index<1>{4}); - CHECK(sav[3] == 3); - CHECK_THROWS_AS(sav[4], fail_fast); + EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{4}); + EXPECT_TRUE(sav[3] == 3); + EXPECT_DEATH(sav[4], deathstring); } { // strided array ctor with smaller strided bounds strided_span sav{arr, {2, 1}}; - CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav[1] == 1); - CHECK_THROWS_AS(sav[2], fail_fast); + EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav[1] == 1); + EXPECT_DEATH(sav[2], deathstring); } { // strided array ctor with fitting irregular bounds strided_span sav{arr, {2, 3}}; - CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); - CHECK(sav[0] == 0); - CHECK(sav[1] == 3); - CHECK_THROWS_AS(sav[2], fail_fast); + EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2}); + EXPECT_TRUE(sav[0] == 0); + EXPECT_TRUE(sav[1] == 3); + EXPECT_DEATH(sav[2], deathstring); } { // bounds cross data boundaries - from static arrays - CHECK_THROWS_AS((strided_span{arr, {3, 2}}), fail_fast); - CHECK_THROWS_AS((strided_span{arr, {3, 3}}), fail_fast); - CHECK_THROWS_AS((strided_span{arr, {4, 5}}), fail_fast); - CHECK_THROWS_AS((strided_span{arr, {5, 1}}), fail_fast); - CHECK_THROWS_AS((strided_span{arr, {5, 5}}), fail_fast); + EXPECT_DEATH((strided_span{arr, {3, 2}}), deathstring); + EXPECT_DEATH((strided_span{arr, {3, 3}}), deathstring); + EXPECT_DEATH((strided_span{arr, {4, 5}}), deathstring); + EXPECT_DEATH((strided_span{arr, {5, 1}}), deathstring); + EXPECT_DEATH((strided_span{arr, {5, 5}}), deathstring); } { // bounds cross data boundaries - from array view - CHECK_THROWS_AS((strided_span{av, {3, 2}}), fail_fast); - CHECK_THROWS_AS((strided_span{av, {3, 3}}), fail_fast); - CHECK_THROWS_AS((strided_span{av, {4, 5}}), fail_fast); - CHECK_THROWS_AS((strided_span{av, {5, 1}}), fail_fast); - CHECK_THROWS_AS((strided_span{av, {5, 5}}), fail_fast); + EXPECT_DEATH((strided_span{av, {3, 2}}), deathstring); + EXPECT_DEATH((strided_span{av, {3, 3}}), deathstring); + EXPECT_DEATH((strided_span{av, {4, 5}}), deathstring); + EXPECT_DEATH((strided_span{av, {5, 1}}), deathstring); + EXPECT_DEATH((strided_span{av, {5, 5}}), deathstring); } { // bounds cross data boundaries - from dynamic arrays - CHECK_THROWS_AS((strided_span{av.data(), 4, {3, 2}}), fail_fast); - CHECK_THROWS_AS((strided_span{av.data(), 4, {3, 3}}), fail_fast); - CHECK_THROWS_AS((strided_span{av.data(), 4, {4, 5}}), fail_fast); - CHECK_THROWS_AS((strided_span{av.data(), 4, {5, 1}}), fail_fast); - CHECK_THROWS_AS((strided_span{av.data(), 4, {5, 5}}), fail_fast); - CHECK_THROWS_AS((strided_span{av.data(), 2, {2, 2}}), fail_fast); + EXPECT_DEATH((strided_span{av.data(), 4, {3, 2}}), deathstring); + EXPECT_DEATH((strided_span{av.data(), 4, {3, 3}}), deathstring); + EXPECT_DEATH((strided_span{av.data(), 4, {4, 5}}), deathstring); + EXPECT_DEATH((strided_span{av.data(), 4, {5, 1}}), deathstring); + EXPECT_DEATH((strided_span{av.data(), 4, {5, 5}}), deathstring); + EXPECT_DEATH((strided_span{av.data(), 2, {2, 2}}), deathstring); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -464,12 +534,16 @@ TEST_CASE("strided_span_bounds") #endif } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("strided_span_type_conversion") +TEST(strided_span_tests, strided_span_type_conversion) { int arr[] = {0, 1, 2, 3}; multi_span av(arr); + std::set_terminate([] { + std::cerr << "Expected Death. strided_span_type_conversion"; + std::abort(); + }); + { strided_span sav{av.data(), av.size(), {av.size() / 2, 2}}; #ifdef CONFIRM_COMPILATION_ERRORS @@ -490,10 +564,10 @@ TEST_CASE("strided_span_type_conversion") strided_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}}; strided_span sav2{bytes.data(), bytes.size(), bounds}; strided_span sav3 = sav2.as_strided_span(); - CHECK(sav3[0][0] == 0); - CHECK(sav3[1][0] == 2); - CHECK_THROWS_AS(sav3[1][1], fail_fast); - CHECK_THROWS_AS(sav3[0][1], fail_fast); + EXPECT_TRUE(sav3[0][0] == 0); + EXPECT_TRUE(sav3[1][0] == 2); + EXPECT_DEATH(sav3[1][1], deathstring); + EXPECT_DEATH(sav3[0][1], deathstring); } // retype strided array with regular strides - from multi_span @@ -503,10 +577,10 @@ TEST_CASE("strided_span_type_conversion") as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); strided_span sav2{bytes2, bounds}; strided_span sav3 = sav2.as_strided_span(); - CHECK(sav3[0][0] == 0); - CHECK(sav3[1][0] == 2); - CHECK_THROWS_AS(sav3[1][1], fail_fast); - CHECK_THROWS_AS(sav3[0][1], fail_fast); + EXPECT_TRUE(sav3[0][0] == 0); + EXPECT_TRUE(sav3[1][0] == 2); + EXPECT_DEATH(sav3[1][1], deathstring); + EXPECT_DEATH(sav3[0][1], deathstring); } // retype strided array with not enough elements - last dimension of the array is too small @@ -515,7 +589,7 @@ TEST_CASE("strided_span_type_conversion") multi_span bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); strided_span sav2{bytes2, bounds}; - CHECK_THROWS_AS(sav2.as_strided_span(), fail_fast); + EXPECT_DEATH(sav2.as_strided_span(), deathstring); } // retype strided array with not enough elements - strides are too small @@ -524,7 +598,7 @@ TEST_CASE("strided_span_type_conversion") multi_span bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); strided_span sav2{bytes2, bounds}; - CHECK_THROWS_AS(sav2.as_strided_span(), fail_fast); + EXPECT_DEATH(sav2.as_strided_span(), deathstring); } // retype strided array with not enough elements - last dimension does not divide by the new @@ -534,7 +608,7 @@ TEST_CASE("strided_span_type_conversion") multi_span bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); strided_span sav2{bytes2, bounds}; - CHECK_THROWS_AS(sav2.as_strided_span(), fail_fast); + EXPECT_DEATH(sav2.as_strided_span(), deathstring); } // retype strided array with not enough elements - strides does not divide by the new @@ -544,88 +618,63 @@ TEST_CASE("strided_span_type_conversion") multi_span bytes2 = as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); strided_span sav2{bytes2, bounds}; - CHECK_THROWS_AS(sav2.as_strided_span(), fail_fast); + EXPECT_DEATH(sav2.as_strided_span(), deathstring); } // retype strided array with irregular strides - from raw data { strided_bounds<1> bounds{bytes.size() / 2, 2}; strided_span sav2{bytes.data(), bytes.size(), bounds}; - CHECK_THROWS_AS(sav2.as_strided_span(), fail_fast); + EXPECT_DEATH(sav2.as_strided_span(), deathstring); } // retype strided array with irregular strides - from multi_span { strided_bounds<1> bounds{bytes.size() / 2, 2}; strided_span sav2{bytes, bounds}; - CHECK_THROWS_AS(sav2.as_strided_span(), fail_fast); + EXPECT_DEATH(sav2.as_strided_span(), deathstring); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -TEST_CASE("empty_strided_spans") +TEST(strided_span_tests, empty_strided_spans) { + std::set_terminate([] { + std::cerr << "Expected Death. empty_strided_spans"; + std::abort(); + }); + { multi_span empty_av(nullptr); strided_span empty_sav{empty_av, {0, 1}}; - CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); - CHECK(empty_sav.empty()); - CHECK_THROWS_AS(empty_sav[0], fail_fast); - CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); - CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); + EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); + EXPECT_TRUE(empty_sav.empty()); + EXPECT_DEATH(empty_sav[0], deathstring); + EXPECT_DEATH(empty_sav.begin()[0], deathstring); + EXPECT_DEATH(empty_sav.cbegin()[0], deathstring); for (const auto& v : empty_sav) { (void) v; - CHECK(false); + EXPECT_TRUE(false); } } { strided_span empty_sav{nullptr, 0, {0, 1}}; - CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); - CHECK_THROWS_AS(empty_sav[0], fail_fast); - CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); - CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); + EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); + EXPECT_DEATH(empty_sav[0], deathstring); + EXPECT_DEATH(empty_sav.begin()[0], deathstring); + EXPECT_DEATH(empty_sav.cbegin()[0], deathstring); for (const auto& v : empty_sav) { (void) v; - CHECK(false); + EXPECT_TRUE(false); } } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -void iterate_every_other_element(multi_span av) -{ - // pick every other element - - auto length = av.size() / 2; -#if defined(_MSC_VER) && _MSC_VER > 1800 - auto bounds = strided_bounds<1>({length}, {2}); -#else - auto bounds = strided_bounds<1>(multi_span_index<1>{length}, multi_span_index<1>{2}); -#endif - strided_span strided(&av.data()[1], av.size() - 1, bounds); - - CHECK(strided.size() == length); - CHECK(strided.bounds().index_bounds()[0] == length); - for (auto i = 0; i < strided.size(); ++i) { - CHECK(strided[i] == av[2 * i + 1]); - } - - int idx = 0; - for (auto num : strided) { - CHECK(num == av[2 * idx + 1]); - idx++; - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("strided_span_section_iteration") +TEST(strided_span_tests, strided_span_section_iteration) { int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3}; @@ -642,12 +691,7 @@ TEST_CASE("strided_span_section_iteration") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("dynamic_strided_span_section_iteration") +TEST(strided_span_tests, dynamic_strided_span_section_iteration) { auto arr = new int[8]; for (int i = 0; i < 4; ++i) { @@ -661,39 +705,7 @@ TEST_CASE("dynamic_strided_span_section_iteration") delete[] arr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // TODO: does not work -void iterate_second_slice(multi_span av) -{ - const int expected[6] = {2, 3, 10, 11, 18, 19}; - auto section = av.section({0, 1, 0}, {3, 1, 2}); - - for (auto i = 0; i < section.extent<0>(); ++i) { - for (auto j = 0; j < section.extent<1>(); ++j) - for (auto k = 0; k < section.extent<2>(); ++k) { - auto idx = multi_span_index<3>{i, j, k}; // avoid braces in the CHECK macro - CHECK(section[idx] == expected[2 * i + 2 * j + k]); - } - } - - for (auto i = 0; i < section.extent<0>(); ++i) { - for (auto j = 0; j < section.extent<1>(); ++j) - for (auto k = 0; k < section.extent<2>(); ++k) - CHECK(section[i][j][k] == expected[2 * i + 2 * j + k]); - } - - int i = 0; - for (const auto num : section) { - CHECK(num == expected[i]); - i++; - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("strided_span_section_iteration_3d") +TEST(strided_span_tests, strided_span_section_iteration_3d) { int arr[3][4][2]{}; for (auto i = 0; i < 3; ++i) { @@ -707,12 +719,7 @@ TEST_CASE("strided_span_section_iteration_3d") } } -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -TEST_CASE("dynamic_strided_span_section_iteration_3d") +TEST(strided_span_tests, dynamic_strided_span_section_iteration_3d) { const auto height = 12, width = 2; const auto size = height * width; @@ -744,11 +751,13 @@ TEST_CASE("dynamic_strided_span_section_iteration_3d") delete[] arr; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("strided_span_conversion") +TEST(strided_span_tests, strided_span_conversion) { + std::set_terminate([] { + std::cerr << "Expected Death. strided_span_conversion"; + std::abort(); + }); + // get an multi_span of 'c' values from the list of X's struct X @@ -767,8 +776,8 @@ TEST_CASE("strided_span_conversion") // convert to 4x12 array of bytes auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2)); - CHECK(av.bounds().index_bounds()[0] == 4); - CHECK(av.bounds().index_bounds()[1] == 12); + EXPECT_TRUE(av.bounds().index_bounds()[0] == 4); + EXPECT_TRUE(av.bounds().index_bounds()[1] == 12); // get the last 4 columns auto section = av.section({0, 2 * s}, {4, s}); // { { arr[0].c[0], arr[0].c[1], arr[0].c[2], @@ -778,8 +787,8 @@ TEST_CASE("strided_span_conversion") // convert to array 4x1 array of integers auto cs = section.as_strided_span(); // { { arr[0].c }, {arr[1].c } , ... } - CHECK(cs.bounds().index_bounds()[0] == 4); - CHECK(cs.bounds().index_bounds()[1] == 1); + EXPECT_TRUE(cs.bounds().index_bounds()[0] == 4); + EXPECT_TRUE(cs.bounds().index_bounds()[1] == 1); // transpose to 1x4 array strided_bounds<2> reverse_bounds{ @@ -791,16 +800,16 @@ TEST_CASE("strided_span_conversion") // slice to get a one-dimensional array of c's strided_span result = transposed[0]; - CHECK(result.bounds().index_bounds()[0] == 4); - CHECK_THROWS_AS(result.bounds().index_bounds()[1], fail_fast); + EXPECT_TRUE(result.bounds().index_bounds()[0] == 4); + EXPECT_DEATH(result.bounds().index_bounds()[1], deathstring); int i = 0; for (auto& num : result) { - CHECK(num == arr[i].c); + EXPECT_TRUE(num == arr[i].c); i++; } } #if __clang__ || __GNUC__ #pragma GCC diagnostic pop -#endif +#endif // __clang__ || __GNUC__ diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index fd3e3e6..b9cfdcc 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -21,7 +21,19 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + +#include #include // for Expects, fail_fast (ptr only) #include // for owner @@ -38,14 +50,16 @@ using namespace std; using namespace gsl; +namespace +{ +static constexpr char deathstring[] = "Expected Death"; +} // Generic string functions namespace generic { template -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -GSL_SUPPRESS(f.23) // NO-FORMAT: attribute auto strlen(const CharT* s) { auto p = s; @@ -54,7 +68,6 @@ auto strlen(const CharT* s) } template -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute auto strnlen(const CharT* s, std::size_t n) { return std::find(s, s + n, CharT{0}) - s; @@ -62,741 +75,8 @@ auto strnlen(const CharT* s, std::size_t n) } // namespace generic -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestLiteralConstruction") +namespace { - cwstring_span<> v = ensure_z(L"Hello"); - CHECK(5 == v.length()); - -#ifdef CONFIRM_COMPILATION_ERRORS - wstring_span<> v2 = ensure0(L"Hello"); -#endif -} -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute - -TEST_CASE("TestConstructFromStdString") -{ - std::string s = "Hello there world"; - cstring_span<> v = s; - CHECK(v.length() == static_cast::index_type>(s.length())); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestConstructFromStdVector") -{ - std::vector vec(5, 'h'); - string_span<> v{vec}; - CHECK(v.length() == static_cast::index_type>(vec.size())); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestStackArrayConstruction") -{ - wchar_t stack_string[] = L"Hello"; - - { - cwstring_span<> v = ensure_z(stack_string); - CHECK(v.length() == 5); - } - - { - cwstring_span<> v = stack_string; - CHECK(v.length() == 5); - } - - { - wstring_span<> v = ensure_z(stack_string); - CHECK(v.length() == 5); - } - - { - wstring_span<> v = stack_string; - CHECK(v.length() == 5); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestConstructFromConstCharPointer") -{ - const char* s = "Hello"; - cstring_span<> v = ensure_z(s); - CHECK(v.length() == 5); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestConversionToConst") -{ - char stack_string[] = "Hello"; - string_span<> v = ensure_z(stack_string); - cstring_span<> v2 = v; - CHECK(v.length() == v2.length()); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestConversionFromConst") -{ - char stack_string[] = "Hello"; - cstring_span<> v = ensure_z(stack_string); - (void) v; -#ifdef CONFIRM_COMPILATION_ERRORS - string_span<> v2 = v; - string_span<> v3 = "Hello"; -#endif -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestToString") -{ - auto s = gsl::to_string(cstring_span<>{}); - CHECK(s.length() == 0); - - char stack_string[] = "Hello"; - cstring_span<> v = ensure_z(stack_string); - auto s2 = gsl::to_string(v); - CHECK(static_cast::index_type>(s2.length()) == v.length()); - CHECK(s2.length() == 5); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestToBasicString") -{ - auto s = gsl::to_basic_string, ::std::allocator>( - cstring_span<>{}); - CHECK(s.length() == 0); - - char stack_string[] = "Hello"; - cstring_span<> v = ensure_z(stack_string); - auto s2 = gsl::to_basic_string, ::std::allocator>(v); - CHECK(static_cast::index_type>(s2.length()) == v.length()); - CHECK(s2.length() == 5); -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -TEST_CASE("EqualityAndImplicitConstructors") -{ - { - cstring_span<> span = "Hello"; - cstring_span<> span1; - - // comparison to empty span - CHECK(span1 != span); - CHECK(span != span1); - } - - { - cstring_span<> span = "Hello"; - cstring_span<> span1 = "Hello1"; - - // comparison to different span - CHECK(span1 != span); - CHECK(span != span1); - } - - { - cstring_span<> span = "Hello"; - - const char ar[] = {'H', 'e', 'l', 'l', 'o'}; - const char ar1[] = "Hello"; - const char ar2[10] = "Hello"; - const char* ptr = "Hello"; - const std::string str = "Hello"; - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - gsl::span sp = ensure_z("Hello"); - - // comparison to literal - CHECK(span == cstring_span<>("Hello")); - - // comparison to static array with no null termination - CHECK(span == cstring_span<>(ar)); - - // comparison to static array with null at the end - CHECK(span == cstring_span<>(ar1)); - - // comparison to static array with null in the middle - CHECK(span == cstring_span<>(ar2)); - - // comparison to null-terminated c string - CHECK(span == cstring_span<>(ptr, 5)); - - // comparison to string - CHECK(span == cstring_span<>(str)); - - // comparison to vector of charaters with no null termination - CHECK(span == cstring_span<>(vec)); - - // comparison to span - CHECK(span == cstring_span<>(sp)); - - // comparison to string_span - CHECK(span == span); - } - - { - char ar[] = {'H', 'e', 'l', 'l', 'o'}; - - string_span<> span = ar; - - char ar1[] = "Hello"; - char ar2[10] = "Hello"; - char* ptr = ar; - std::string str = "Hello"; - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - gsl::span sp = ensure_z(ar1); - - // comparison to static array with no null termination - CHECK(span == string_span<>(ar)); - - // comparison to static array with null at the end - CHECK(span == string_span<>(ar1)); - - // comparison to static array with null in the middle - CHECK(span == string_span<>(ar2)); - - // comparison to null-terminated c string - CHECK(span == string_span<>(ptr, 5)); - - // comparison to string - CHECK(span == string_span<>(str)); - - // comparison to vector of charaters with no null termination - CHECK(span == string_span<>(vec)); - - // comparison to span - CHECK(span == string_span<>(sp)); - - // comparison to string_span - CHECK(span == span); - } - - { - const char ar[] = {'H', 'e', 'l', 'l', 'o'}; - const char ar1[] = "Hello"; - const char ar2[10] = "Hello"; - const std::string str = "Hello"; - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const gsl::span sp = ensure_z("Hello"); - - cstring_span<> span = "Hello"; - - // const span, const other type - - CHECK(span == "Hello"); - CHECK(span == ar); - CHECK(span == ar1); - CHECK(span == ar2); -#ifdef CONFIRM_COMPILATION_ERRORS - const char* ptr = "Hello"; - CHECK(span == ptr); -#endif - CHECK(span == str); - CHECK(span == vec); - CHECK(span == sp); - - CHECK("Hello" == span); - CHECK(ar == span); - CHECK(ar1 == span); - CHECK(ar2 == span); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(ptr == span); -#endif - CHECK(str == span); - CHECK(vec == span); - CHECK(sp == span); - - // const span, non-const other type - - char _ar[] = {'H', 'e', 'l', 'l', 'o'}; - char _ar1[] = "Hello"; - char _ar2[10] = "Hello"; - char* _ptr = _ar; - std::string _str = "Hello"; - std::vector _vec = {'H', 'e', 'l', 'l', 'o'}; - gsl::span _sp{_ar, 5}; - - CHECK(span == _ar); - CHECK(span == _ar1); - CHECK(span == _ar2); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(span == _ptr); -#endif - CHECK(span == _str); - CHECK(span == _vec); - CHECK(span == _sp); - - CHECK(_ar == span); - CHECK(_ar1 == span); - CHECK(_ar2 == span); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(_ptr == span); -#endif - CHECK(_str == span); - CHECK(_vec == span); - CHECK(_sp == span); - - string_span<> _span{_ptr, 5}; - - // non-const span, non-const other type - - CHECK(_span == _ar); - CHECK(_span == _ar1); - CHECK(_span == _ar2); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(_span == _ptr); -#endif - CHECK(_span == _str); - CHECK(_span == _vec); - CHECK(_span == _sp); - - CHECK(_ar == _span); - CHECK(_ar1 == _span); - CHECK(_ar2 == _span); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(_ptr == _span); -#endif - CHECK(_str == _span); - CHECK(_vec == _span); - CHECK(_sp == _span); - - // non-const span, const other type - - CHECK(_span == "Hello"); - CHECK(_span == ar); - CHECK(_span == ar1); - CHECK(_span == ar2); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(_span == ptr); -#endif - CHECK(_span == str); - CHECK(_span == vec); - CHECK(_span == sp); - - CHECK("Hello" == _span); - CHECK(ar == _span); - CHECK(ar1 == _span); - CHECK(ar2 == _span); -#ifdef CONFIRM_COMPILATION_ERRORS - CHECK(ptr == _span); -#endif - CHECK(str == _span); - CHECK(vec == _span); - CHECK(sp == _span); - - // two spans - - CHECK(_span == span); - CHECK(span == _span); - } - - { - std::vector str1 = {'H', 'e', 'l', 'l', 'o'}; - cstring_span<> span1 = str1; - std::vector str2 = std::move(str1); - cstring_span<> span2 = str2; - - // comparison of spans from the same vector before and after move (ok) - CHECK(span1 == span2); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -TEST_CASE("ComparisonAndImplicitConstructors") -{ - { - cstring_span<> span = "Hello"; - - const char ar[] = {'H', 'e', 'l', 'l', 'o'}; - const char ar1[] = "Hello"; - const char ar2[10] = "Hello"; - const char* ptr = "Hello"; - const std::string str = "Hello"; - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - - // comparison to literal - CHECK(span < cstring_span<>("Helloo")); - CHECK(span > cstring_span<>("Hell")); - - // comparison to static array with no null termination - CHECK(span >= cstring_span<>(ar)); - - // comparison to static array with null at the end - CHECK(span <= cstring_span<>(ar1)); - - // comparison to static array with null in the middle - CHECK(span >= cstring_span<>(ar2)); - - // comparison to null-terminated c string - CHECK(span <= cstring_span<>(ptr, 5)); - - // comparison to string - CHECK(span >= cstring_span<>(str)); - - // comparison to vector of charaters with no null termination - CHECK(span <= cstring_span<>(vec)); - } - - { - char ar[] = {'H', 'e', 'l', 'l', 'o'}; - - string_span<> span = ar; - - char larr[] = "Hell"; - char rarr[] = "Helloo"; - - char ar1[] = "Hello"; - char ar2[10] = "Hello"; - char* ptr = ar; - std::string str = "Hello"; - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - - // comparison to static array with no null termination - CHECK(span <= string_span<>(ar)); - CHECK(span < string_span<>(rarr)); - CHECK(span > string_span<>(larr)); - - // comparison to static array with null at the end - CHECK(span >= string_span<>(ar1)); - - // comparison to static array with null in the middle - CHECK(span <= string_span<>(ar2)); - - // comparison to null-terminated c string - CHECK(span >= string_span<>(ptr, 5)); - - // comparison to string - CHECK(span <= string_span<>(str)); - - // comparison to vector of charaters with no null termination - CHECK(span >= string_span<>(vec)); - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(r.11) // NO-FORMAT: attribute -GSL_SUPPRESS(r.3) // NO-FORMAT: attribute -GSL_SUPPRESS(r.5) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("ConstrutorsEnsureZ") -{ - // remove z from literals - { - cstring_span<> sp = "hello"; - CHECK((sp.length() == 5)); - } - - // take the string as is - { - auto str = std::string("hello"); - cstring_span<> sp = str; - CHECK((sp.length() == 5)); - } - - // ensure z on c strings - { - gsl::owner ptr = new char[3]; - - ptr[0] = 'a'; - ptr[1] = 'b'; - ptr[2] = '\0'; - - string_span<> span = ensure_z(ptr); - CHECK(span.length() == 2); - - delete[] ptr; - } -} - -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -TEST_CASE("Constructors") -{ - // creating cstring_span - - // from span of a final extent - { - span sp = "Hello"; - cstring_span<> span = sp; - CHECK(span.length() == 6); - } - -// from const span of a final extent to non-const string_span -#ifdef CONFIRM_COMPILATION_ERRORS - { - span sp = "Hello"; - string_span<> span = sp; - CHECK(span.length() == 6); - } -#endif - -// from string temporary -#ifdef CONFIRM_COMPILATION_ERRORS - { - cstring_span<> span = std::string("Hello"); - } -#endif - - // default - { - cstring_span<> span; - CHECK(span.length() == 0); - } - - // from string literal - { - cstring_span<> span = "Hello"; - CHECK(span.length() == 5); - } - - // from const static array - { - const char ar[] = {'H', 'e', 'l', 'l', 'o'}; - cstring_span<> span = ar; - CHECK(span.length() == 5); - } - - // from non-const static array - { - char ar[] = {'H', 'e', 'l', 'l', 'o'}; - cstring_span<> span = ar; - CHECK(span.length() == 5); - } - - // from const ptr and length - { - const char* ptr = "Hello"; - cstring_span<> span{ptr, 5}; - CHECK(span.length() == 5); - } - - // from const ptr and length, include 0 - { - const char* ptr = "Hello"; - cstring_span<> span{ptr, 6}; - CHECK(span.length() == 6); - } - - // from const ptr and length, 0 inside - { - const char* ptr = "He\0lo"; - cstring_span<> span{ptr, 5}; - CHECK(span.length() == 5); - } - - // from non-const ptr and length - { - char ar[] = {'H', 'e', 'l', 'l', 'o'}; - char* ptr = ar; - cstring_span<> span{ptr, 5}; - CHECK(span.length() == 5); - } - - // from non-const ptr and length, 0 inside - { - char ar[] = {'H', 'e', '\0', 'l', 'o'}; - char* ptr = ar; - cstring_span<> span{ptr, 5}; - CHECK(span.length() == 5); - } - - // from const string - { - const std::string str = "Hello"; - const cstring_span<> span = str; - CHECK(span.length() == 5); - } - - // from non-const string - { - std::string str = "Hello"; - const cstring_span<> span = str; - CHECK(span.length() == 5); - } - - // from const vector - { - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const cstring_span<> span = vec; - CHECK(span.length() == 5); - } - - // from non-const vector - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const cstring_span<> span = vec; - CHECK(span.length() == 5); - } - - // from const span - { - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const span inner = vec; - const cstring_span<> span = inner; - CHECK(span.length() == 5); - } - - // from non-const span - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const span inner = vec; - const cstring_span<> span = inner; - CHECK(span.length() == 5); - } - - // from const string_span - { - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const cstring_span<> tmp = vec; - const cstring_span<> span = tmp; - CHECK(span.length() == 5); - } - - // from non-const string_span - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - string_span<> tmp = vec; - cstring_span<> span = tmp; - CHECK(span.length() == 5); - } - - // creating string_span - - // from string literal - { -#ifdef CONFIRM_COMPILATION_ERRORS - string_span<> span = "Hello"; -#endif - } - - // from const static array - { -#ifdef CONFIRM_COMPILATION_ERRORS - const char ar[] = {'H', 'e', 'l', 'l', 'o'}; - string_span<> span = ar; - CHECK(span.length() == 5); -#endif - } - - // from non-const static array - { - char ar[] = {'H', 'e', 'l', 'l', 'o'}; - string_span<> span = ar; - CHECK(span.length() == 5); - } - - // from const ptr and length - { -#ifdef CONFIRM_COMPILATION_ERRORS - const char* ptr = "Hello"; - string_span<> span{ptr, 5}; - CHECK(span.length() == 5); -#endif - } - - // from non-const ptr and length - { - char ar[] = {'H', 'e', 'l', 'l', 'o'}; - char* ptr = ar; - string_span<> span{ptr, 5}; - CHECK(span.length() == 5); - } - - // from const string - { -#ifdef CONFIRM_COMPILATION_ERRORS - const std::string str = "Hello"; - string_span<> span = str; - CHECK(span.length() == 5); -#endif - } - - // from non-const string - { - std::string str = "Hello"; - string_span<> span = str; - CHECK(span.length() == 5); - } - - // from const vector - { -#ifdef CONFIRM_COMPILATION_ERRORS - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - string_span<> span = vec; - CHECK(span.length() == 5); -#endif - } - - // from non-const vector - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - string_span<> span = vec; - CHECK(span.length() == 5); - } - - // from const span - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const span inner = vec; - string_span<> span = inner; - CHECK(span.length() == 5); -#endif - } - - // from non-const span - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - span inner = vec; - string_span<> span = inner; - CHECK(span.length() == 5); - } - - // from non-const span of non-const data from const vector - { -#ifdef CONFIRM_COMPILATION_ERRORS - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const span inner = vec; - string_span<> span = inner; - CHECK(span.length() == 5); -#endif - } - - // from const string_span - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - cstring_span<> tmp = vec; - string_span<> span = tmp; - CHECK(span.length() == 5); -#endif - } - - // from non-const string_span - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const string_span<> tmp = vec; - const string_span<> span = tmp; - CHECK(span.length() == 5); - } - - // from non-const string_span from const vector - { -#ifdef CONFIRM_COMPILATION_ERRORS - const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - string_span<> tmp = vec; - string_span<> span = tmp; - CHECK(span.length() == 5); -#endif - } - - // from const string_span of non-const data - { - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - const string_span<> tmp = vec; - const string_span<> span = tmp; - CHECK(span.length() == 5); - } -} template T move_wrapper(T&& t) @@ -804,6 +84,9 @@ T move_wrapper(T&& t) return std::move(t); } +// not used otherwise +#ifdef CONFIRM_COMPILATION_ERRORS + template T create() { @@ -814,89 +97,7 @@ template void use(basic_string_span) { } - -TEST_CASE("MoveConstructors") -{ - // move string_span - { - cstring_span<> span = "Hello"; - const auto span1 = std::move(span); - CHECK(span1.length() == 5); - } - { - cstring_span<> span = "Hello"; - const auto span1 = move_wrapper(std::move(span)); - CHECK(span1.length() == 5); - } - { - cstring_span<> span = "Hello"; - const auto span1 = move_wrapper(std::move(span)); - CHECK(span1.length() == 5); - } - - // move span - { - span span = ensure_z("Hello"); - const cstring_span<> span1 = std::move(span); - CHECK(span1.length() == 5); - } - { - span span = ensure_z("Hello"); - const cstring_span<> span2 = move_wrapper(std::move(span)); - CHECK(span2.length() == 5); - } - - // move string - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::string str = "Hello"; - string_span<> span = std::move(str); - CHECK(span.length() == 5); #endif - } - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::string str = "Hello"; - string_span<> span = move_wrapper(std::move(str)); - CHECK(span.length() == 5); -#endif - } - { -#ifdef CONFIRM_COMPILATION_ERRORS - use(create()); -#endif - } - - // move container - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - string_span<> span = std::move(vec); - CHECK(span.length() == 5); -#endif - } - { -#ifdef CONFIRM_COMPILATION_ERRORS - std::vector vec = {'H', 'e', 'l', 'l', 'o'}; - string_span<> span = move_wrapper>(std::move(vec)); - CHECK(span.length() == 5); -#endif - } - { -#ifdef CONFIRM_COMPILATION_ERRORS - use(create>()); -#endif - } -} - -TEST_CASE("Conversion") -{ -#ifdef CONFIRM_COMPILATION_ERRORS - cstring_span<> span = "Hello"; - cwstring_span<> wspan{span}; - CHECK(wspan.length() == 5); -#endif -} czstring_span<> CreateTempName(string_span<> span) { @@ -915,45 +116,6 @@ czstring_span<> CreateTempName(string_span<> span) return {ret}; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("zstring") -{ - - // create zspan from zero terminated string - { - char buf[1]; - buf[0] = '\0'; - - zstring_span<> zspan({buf, 1}); - - CHECK(generic::strlen(zspan.assume_z()) == 0); - CHECK(zspan.as_string_span().size() == 0); - CHECK(zspan.ensure_z().size() == 0); - } - - // create zspan from non-zero terminated string - { - char buf[1]; - buf[0] = 'a'; - - auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); - } - - // usage scenario: create zero-terminated temp file name and pass to a legacy API - { - char buf[10]; - - auto name = CreateTempName({buf, 10}); - if (!name.empty()) { - czstring<> str = name.assume_z(); - CHECK(generic::strlen(str) == 3); - CHECK(*(str + 3) == '\0'); - } - } -} - cwzstring_span<> CreateTempNameW(wstring_span<> span) { Expects(span.size() > 1); @@ -971,45 +133,6 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span) return {ret}; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("wzstring") -{ - - // create zspan from zero terminated string - { - wchar_t buf[1]; - buf[0] = L'\0'; - - wzstring_span<> zspan({buf, 1}); - - CHECK(generic::strnlen(zspan.assume_z(), 1) == 0); - CHECK(zspan.as_string_span().size() == 0); - CHECK(zspan.ensure_z().size() == 0); - } - - // create zspan from non-zero terminated string - { - wchar_t buf[1]; - buf[0] = L'a'; - - const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); - } - - // usage scenario: create zero-terminated temp file name and pass to a legacy API - { - wchar_t buf[10]; - - const auto name = CreateTempNameW({buf, 10}); - if (!name.empty()) { - cwzstring<> str = name.assume_z(); - CHECK(generic::strnlen(str, 10) == 3); - CHECK(*(str + 3) == L'\0'); - } - } -} - cu16zstring_span<> CreateTempNameU16(u16string_span<> span) { Expects(span.size() > 1); @@ -1027,45 +150,6 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span) return {ret}; } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("u16zstring") -{ - - // create zspan from zero terminated string - { - char16_t buf[1]; - buf[0] = L'\0'; - - u16zstring_span<> zspan({buf, 1}); - - CHECK(generic::strnlen(zspan.assume_z(), 1) == 0); - CHECK(zspan.as_string_span().size() == 0); - CHECK(zspan.ensure_z().size() == 0); - } - - // create zspan from non-zero terminated string - { - char16_t buf[1]; - buf[0] = u'a'; - - const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); - } - - // usage scenario: create zero-terminated temp file name and pass to a legacy API - { - char16_t buf[10]; - - const auto name = CreateTempNameU16({buf, 10}); - if (!name.empty()) { - cu16zstring<> str = name.assume_z(); - CHECK(generic::strnlen(str, 10) == 3); - CHECK(*(str + 3) == L'\0'); - } - } -} - cu32zstring_span<> CreateTempNameU32(u32string_span<> span) { Expects(span.size() > 1); @@ -1082,11 +166,936 @@ cu32zstring_span<> CreateTempNameU32(u32string_span<> span) auto ret = span.subspan(0, 4); return {ret}; } +} // namespace -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute -TEST_CASE("u32zstring") +TEST(string_span_tests, TestLiteralConstruction) { + cwstring_span<> v = ensure_z(L"Hello"); + EXPECT_TRUE(5 == v.length()); + +#ifdef CONFIRM_COMPILATION_ERRORS + wstring_span<> v2 = ensure0(L"Hello"); +#endif +} + +TEST(string_span_tests, TestConstructFromStdString) +{ + std::string s = "Hello there world"; + cstring_span<> v = s; + EXPECT_TRUE(v.length() == static_cast::index_type>(s.length())); +} + +TEST(string_span_tests, TestConstructFromStdVector) +{ + std::vector vec(5, 'h'); + string_span<> v{vec}; + EXPECT_TRUE(v.length() == static_cast::index_type>(vec.size())); +} + +TEST(string_span_tests, TestStackArrayConstruction) +{ + wchar_t stack_string[] = L"Hello"; + + { + cwstring_span<> v = ensure_z(stack_string); + EXPECT_TRUE(v.length() == 5); + } + + { + cwstring_span<> v = stack_string; + EXPECT_TRUE(v.length() == 5); + } + + { + wstring_span<> v = ensure_z(stack_string); + EXPECT_TRUE(v.length() == 5); + } + + { + wstring_span<> v = stack_string; + EXPECT_TRUE(v.length() == 5); + } +} + +TEST(string_span_tests, TestConstructFromConstCharPointer) +{ + const char* s = "Hello"; + cstring_span<> v = ensure_z(s); + EXPECT_TRUE(v.length() == 5); +} + +TEST(string_span_tests, TestConversionToConst) +{ + char stack_string[] = "Hello"; + string_span<> v = ensure_z(stack_string); + cstring_span<> v2 = v; + EXPECT_TRUE(v.length() == v2.length()); +} + +TEST(string_span_tests, TestConversionFromConst) +{ + char stack_string[] = "Hello"; + cstring_span<> v = ensure_z(stack_string); + (void) v; +#ifdef CONFIRM_COMPILATION_ERRORS + string_span<> v2 = v; + string_span<> v3 = "Hello"; +#endif +} + +TEST(string_span_tests, TestToString) +{ + auto s = gsl::to_string(cstring_span<>{}); + EXPECT_TRUE(s.length() == static_cast(0)); + + char stack_string[] = "Hello"; + cstring_span<> v = ensure_z(stack_string); + auto s2 = gsl::to_string(v); + EXPECT_TRUE(static_cast::index_type>(s2.length()) == v.length()); + EXPECT_TRUE(s2.length() == static_cast(5)); +} + +TEST(string_span_tests, TestToBasicString) +{ + auto s = gsl::to_basic_string, ::std::allocator>( + cstring_span<>{}); + EXPECT_TRUE(s.length() == static_cast(0)); + + char stack_string[] = "Hello"; + cstring_span<> v = ensure_z(stack_string); + auto s2 = gsl::to_basic_string, ::std::allocator>(v); + EXPECT_TRUE(static_cast::index_type>(s2.length()) == v.length()); + EXPECT_TRUE(s2.length() == static_cast(5)); +} + +TEST(string_span_tests, EqualityAndImplicitConstructors) +{ + { + cstring_span<> span = "Hello"; + cstring_span<> span1; + + // comparison to empty span + EXPECT_TRUE(span1 != span); + EXPECT_TRUE(span != span1); + } + + { + cstring_span<> span = "Hello"; + cstring_span<> span1 = "Hello1"; + + // comparison to different span + EXPECT_TRUE(span1 != span); + EXPECT_TRUE(span != span1); + } + + { + cstring_span<> span = "Hello"; + + const char ar[] = {'H', 'e', 'l', 'l', 'o'}; + const char ar1[] = "Hello"; + const char ar2[10] = "Hello"; + const char* ptr = "Hello"; + const std::string str = "Hello"; + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + gsl::span sp = ensure_z("Hello"); + + // comparison to literal + EXPECT_TRUE(span == cstring_span<>("Hello")); + + // comparison to static array with no null termination + EXPECT_TRUE(span == cstring_span<>(ar)); + + // comparison to static array with null at the end + EXPECT_TRUE(span == cstring_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_TRUE(span == cstring_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_TRUE(span == cstring_span<>(ptr, 5)); + + // comparison to string + EXPECT_TRUE(span == cstring_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_TRUE(span == cstring_span<>(vec)); + + // comparison to span + EXPECT_TRUE(span == cstring_span<>(sp)); + + // comparison to string_span + EXPECT_TRUE(span == span); + } + + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + + string_span<> span = ar; + + char ar1[] = "Hello"; + char ar2[10] = "Hello"; + char* ptr = ar; + std::string str = "Hello"; + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + gsl::span sp = ensure_z(ar1); + + // comparison to static array with no null termination + EXPECT_TRUE(span == string_span<>(ar)); + + // comparison to static array with null at the end + EXPECT_TRUE(span == string_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_TRUE(span == string_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_TRUE(span == string_span<>(ptr, 5)); + + // comparison to string + EXPECT_TRUE(span == string_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_TRUE(span == string_span<>(vec)); + + // comparison to span + EXPECT_TRUE(span == string_span<>(sp)); + + // comparison to string_span + EXPECT_TRUE(span == span); + } + + { + const char ar[] = {'H', 'e', 'l', 'l', 'o'}; + const char ar1[] = "Hello"; + const char ar2[10] = "Hello"; + const std::string str = "Hello"; + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const gsl::span sp = ensure_z("Hello"); + + cstring_span<> span = "Hello"; + + // const span, const other type + + EXPECT_TRUE(span == "Hello"); + EXPECT_TRUE(span == ar); + EXPECT_TRUE(span == ar1); + EXPECT_TRUE(span == ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + const char* ptr = "Hello"; + EXPECT_TRUE(span == ptr); +#endif + EXPECT_TRUE(span == str); + EXPECT_TRUE(span == vec); + EXPECT_TRUE(span == sp); + + EXPECT_TRUE("Hello" == span); + EXPECT_TRUE(ar == span); + EXPECT_TRUE(ar1 == span); + EXPECT_TRUE(ar2 == span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(ptr == span); +#endif + EXPECT_TRUE(str == span); + EXPECT_TRUE(vec == span); + EXPECT_TRUE(sp == span); + + // const span, non-const other type + + char _ar[] = {'H', 'e', 'l', 'l', 'o'}; + char _ar1[] = "Hello"; + char _ar2[10] = "Hello"; + char* _ptr = _ar; + std::string _str = "Hello"; + std::vector _vec = {'H', 'e', 'l', 'l', 'o'}; + gsl::span _sp{_ar, 5}; + + EXPECT_TRUE(span == _ar); + EXPECT_TRUE(span == _ar1); + EXPECT_TRUE(span == _ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(span == _ptr); +#endif + EXPECT_TRUE(span == _str); + EXPECT_TRUE(span == _vec); + EXPECT_TRUE(span == _sp); + + EXPECT_TRUE(_ar == span); + EXPECT_TRUE(_ar1 == span); + EXPECT_TRUE(_ar2 == span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(_ptr == span); +#endif + EXPECT_TRUE(_str == span); + EXPECT_TRUE(_vec == span); + EXPECT_TRUE(_sp == span); + + string_span<> _span{_ptr, 5}; + + // non-const span, non-const other type + + EXPECT_TRUE(_span == _ar); + EXPECT_TRUE(_span == _ar1); + EXPECT_TRUE(_span == _ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(_span == _ptr); +#endif + EXPECT_TRUE(_span == _str); + EXPECT_TRUE(_span == _vec); + EXPECT_TRUE(_span == _sp); + + EXPECT_TRUE(_ar == _span); + EXPECT_TRUE(_ar1 == _span); + EXPECT_TRUE(_ar2 == _span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(_ptr == _span); +#endif + EXPECT_TRUE(_str == _span); + EXPECT_TRUE(_vec == _span); + EXPECT_TRUE(_sp == _span); + + // non-const span, const other type + + EXPECT_TRUE(_span == "Hello"); + EXPECT_TRUE(_span == ar); + EXPECT_TRUE(_span == ar1); + EXPECT_TRUE(_span == ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(_span == ptr); +#endif + EXPECT_TRUE(_span == str); + EXPECT_TRUE(_span == vec); + EXPECT_TRUE(_span == sp); + + EXPECT_TRUE("Hello" == _span); + EXPECT_TRUE(ar == _span); + EXPECT_TRUE(ar1 == _span); + EXPECT_TRUE(ar2 == _span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(ptr == _span); +#endif + EXPECT_TRUE(str == _span); + EXPECT_TRUE(vec == _span); + EXPECT_TRUE(sp == _span); + + // two spans + + EXPECT_TRUE(_span == span); + EXPECT_TRUE(span == _span); + } + + { + std::vector str1 = {'H', 'e', 'l', 'l', 'o'}; + cstring_span<> span1 = str1; + std::vector str2 = std::move(str1); + cstring_span<> span2 = str2; + + // comparison of spans from the same vector before and after move (ok) + EXPECT_TRUE(span1 == span2); + } +} + +TEST(string_span_tests, ComparisonAndImplicitConstructors) +{ + { + cstring_span<> span = "Hello"; + + const char ar[] = {'H', 'e', 'l', 'l', 'o'}; + const char ar1[] = "Hello"; + const char ar2[10] = "Hello"; + const char* ptr = "Hello"; + const std::string str = "Hello"; + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + + // comparison to literal + EXPECT_TRUE(span < cstring_span<>("Helloo")); + EXPECT_TRUE(span > cstring_span<>("Hell")); + + // comparison to static array with no null termination + EXPECT_TRUE(span >= cstring_span<>(ar)); + + // comparison to static array with null at the end + EXPECT_TRUE(span <= cstring_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_TRUE(span >= cstring_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_TRUE(span <= cstring_span<>(ptr, 5)); + + // comparison to string + EXPECT_TRUE(span >= cstring_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_TRUE(span <= cstring_span<>(vec)); + } + + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + + string_span<> span = ar; + + char larr[] = "Hell"; + char rarr[] = "Helloo"; + + char ar1[] = "Hello"; + char ar2[10] = "Hello"; + char* ptr = ar; + std::string str = "Hello"; + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + + // comparison to static array with no null termination + EXPECT_TRUE(span <= string_span<>(ar)); + EXPECT_TRUE(span < string_span<>(rarr)); + EXPECT_TRUE(span > string_span<>(larr)); + + // comparison to static array with null at the end + EXPECT_TRUE(span >= string_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_TRUE(span <= string_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_TRUE(span >= string_span<>(ptr, 5)); + + // comparison to string + EXPECT_TRUE(span <= string_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_TRUE(span >= string_span<>(vec)); + } +} + +TEST(string_span_tests, ConstrutorsEnsureZ) +{ + // remove z from literals + { + cstring_span<> sp = "hello"; + EXPECT_TRUE(sp.length() == 5); + } + + // take the string as is + { + auto str = std::string("hello"); + cstring_span<> sp = str; + EXPECT_TRUE(sp.length() == 5); + } + + // ensure z on c strings + { + gsl::owner ptr = new char[3]; + + ptr[0] = 'a'; + ptr[1] = 'b'; + ptr[2] = '\0'; + + string_span<> span = ensure_z(ptr); + EXPECT_TRUE(span.length() == 2); + + delete[] ptr; + } +} + +TEST(string_span_tests, Constructors) +{ + // creating cstring_span + + // from span of a final extent + { + span sp = "Hello"; + cstring_span<> span = sp; + EXPECT_TRUE(span.length() == 6); + } + +// from const span of a final extent to non-const string_span +#ifdef CONFIRM_COMPILATION_ERRORS + { + span sp = "Hello"; + string_span<> span = sp; + EXPECT_TRUE(span.length() == 6); + } +#endif + +// from string temporary +#ifdef CONFIRM_COMPILATION_ERRORS + { + cstring_span<> span = std::string("Hello"); + } +#endif + + // default + { + cstring_span<> span; + EXPECT_TRUE(span.length() == 0); + } + + // from string literal + { + cstring_span<> span = "Hello"; + EXPECT_TRUE(span.length() == 5); + } + + // from const static array + { + const char ar[] = {'H', 'e', 'l', 'l', 'o'}; + cstring_span<> span = ar; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const static array + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + cstring_span<> span = ar; + EXPECT_TRUE(span.length() == 5); + } + + // from const ptr and length + { + const char* ptr = "Hello"; + cstring_span<> span{ptr, 5}; + EXPECT_TRUE(span.length() == 5); + } + + // from const ptr and length, include 0 + { + const char* ptr = "Hello"; + cstring_span<> span{ptr, 6}; + EXPECT_TRUE(span.length() == 6); + } + + // from const ptr and length, 0 inside + { + const char* ptr = "He\0lo"; + cstring_span<> span{ptr, 5}; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const ptr and length + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + char* ptr = ar; + cstring_span<> span{ptr, 5}; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const ptr and length, 0 inside + { + char ar[] = {'H', 'e', '\0', 'l', 'o'}; + char* ptr = ar; + cstring_span<> span{ptr, 5}; + EXPECT_TRUE(span.length() == 5); + } + + // from const string + { + const std::string str = "Hello"; + const cstring_span<> span = str; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const string + { + std::string str = "Hello"; + const cstring_span<> span = str; + EXPECT_TRUE(span.length() == 5); + } + + // from const vector + { + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const cstring_span<> span = vec; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const vector + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const cstring_span<> span = vec; + EXPECT_TRUE(span.length() == 5); + } + + // from const span + { + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const span inner = vec; + const cstring_span<> span = inner; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const span + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const span inner = vec; + const cstring_span<> span = inner; + EXPECT_TRUE(span.length() == 5); + } + + // from const string_span + { + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const cstring_span<> tmp = vec; + const cstring_span<> span = tmp; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const string_span + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> tmp = vec; + cstring_span<> span = tmp; + EXPECT_TRUE(span.length() == 5); + } + + // creating string_span + + // from string literal + { +#ifdef CONFIRM_COMPILATION_ERRORS + string_span<> span = "Hello"; +#endif + } + + // from const static array + { +#ifdef CONFIRM_COMPILATION_ERRORS + const char ar[] = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = ar; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from non-const static array + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = ar; + EXPECT_TRUE(span.length() == 5); + } + + // from const ptr and length + { +#ifdef CONFIRM_COMPILATION_ERRORS + const char* ptr = "Hello"; + string_span<> span{ptr, 5}; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from non-const ptr and length + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + char* ptr = ar; + string_span<> span{ptr, 5}; + EXPECT_TRUE(span.length() == 5); + } + + // from const string + { +#ifdef CONFIRM_COMPILATION_ERRORS + const std::string str = "Hello"; + string_span<> span = str; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from non-const string + { + std::string str = "Hello"; + string_span<> span = str; + EXPECT_TRUE(span.length() == 5); + } + + // from const vector + { +#ifdef CONFIRM_COMPILATION_ERRORS + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = vec; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from non-const vector + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = vec; + EXPECT_TRUE(span.length() == 5); + } + + // from const span + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const span inner = vec; + string_span<> span = inner; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from non-const span + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + span inner = vec; + string_span<> span = inner; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const span of non-const data from const vector + { +#ifdef CONFIRM_COMPILATION_ERRORS + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const span inner = vec; + string_span<> span = inner; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from const string_span + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + cstring_span<> tmp = vec; + string_span<> span = tmp; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from non-const string_span + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const string_span<> tmp = vec; + const string_span<> span = tmp; + EXPECT_TRUE(span.length() == 5); + } + + // from non-const string_span from const vector + { +#ifdef CONFIRM_COMPILATION_ERRORS + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> tmp = vec; + string_span<> span = tmp; + EXPECT_TRUE(span.length() == 5); +#endif + } + + // from const string_span of non-const data + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const string_span<> tmp = vec; + const string_span<> span = tmp; + EXPECT_TRUE(span.length() == 5); + } +} + +TEST(string_span_tests, MoveConstructors) +{ + // move string_span + { + cstring_span<> span = "Hello"; + const auto span1 = std::move(span); + EXPECT_TRUE(span1.length() == 5); + } + { + cstring_span<> span = "Hello"; + const auto span1 = move_wrapper(std::move(span)); + EXPECT_TRUE(span1.length() == 5); + } + { + cstring_span<> span = "Hello"; + const auto span1 = move_wrapper(std::move(span)); + EXPECT_TRUE(span1.length() == 5); + } + + // move span + { + span span = ensure_z("Hello"); + const cstring_span<> span1 = std::move(span); + EXPECT_TRUE(span1.length() == 5); + } + { + span span = ensure_z("Hello"); + const cstring_span<> span2 = move_wrapper(std::move(span)); + EXPECT_TRUE(span2.length() == 5); + } + + // move string + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::string str = "Hello"; + string_span<> span = std::move(str); + EXPECT_TRUE(span.length() == 5); +#endif + } + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::string str = "Hello"; + string_span<> span = move_wrapper(std::move(str)); + EXPECT_TRUE(span.length() == 5); +#endif + } + { +#ifdef CONFIRM_COMPILATION_ERRORS + use(create()); +#endif + } + + // move container + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = std::move(vec); + EXPECT_TRUE(span.length() == 5); +#endif + } + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = move_wrapper>(std::move(vec)); + EXPECT_TRUE(span.length() == 5); +#endif + } + { +#ifdef CONFIRM_COMPILATION_ERRORS + use(create>()); +#endif + } +} + +TEST(string_span_tests, Conversion) +{ +#ifdef CONFIRM_COMPILATION_ERRORS + cstring_span<> span = "Hello"; + cwstring_span<> wspan{span}; + EXPECT_TRUE(wspan.length() == 5); +#endif +} + +TEST(string_span_tests, zstring) +{ + std::set_terminate([] { + std::cerr << "Expected Death. zstring"; + std::abort(); + }); + + // create zspan from zero terminated string + { + char buf[1]; + buf[0] = '\0'; + + zstring_span<> zspan({buf, 1}); + + EXPECT_TRUE(generic::strlen(zspan.assume_z()) == 0); + EXPECT_TRUE(zspan.as_string_span().size() == 0); + EXPECT_TRUE(zspan.ensure_z().size() == 0); + } + + // create zspan from non-zero terminated string + { + char buf[1]; + buf[0] = 'a'; + + auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); }; + EXPECT_DEATH(workaround_macro(), deathstring); + } + + // usage scenario: create zero-terminated temp file name and pass to a legacy API + { + char buf[10]; + + auto name = CreateTempName({buf, 10}); + if (!name.empty()) { + czstring<> str = name.assume_z(); + EXPECT_TRUE(generic::strlen(str) == 3); + EXPECT_TRUE(*(str + 3) == '\0'); + } + } +} + +TEST(string_span_tests, wzstring) +{ + std::set_terminate([] { + std::cerr << "Expected Death. wzstring"; + std::abort(); + }); + + // create zspan from zero terminated string + { + wchar_t buf[1]; + buf[0] = L'\0'; + + wzstring_span<> zspan({buf, 1}); + + EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0); + EXPECT_TRUE(zspan.as_string_span().size() == 0); + EXPECT_TRUE(zspan.ensure_z().size() == 0); + } + + // create zspan from non-zero terminated string + { + wchar_t buf[1]; + buf[0] = L'a'; + + const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); }; + EXPECT_DEATH(workaround_macro(), deathstring); + } + + // usage scenario: create zero-terminated temp file name and pass to a legacy API + { + wchar_t buf[10]; + + const auto name = CreateTempNameW({buf, 10}); + if (!name.empty()) { + cwzstring<> str = name.assume_z(); + EXPECT_TRUE(generic::strnlen(str, 10) == 3); + EXPECT_TRUE(*(str + 3) == L'\0'); + } + } +} + +TEST(string_span_tests, u16zstring) +{ + std::set_terminate([] { + std::cerr << "Expected Death. u16zstring"; + std::abort(); + }); + + // create zspan from zero terminated string + { + char16_t buf[1]; + buf[0] = L'\0'; + + u16zstring_span<> zspan({buf, 1}); + + EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0); + EXPECT_TRUE(zspan.as_string_span().size() == 0); + EXPECT_TRUE(zspan.ensure_z().size() == 0); + } + + // create zspan from non-zero terminated string + { + char16_t buf[1]; + buf[0] = u'a'; + + const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); }; + EXPECT_DEATH(workaround_macro(), deathstring); + } + + // usage scenario: create zero-terminated temp file name and pass to a legacy API + { + char16_t buf[10]; + + const auto name = CreateTempNameU16({buf, 10}); + if (!name.empty()) { + cu16zstring<> str = name.assume_z(); + EXPECT_TRUE(generic::strnlen(str, 10) == 3); + EXPECT_TRUE(*(str + 3) == L'\0'); + } + } +} + +TEST(string_span_tests, u32zstring) +{ + std::set_terminate([] { + std::cerr << "Expected Death. u31zstring"; + std::abort(); + }); // create zspan from zero terminated string { @@ -1095,9 +1104,9 @@ TEST_CASE("u32zstring") u32zstring_span<> zspan({buf, 1}); - CHECK(generic::strnlen(zspan.assume_z(), 1) == 0); - CHECK(zspan.as_string_span().size() == 0); - CHECK(zspan.ensure_z().size() == 0); + EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0); + EXPECT_TRUE(zspan.as_string_span().size() == 0); + EXPECT_TRUE(zspan.ensure_z().size() == 0); } // create zspan from non-zero terminated string @@ -1106,7 +1115,7 @@ TEST_CASE("u32zstring") buf[0] = u'a'; const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), deathstring); } // usage scenario: create zero-terminated temp file name and pass to a legacy API @@ -1116,118 +1125,116 @@ TEST_CASE("u32zstring") const auto name = CreateTempNameU32({buf, 10}); if (!name.empty()) { cu32zstring<> str = name.assume_z(); - CHECK(generic::strnlen(str, 10) == 3); - CHECK(*(str + 3) == L'\0'); + EXPECT_TRUE(generic::strnlen(str, 10) == 3); + EXPECT_TRUE(*(str + 3) == L'\0'); } } } -TEST_CASE("Issue305") +TEST(string_span_tests, Issue305) { std::map, int> foo = {{"foo", 0}, {"bar", 1}}; - CHECK(foo["foo"] == 0); - CHECK(foo["bar"] == 1); + EXPECT_TRUE(foo["foo"] == 0); + EXPECT_TRUE(foo["bar"] == 1); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -TEST_CASE("char16_t type") +TEST(string_span_tests, char16_t_type) { gsl::cu16string_span<> ss1 = gsl::ensure_z(u"abc"); - CHECK(ss1.size() == 3); - CHECK(ss1.size_bytes() == 6); + EXPECT_TRUE(ss1.size() == 3); + EXPECT_TRUE(ss1.size_bytes() == 6); std::u16string s1 = gsl::to_string(ss1); - CHECK(s1 == u"abc"); + EXPECT_TRUE(s1 == u"abc"); std::u16string s2 = u"abc"; gsl::u16string_span<> ss2 = s2; - CHECK(ss2.size() == 3); + EXPECT_TRUE(ss2.size() == 3); gsl::u16string_span<> ss3 = ss2.subspan(1, 1); - CHECK(ss3.size() == 1); - CHECK(ss3[0] == u'b'); + EXPECT_TRUE(ss3.size() == 1); + EXPECT_TRUE(ss3[0] == u'b'); char16_t buf[4]{u'a', u'b', u'c', u'\0'}; gsl::u16string_span<> ss4{buf, 4}; - CHECK(ss4[3] == u'\0'); + EXPECT_TRUE(ss4[3] == u'\0'); gsl::cu16zstring_span<> ss5(u"abc"); - CHECK(ss5.as_string_span().size() == 3); + EXPECT_TRUE((ss5.as_string_span().size()) == 3); gsl::cu16string_span<> ss6 = ss5.as_string_span(); - CHECK(ss6 == ss1); + EXPECT_TRUE(ss6 == ss1); std::vector v7 = {u'a', u'b', u'c'}; gsl::cu16string_span<> ss7{v7}; - CHECK(ss7 == ss1); + EXPECT_TRUE(ss7 == ss1); gsl::cu16string_span<> ss8 = gsl::ensure_z(u"abc"); gsl::cu16string_span<> ss9 = gsl::ensure_z(u"abc"); - CHECK(ss8 == ss9); + EXPECT_TRUE(ss8 == ss9); ss9 = gsl::ensure_z(u"abd"); - CHECK(ss8 < ss9); - CHECK(ss8 <= ss9); - CHECK(ss8 != ss9); + EXPECT_TRUE(ss8 < ss9); + EXPECT_TRUE(ss8 <= ss9); + EXPECT_TRUE(ss8 != ss9); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute -TEST_CASE("char32_t type") +TEST(string_span_tests, char32_t_type) { gsl::cu32string_span<> ss1 = gsl::ensure_z(U"abc"); - CHECK(ss1.size() == 3); - CHECK(ss1.size_bytes() == 12); + EXPECT_TRUE(ss1.size() == 3); + EXPECT_TRUE(ss1.size_bytes() == 12); std::u32string s1 = gsl::to_string(ss1); - CHECK(s1 == U"abc"); + EXPECT_TRUE(s1 == U"abc"); std::u32string s2 = U"abc"; gsl::u32string_span<> ss2 = s2; - CHECK(ss2.size() == 3); + EXPECT_TRUE(ss2.size() == 3); gsl::u32string_span<> ss3 = ss2.subspan(1, 1); - CHECK(ss3.size() == 1); - CHECK(ss3[0] == U'b'); + EXPECT_TRUE(ss3.size() == 1); + EXPECT_TRUE(ss3[0] == U'b'); char32_t buf[4]{U'a', U'b', U'c', U'\0'}; gsl::u32string_span<> ss4{buf, 4}; - CHECK(ss4[3] == u'\0'); + EXPECT_TRUE(ss4[3] == u'\0'); gsl::cu32zstring_span<> ss5(U"abc"); - CHECK(ss5.as_string_span().size() == 3); + EXPECT_TRUE(ss5.as_string_span().size() == 3); gsl::cu32string_span<> ss6 = ss5.as_string_span(); - CHECK(ss6 == ss1); + EXPECT_TRUE(ss6 == ss1); gsl::cu32string_span<> ss8 = gsl::ensure_z(U"abc"); gsl::cu32string_span<> ss9 = gsl::ensure_z(U"abc"); - CHECK(ss8 == ss9); + EXPECT_TRUE(ss8 == ss9); ss9 = gsl::ensure_z(U"abd"); - CHECK(ss8 < ss9); - CHECK(ss8 <= ss9); - CHECK(ss8 != ss9); + EXPECT_TRUE(ss8 < ss9); + EXPECT_TRUE(ss8 <= ss9); + EXPECT_TRUE(ss8 != ss9); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("as_bytes") +TEST(string_span_tests, as_bytes) { cwzstring_span<> v(L"qwerty"); const auto s = v.as_string_span(); const auto bs = as_bytes(s); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.size() == s.size_bytes()); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("as_writeable_bytes") +TEST(string_span_tests, as_writeable_bytes) { wchar_t buf[]{L"qwerty"}; wzstring_span<> v(buf); const auto s = v.as_string_span(); const auto bs = as_writeable_bytes(s); - CHECK(static_cast(bs.data()) == static_cast(s.data())); - CHECK(bs.size() == s.size_bytes()); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); } + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__ diff --git a/tests/test.cpp b/tests/test.cpp deleted file mode 100644 index 47daf5c..0000000 --- a/tests/test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// 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_MAIN - -#ifdef _MSC_VER - -// blanket turn off warnings from CppCoreCheck from catch -// so people aren't annoyed by them when running the tool. -#include -#pragma warning(disable : ALL_CODE_ANALYSIS_WARNINGS) // from catch -#endif // _MSC_VER - -#include diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 3d54ce6..d779384 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -21,7 +21,20 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#if __clang__ || __GNUC__ +//disable warnings from gtest +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif // __clang__ || __GNUC__ + +#if __clang__ +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#pragma GCC diagnostic ignored "-Wused-but-marked-unused" +#pragma GCC diagnostic ignored "-Wcovered-switch-default" +#endif // __clang__ + + +#include #include // for narrow, finally, narrow_cast, narrowing_e... @@ -33,101 +46,114 @@ using namespace gsl; -TEST_CASE("sanity check for gsl::index typedef") +namespace +{ +static constexpr char deathstring[] = "Expected Death"; +void f(int& i) { i += 1; } +static int j = 0; +void g() { j += 1; } +} + + +TEST(utils_tests, sanity_check_for_gsl_index_typedef) { static_assert(std::is_same::value, "gsl::index represents wrong arithmetic type"); } -void f(int& i) { i += 1; } - -TEST_CASE("finally_lambda") +TEST(utils_tests, finally_lambda) { int i = 0; { auto _ = finally([&]() { f(i); }); - CHECK(i == 0); + EXPECT_TRUE(i == 0); } - CHECK(i == 1); + EXPECT_TRUE(i == 1); } -TEST_CASE("finally_lambda_move") +TEST(utils_tests, finally_lambda_move) { int i = 0; { auto _1 = finally([&]() { f(i); }); { auto _2 = std::move(_1); - CHECK(i == 0); + EXPECT_TRUE(i == 0); } - CHECK(i == 1); + EXPECT_TRUE(i == 1); { auto _2 = std::move(_1); - CHECK(i == 1); + EXPECT_TRUE(i == 1); } - CHECK(i == 1); + EXPECT_TRUE(i == 1); } - CHECK(i == 1); + EXPECT_TRUE(i == 1); } -TEST_CASE("finally_function_with_bind") +TEST(utils_tests, finally_function_with_bind) { int i = 0; { auto _ = finally(std::bind(&f, std::ref(i))); - CHECK(i == 0); + EXPECT_TRUE(i == 0); } - CHECK(i == 1); + EXPECT_TRUE(i == 1); } -static int j = 0; -void g() { j += 1; } -TEST_CASE("finally_function_ptr") +TEST(utils_tests, finally_function_ptr) { j = 0; { auto _ = finally(&g); - CHECK(j == 0); + EXPECT_TRUE(j == 0); } - CHECK(j == 1); + EXPECT_TRUE(j == 1); } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("narrow_cast") +TEST(utils_tests, narrow_cast) { int n = 120; char c = narrow_cast(n); - CHECK(c == 120); + EXPECT_TRUE(c == 120); n = 300; unsigned char uc = narrow_cast(n); - CHECK(uc == 44); + EXPECT_TRUE(uc == 44); } -GSL_SUPPRESS(con.5) // NO-FORMAT: attribute -TEST_CASE("narrow") +TEST(utils_tests, narrow) { + std::set_terminate([] { + std::cerr << "Expected Death. narrow"; + std::abort(); + }); + int n = 120; const char c = narrow(n); - CHECK(c == 120); + EXPECT_TRUE(c == 120); n = 300; - CHECK_THROWS_AS(narrow(n), narrowing_error); + EXPECT_DEATH(narrow(n), deathstring); const auto int32_max = std::numeric_limits::max(); const auto int32_min = std::numeric_limits::min(); - CHECK(narrow(int32_t(0)) == 0); - CHECK(narrow(int32_t(1)) == 1); - CHECK(narrow(int32_max) == static_cast(int32_max)); + EXPECT_TRUE(narrow(int32_t(0)) == 0); + EXPECT_TRUE(narrow(int32_t(1)) == 1); + EXPECT_TRUE(narrow(int32_max) == static_cast(int32_max)); - CHECK_THROWS_AS(narrow(int32_t(-1)), narrowing_error); - CHECK_THROWS_AS(narrow(int32_min), narrowing_error); + EXPECT_DEATH(narrow(int32_t(-1)), deathstring); + EXPECT_DEATH(narrow(int32_min), deathstring); n = -42; - CHECK_THROWS_AS(narrow(n), narrowing_error); + EXPECT_DEATH(narrow(n), deathstring); #if GSL_CONSTEXPR_NARROW static_assert(narrow(120) == 120, "Fix GSL_CONSTEXPR_NARROW"); #endif + } + +#if __clang__ || __GNUC__ +#pragma GCC diagnostic pop +#endif // __clang__ || __GNUC__