From 2b10729386062479641951e822e4257066655863 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Tue, 3 Dec 2019 14:32:25 -0800 Subject: [PATCH] gtest migration --- include/gsl/gsl_assert | 41 - tests/CMakeLists.txt | 83 +- tests/CMakeLists.txt.in | 14 + tests/algorithm_tests.cpp | 53 +- tests/assertion_tests.cpp | 24 +- tests/at_tests.cpp | 76 +- tests/bounds_tests.cpp | 22 +- tests/byte_tests.cpp | 179 ++- tests/multi_span_tests.cpp | 1071 ++++++------- tests/notnull_tests.cpp | 195 ++- tests/owner_tests.cpp | 13 +- tests/span_tests.cpp | 2714 ++++++++++++++++---------------- tests/strict_notnull_tests.cpp | 42 +- tests/strided_span_tests.cpp | 495 +++--- tests/string_span_tests.cpp | 1949 +++++++++++------------ tests/test.cpp | 1 - tests/utils_tests.cpp | 69 +- 17 files changed, 3453 insertions(+), 3588 deletions(-) create mode 100644 tests/CMakeLists.txt.in diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index c704633..c707030 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -50,19 +50,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 +81,6 @@ namespace gsl { -struct fail_fast : public std::logic_error -{ - explicit fail_fast(char const* const message) : std::logic_error(message) {} -}; namespace details { @@ -128,7 +111,6 @@ namespace details #endif } -#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) template [[noreturn]] void throw_exception(Exception&&) noexcept @@ -136,37 +118,14 @@ namespace details 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/tests/CMakeLists.txt b/tests/CMakeLists.txt index 832513f..7b9dd22 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,9 +133,6 @@ 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} /W4 @@ -184,16 +173,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} @@ -203,5 +188,5 @@ function(add_gsl_test_noexcept name) set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests_noexcept") endfunction() -add_gsl_test_noexcept(no_exception_throw_tests) -add_gsl_test_noexcept(no_exception_ensure_tests) +# add_gsl_test_noexcept(no_exception_throw_tests) +# add_gsl_test_noexcept(no_exception_ensure_tests) 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..9345e95 100644 --- a/tests/algorithm_tests.cpp +++ b/tests/algorithm_tests.cpp @@ -20,7 +20,7 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK, CHE... +#include #include // for copy #include // for span @@ -35,9 +35,7 @@ struct fail_fast; 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 { @@ -51,8 +49,8 @@ TEST_CASE("same_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(dst[i + src.size()], src[i]); } } @@ -68,8 +66,8 @@ TEST_CASE("same_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(dst[i + src.size()], src[i]); } } @@ -85,8 +83,8 @@ TEST_CASE("same_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(dst[i + src.size()], src[i]); } } @@ -102,16 +100,13 @@ TEST_CASE("same_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(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 { @@ -125,8 +120,8 @@ TEST_CASE("compatible_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(dst[i + src.size()], src[i]); } } @@ -142,8 +137,8 @@ TEST_CASE("compatible_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(dst[i + src.size()], src[i]); } } @@ -159,8 +154,8 @@ TEST_CASE("compatible_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(dst[i + src.size()], src[i]); } } @@ -176,14 +171,14 @@ TEST_CASE("compatible_type") 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]); + EXPECT_EQ(dst[i], src[i]); + EXPECT_EQ(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,7 +196,7 @@ TEST_CASE("incompatible_type") } #endif -TEST_CASE("small_destination_span") +TEST(algorithm_tests, small_destination_span) { std::array src{1, 2, 3, 4}; std::array dst{}; @@ -211,9 +206,9 @@ 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), ".*"); + EXPECT_DEATH(copy(src_span_dyn, dst_span_static), ".*"); + EXPECT_DEATH(copy(src_span_static, dst_span_dyn), ".*"); #ifdef CONFIRM_COMPILATION_ERRORS copy(src_span_static, dst_span_static); diff --git a/tests/assertion_tests.cpp b/tests/assertion_tests.cpp index 0c509ad..6aa3830 100644 --- a/tests/assertion_tests.cpp +++ b/tests/assertion_tests.cpp @@ -20,33 +20,37 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK, CHECK... +#include #include // for fail_fast (ptr only), Ensures, Expects using namespace gsl; +namespace +{ 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); + EXPECT_EQ(f(2), 2); + EXPECT_DEATH(f(10), ".*"); +} + + +TEST(assertion_tests, ensures) +{ + EXPECT_EQ(g(2), 3); + EXPECT_DEATH(g(9), ".*"); } diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 7f07be0..fb007b8 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -20,7 +20,7 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK_THROW... +#include #include // for at @@ -29,88 +29,70 @@ #include // for initializer_list #include // for vector - -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_EQ(&gsl::at(a, i), &a[i]); + EXPECT_EQ(&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); + EXPECT_DEATH(gsl::at(a, -1), ".*"); + EXPECT_DEATH(gsl::at(a, 4), ".*"); + EXPECT_DEATH(gsl::at(c_a, -1), ".*"); + EXPECT_DEATH(gsl::at(c_a, 4), ".*"); } -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_EQ(&gsl::at(a, i), &a[static_cast(i)]); + EXPECT_EQ(&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); + EXPECT_DEATH(gsl::at(a, -1), ".*"); + EXPECT_DEATH(gsl::at(a, 4), ".*"); + EXPECT_DEATH(gsl::at(c_a, -1), ".*"); + EXPECT_DEATH(gsl::at(c_a, 4), ".*"); } -GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute -TEST_CASE("StdVector") +TEST(at_tests, StdVector) { 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_EQ(&gsl::at(a, i), &a[static_cast(i)]); + EXPECT_EQ(&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); + EXPECT_DEATH(gsl::at(a, -1), ".*"); + EXPECT_DEATH(gsl::at(a, 4), ".*"); + EXPECT_DEATH(gsl::at(c_a, -1), ".*"); + EXPECT_DEATH(gsl::at(c_a, 4), ".*"); } -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_EQ(gsl::at(a, i), i + 1); + EXPECT_EQ(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); + EXPECT_DEATH(gsl::at(a, -1), ".*"); + EXPECT_DEATH(gsl::at(a, 4), ".*"); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), ".*"); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), ".*"); } #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}; diff --git a/tests/bounds_tests.cpp b/tests/bounds_tests.cpp index d72e31a..d8a9793 100644 --- a/tests/bounds_tests.cpp +++ b/tests/bounds_tests.cpp @@ -26,7 +26,7 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif -#include // for AssertionHandler, StringRef, TEST_CASE +#include #include // for static_bounds, static_bounds_dynamic_range_t @@ -44,8 +44,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 +56,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 +65,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 +83,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; @@ -108,12 +102,12 @@ TEST_CASE("bounds_convertible") static_bounds<34> b6; 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_EQ(b5, b6); + EXPECT_EQ(b5.size(), b6.size()); } #ifdef CONFIRM_COMPILATION_ERRORS diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp index d6634bb..0a8a1f6 100644 --- a/tests/byte_tests.cpp +++ b/tests/byte_tests.cpp @@ -20,7 +20,7 @@ #pragma warning(disable : 26440 26426) // from catch #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#include #include // for to_byte, to_integer, byte, operator&, ope... @@ -29,104 +29,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); } } diff --git a/tests/multi_span_tests.cpp b/tests/multi_span_tests.cpp index 0aa0ff9..ef0a4d4 100644 --- a/tests/multi_span_tests.cpp +++ b/tests/multi_span_tests.cpp @@ -17,8 +17,8 @@ #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 @@ -27,7 +27,7 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif -#include // for AssertionHandler, StringRef, CHECK, CHECK... +#include #include // for byte #include // for narrow_cast @@ -58,149 +58,246 @@ struct BaseClass struct DerivedClass : BaseClass { }; + +void overloaded_func(multi_span exp, int expected_value) +{ + for (auto val : exp) { EXPECT_EQ(val, expected_value); } +} + +void overloaded_func(multi_span exp, char expected_value) +{ + for (auto val : exp) { EXPECT_EQ(val, expected_value); } +} + +void fixed_func(multi_span exp, int expected_value) +{ + for (auto val : exp) { EXPECT_EQ(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_EQ(section.size(), length); + for (auto i = 0; i < section.size(); ++i) { EXPECT_EQ(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_EQ(section[idx], av[i][1]); + } + + EXPECT_EQ(section.bounds().index_bounds()[0], length); + EXPECT_EQ(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_EQ(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_EQ(num, av[idx][1]); + sum += num; + idx++; + } + + EXPECT_EQ(sum, check_sum); + } + { + auto idx = length - 1; + auto sum = 0; + for (auto iter = section.rbegin(); iter != section.rend(); ++iter) + { + EXPECT_EQ(*iter, av[idx][1]); + sum += *iter; + idx--; + } + + EXPECT_EQ(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_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(cs.data(), nullptr); } { multi_span s; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(cs.data(), nullptr); } { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s; - CHECK((s.length() == 1 && s.data() == nullptr)); // explains why it can't compile + EXPECT_EQ(s.length(), 1); + EXPECT_EQ(s.data(), nullptr); // explains why it can't compile #endif } { multi_span s{}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs{}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(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_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs = nullptr; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(cs.data(), nullptr); } { multi_span s = nullptr; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs = nullptr; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(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_EQ(s.length(), 1); + EXPECT_EQ(s.data(), nullptr); // explains why it can't compile #endif } { multi_span s{nullptr}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs{nullptr}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(cs.data(), nullptr); } { multi_span s{nullptr}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs{nullptr}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(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_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs{nullptr, 0}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(cs.data(), nullptr); } { multi_span s{nullptr, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs{nullptr, 0}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(cs.data(), nullptr); } { auto workaround_macro = []() { const multi_span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); auto const_workaround_macro = []() { const multi_span cs{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + EXPECT_DEATH(const_workaround_macro(), ".*"); } { auto workaround_macro = []() { const multi_span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); auto const_workaround_macro = []() { const multi_span s{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + EXPECT_DEATH(const_workaround_macro(), ".*"); } { multi_span s{nullptr, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); multi_span cs{nullptr, 0}; - CHECK((cs.length() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.length(), 0); + EXPECT_EQ(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_EQ(s.length(), 1); + EXPECT_EQ(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_EQ(s.length(), 1); + EXPECT_EQ(s.data(), &i); + EXPECT_EQ(s[0], 5); multi_span cs = i; - CHECK((cs.length() == 1 && cs.data() == &i)); - CHECK(cs[0] == 5); + EXPECT_EQ(cs.length(), 1); + EXPECT_EQ(cs.data(), &i); + EXPECT_EQ(cs[0], 5); } { @@ -213,20 +310,23 @@ TEST_CASE("from_element_constructor") { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s = i; - CHECK((s.length() == 0 && s.data() == &i)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), &i); #endif } { multi_span s = i; - CHECK((s.length() == 1 && s.data() == &i)); - CHECK(s[0] == 5); + EXPECT_EQ(s.length(), 1); + EXPECT_EQ(s.data(), &i); + EXPECT_EQ(s[0], 5); } { #ifdef CONFIRM_COMPILATION_ERRORS multi_span s = i; - CHECK((s.length() == 2 && s.data() == &i)); + EXPECT_EQ(s.length(), 2); + EXPECT_EQ(s.data(), &i); #endif } @@ -239,101 +339,110 @@ 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_EQ(s.length(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(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_EQ(s.length(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[1], 2); } { int* p = nullptr; multi_span s{p, 0}; - CHECK((s.length() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), nullptr); } { int* p = nullptr; auto workaround_macro = [=]() { const multi_span s{p, 2}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } } -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_EQ(s.length(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(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_EQ(s.length(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[1], 2); } { multi_span s{&arr[0], &arr[0]}; - CHECK((s.length() == 0 && s.data() == &arr[0])); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), &arr[0]); } { multi_span s{&arr[0], &arr[0]}; - CHECK((s.length() == 0 && s.data() == &arr[0])); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), &arr[0]); } { auto workaround_macro = [&]() { const multi_span s{&arr[1], &arr[0]}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { int* p = nullptr; auto workaround_macro = [&]() { const multi_span s{&arr[0], p}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { int* p = nullptr; auto workaround_macro = [&]() { const multi_span s{p, p}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { int* p = nullptr; auto workaround_macro = [&]() { const multi_span s{&arr[0], p}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } } -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_EQ(s.length(), 5); + EXPECT_EQ(s.data(), &arr[0]); } { multi_span s{arr}; - CHECK((s.length() == 5 && s.data() == &arr[0])); + EXPECT_EQ(s.length(), 5); + EXPECT_EQ(s.data(), &arr[0]); } { @@ -344,20 +453,24 @@ TEST_CASE("from_array_constructor") { multi_span s{arr}; - CHECK((s.length() == 0 && s.data() == &arr[0])); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(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_EQ(s.length(), 6); + EXPECT_EQ(s.data(), &arr2d[0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[5], 6); } { multi_span s{arr2d}; - CHECK((s.length() == 0 && s.data() == &arr2d[0][0])); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), &arr2d[0][0]); } { @@ -368,8 +481,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_EQ(s.length(), 6); + EXPECT_EQ(s.data(), &arr2d[0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[5], 6); } { @@ -380,14 +495,16 @@ TEST_CASE("from_array_constructor") { multi_span s{arr2d[0]}; - CHECK((s.length() == 1 && s.data() == &arr2d[0])); + EXPECT_EQ(s.length(), 1); + EXPECT_EQ(s.data(), &arr2d[0]); } { multi_span s{arr2d}; - CHECK((s.length() == 6 && s.data() == &arr2d[0][0])); + EXPECT_EQ(s.length(), 6); + EXPECT_EQ(s.data(), &arr2d[0][0]); auto workaround_macro = [&]() { return s[{1, 2}] == 6; }; - CHECK(workaround_macro()); + EXPECT_TRUE(workaround_macro()); } { @@ -400,13 +517,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_EQ(s.length(), 12); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[11], 12); } { multi_span s{arr3d}; - CHECK((s.length() == 0 && s.data() == &arr3d[0][0][0])); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); } { @@ -417,8 +537,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_EQ(s.length(), 12); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[5], 6); } { @@ -429,14 +551,16 @@ TEST_CASE("from_array_constructor") { multi_span s{arr3d[0]}; - CHECK((s.length() == 1 && s.data() == &arr3d[0])); + EXPECT_EQ(s.length(), 1); + EXPECT_EQ(s.data(), &arr3d[0]); } { multi_span s{arr3d}; - CHECK((s.length() == 12 && s.data() == &arr3d[0][0][0])); + EXPECT_EQ(s.length(), 12); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); auto workaround_macro = [&]() { return s[{2, 1, 0}] == 11; }; - CHECK(workaround_macro()); + EXPECT_TRUE(workaround_macro()); } { @@ -446,81 +570,88 @@ 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]; { 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_EQ(s.length(), 120); + EXPECT_EQ(s.data(), &arr[0][0][0]); + EXPECT_DEATH(s[10][3][4], ".*"); } { multi_span s(arr, 10); - CHECK((s.length() == 120 && s.data() == &arr[0][0][0])); + EXPECT_EQ(s.length(), 120); + EXPECT_EQ(s.data(), &arr[0][0][0]); } { multi_span s(arr, 10); - CHECK((s.length() == 120 && s.data() == &arr[0][0][0])); + EXPECT_EQ(s.length(), 120); + EXPECT_EQ(s.data(), &arr[0][0][0]); } { multi_span s(arr, 0); - CHECK((s.length() == 0 && s.data() == &arr[0][0][0])); + EXPECT_EQ(s.length(), 0); + EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); + EXPECT_EQ(s.data(), arr.data()); multi_span cs{arr}; - CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); + EXPECT_EQ(cs.size(), narrow_cast(arr.size())); + EXPECT_EQ(cs.data(), arr.data()); } { multi_span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); + EXPECT_EQ(s.size(), narrow_cast(arr.size())); + EXPECT_EQ(s.data(), arr.data()); multi_span cs{arr}; - CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); + EXPECT_EQ(cs.size(), narrow_cast(arr.size())); + EXPECT_EQ(cs.data(), arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); + EXPECT_EQ(s.size(), 2); + EXPECT_EQ(s.data(), arr.data()); multi_span cs{arr}; - CHECK((cs.size() == 2 && cs.data() == arr.data())); + EXPECT_EQ(cs.size(), 2); + EXPECT_EQ(cs.data(), arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), arr.data()); multi_span cs{arr}; - CHECK((cs.size() == 0 && cs.data() == arr.data())); + EXPECT_EQ(cs.size(), 0); + EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); + // EXPECT_EQ(s.data(), arr.data()); //} { @@ -539,36 +670,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_EQ(s.size(), narrow_cast(arr.size())); + EXPECT_EQ(s.data(), arr.data()); } { multi_span s{arr}; - CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); + EXPECT_EQ(s.size(), narrow_cast(arr.size())); + EXPECT_EQ(s.data(), arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 2 && s.data() == arr.data())); + EXPECT_EQ(s.size(), 2); + EXPECT_EQ(s.data(), arr.data()); } { multi_span s{arr}; - CHECK((s.size() == 0 && s.data() == arr.data())); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); + // EXPECT_EQ(s.data(), arr.data()); //} { @@ -587,18 +722,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_EQ(s.size(), narrow_cast(v.size())); + EXPECT_EQ(s.data(), v.data()); multi_span cs{v}; - CHECK((cs.size() == narrow_cast(v.size()) && cs.data() == v.data())); + EXPECT_EQ(cs.size(), narrow_cast(v.size())); + EXPECT_EQ(cs.data(), v.data()); } std::string str = "hello"; @@ -607,10 +743,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_EQ(s.size(), narrow_cast(str.size())); + EXPECT_EQ(s.data(), str.data()); #endif multi_span cs{str}; - CHECK((cs.size() == narrow_cast(str.size()) && cs.data() == str.data())); + EXPECT_EQ(cs.size(), narrow_cast(str.size())); + EXPECT_EQ(cs.data(), str.data()); } { @@ -618,7 +756,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_EQ(cs.size(), narrow_cast(cstr.size())); + EXPECT_EQ(cs.data(), cstr.data()); } { @@ -661,15 +800,13 @@ 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); auto f = [&]() { multi_span av1(nullptr); }; - CHECK_THROWS_AS(f(), fail_fast); + EXPECT_DEATH(f(), ".*"); #endif #ifdef CONFIRM_COMPILATION_ERRORS @@ -690,38 +827,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_EQ(s2.length(), 3); + EXPECT_EQ(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_EQ(s.length(), 2); + EXPECT_EQ(s.data(), &arr[1]); }; use_span(get_temp_span()); s1 = get_temp_span(); - CHECK((s1.length() == 2 && s1.data() == &arr[1])); + EXPECT_EQ(s1.length(), 2); + EXPECT_EQ(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 +870,310 @@ 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_EQ(av8.size(), av6.size()); + for (auto i = 0; i < av8.size(); i++) { EXPECT_EQ(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_EQ(av.first<2>().bounds(), static_bounds<2>()); + EXPECT_EQ(av.first<2>().length(), 2); + EXPECT_EQ(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_EQ(av.first<0>().bounds(), static_bounds<0>()); + EXPECT_EQ(av.first<0>().length(), 0); + EXPECT_EQ(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_EQ(av.first<5>().bounds(), static_bounds<5>()); + EXPECT_EQ(av.first<5>().length(), 5); + EXPECT_EQ(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_EQ(av.first<6>().bounds(), static_bounds<6>()); + EXPECT_EQ(av.first<6>().length(), 6); + EXPECT_EQ(av.first<-1>().length(), -1); #endif - CHECK_THROWS_AS(av.first(6).length(), fail_fast); + EXPECT_DEATH(av.first(6).length(), ".*"); } { multi_span av; - CHECK((av.first<0>().bounds() == static_bounds<0>())); - CHECK(av.first<0>().length() == 0); - CHECK(av.first(0).length() == 0); + EXPECT_EQ(av.first<0>().bounds(), static_bounds<0>()); + EXPECT_EQ(av.first<0>().length(), 0); + EXPECT_EQ(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_EQ(av.last<2>().bounds(), static_bounds<2>()); + EXPECT_EQ(av.last<2>().length(), 2); + EXPECT_EQ(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_EQ(av.last<0>().bounds(), static_bounds<0>()); + EXPECT_EQ(av.last<0>().length(), 0); + EXPECT_EQ(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_EQ(av.last<5>().bounds(), static_bounds<5>()); + EXPECT_EQ(av.last<5>().length(), 5); + EXPECT_EQ(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_EQ(av.last<6>().bounds(), static_bounds<6>()); + EXPECT_EQ(av.last<6>().length(), 6); #endif - CHECK_THROWS_AS(av.last(6).length(), fail_fast); + EXPECT_DEATH(av.last(6).length(), ".*"); } { multi_span av; - CHECK((av.last<0>().bounds() == static_bounds<0>())); - CHECK(av.last<0>().length() == 0); - CHECK(av.last(0).length() == 0); + EXPECT_EQ(av.last<0>().bounds(), static_bounds<0>()); + EXPECT_EQ(av.last<0>().length(), 0); + EXPECT_EQ(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_EQ((av.subspan<2, 2>().bounds()), static_bounds<2>()); + EXPECT_EQ((av.subspan<2, 2>().length()), 2); + EXPECT_EQ(av.subspan(2, 2).length(), 2); + EXPECT_EQ(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_EQ((av.subspan<0, 0>().bounds()), static_bounds<0>()); + EXPECT_EQ((av.subspan<0, 0>().length()), 0); + EXPECT_EQ(av.subspan(0, 0).length(), 0); } { 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); + EXPECT_EQ((av.subspan<0, 5>().bounds()), static_bounds<5>()); + EXPECT_EQ((av.subspan<0, 5>().length()), 5); + EXPECT_EQ(av.subspan(0, 5).length(), 5); + EXPECT_DEATH(av.subspan(0, 6).length(), ".*"); + EXPECT_DEATH(av.subspan(1, 5).length(), ".*"); } { 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_EQ((av.subspan<5, 0>().bounds()), static_bounds<0>()); + EXPECT_EQ((av.subspan<5, 0>().length()), 0); + EXPECT_EQ(av.subspan(5, 0).length(), 0); + EXPECT_DEATH(av.subspan(6, 0).length(), ".*"); } { 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_EQ((av.subspan<0, 0>().bounds()), static_bounds<0>()); + EXPECT_EQ((av.subspan<0, 0>().length()), 0); + EXPECT_EQ(av.subspan(0, 0).length(), 0); + EXPECT_DEATH((av.subspan<1, 0>().length()), ".*"); } { multi_span av; - CHECK(av.subspan(0).length() == 0); - CHECK_THROWS_AS(av.subspan(1).length(), fail_fast); + EXPECT_EQ(av.subspan(0).length(), 0); + EXPECT_DEATH(av.subspan(1).length(), ".*"); } { 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_EQ(av.subspan(0).length(), 5); + EXPECT_EQ(av.subspan(1).length(), 4); + EXPECT_EQ(av.subspan(4).length(), 1); + EXPECT_EQ(av.subspan(5).length(), 0); + EXPECT_DEATH(av.subspan(6).length(), ".*"); 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_EQ(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_EQ(av.subspan(0).length(), 5); + EXPECT_EQ(av.subspan(1).length(), 4); + EXPECT_EQ(av.subspan(4).length(), 1); + EXPECT_EQ(av.subspan(5).length(), 0); + EXPECT_DEATH(av.subspan(6).length(), ".*"); 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_EQ(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_EQ(s.rank(), 1); } { multi_span s = arr; - CHECK(s.rank() == 1); + EXPECT_EQ(s.rank(), 1); } int arr2d[1][1] = {}; { multi_span s = arr2d; - CHECK(s.rank() == 2); + EXPECT_EQ(s.rank(), 2); } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("extent") +TEST(multi_span_test, extent) { { multi_span s; - CHECK(s.extent() == 0); - CHECK(s.extent(0) == 0); - CHECK_THROWS_AS(s.extent(1), fail_fast); + EXPECT_EQ(s.extent(), 0); + EXPECT_EQ(s.extent(0), 0); + EXPECT_DEATH(s.extent(1), ".*"); #ifdef CONFIRM_COMPILATION_ERRORS - CHECK(s.extent<1>() == 0); + EXPECT_EQ(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_EQ(s.extent(), 0); + EXPECT_EQ(s.extent(0), 0); + EXPECT_DEATH(s.extent(1), ".*"); } { 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_EQ(s.extent(), 1); + EXPECT_EQ(s.extent<0>(), 1); + EXPECT_EQ(s.extent<1>(), 2); + EXPECT_EQ(s.extent(0), 1); + EXPECT_EQ(s.extent(1), 2); + EXPECT_DEATH(s.extent(3), ".*"); } { 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_EQ(s.extent(), 0); + EXPECT_EQ(s.extent<0>(), 0); + EXPECT_EQ(s.extent<1>(), 2); + EXPECT_EQ(s.extent(0), 0); + EXPECT_EQ(s.extent(1), 2); + EXPECT_DEATH(s.extent(3), ".*"); } } -TEST_CASE("operator_function_call") +TEST(multi_span_test, operator_function_call) { int arr[4] = {1, 2, 3, 4}; { multi_span s = arr; - CHECK(s(0) == 1); - CHECK_THROWS_AS(s(5), fail_fast); + EXPECT_EQ(s(0), 1); + EXPECT_DEATH(s(5), ".*"); } 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_EQ(s(0, 0), 1); + EXPECT_EQ(s(0, 1), 2); + EXPECT_EQ(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_EQ(s(0, 0, 0), 1); + EXPECT_EQ(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 +1182,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 +1202,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 +1223,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_EQ(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); @@ -1136,52 +1258,32 @@ TEST_CASE("bounds_checks") av[1][1] = 3; // 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, ".*"); + EXPECT_DEATH((av[{1, 3}] = 3), ".*"); - CHECK_THROWS_AS(av[10][2], fail_fast); - CHECK_THROWS_AS((av[{10, 2}]), fail_fast); + EXPECT_DEATH(av[10][2], ".*"); + EXPECT_DEATH((av[{10, 2}]), ".*"); - CHECK_THROWS_AS(av[-1][0], fail_fast); - CHECK_THROWS_AS((av[{-1, 0}]), fail_fast); + EXPECT_DEATH(av[-1][0], ".*"); + EXPECT_DEATH((av[{-1, 0}]), ".*"); - CHECK_THROWS_AS(av[0][-1], fail_fast); - CHECK_THROWS_AS((av[{0, -1}]), fail_fast); + EXPECT_DEATH(av[0][-1], ".*"); + EXPECT_DEATH((av[{0, -1}]), ".*"); } -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_EQ(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_EQ(count, 34 * 60); overloaded_func(av, 34); overloaded_func(as_multi_span(av, dim(4), dim(3), dim(5)), 34); @@ -1190,11 +1292,7 @@ TEST_CASE("span_parameter_test") 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 +1310,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_EQ(expected + 1, image_view[i][j][0]); + EXPECT_EQ(expected + 2, image_view[i][j][1]); + EXPECT_EQ(expected + 3, image_view[i][j][2]); auto val = image_view[{i, j, 0}]; - CHECK(expected + 1 == val); + EXPECT_EQ(expected + 1, val); val = image_view[{i, j, 1}]; - CHECK(expected + 2 == val); + EXPECT_EQ(expected + 2, val); val = image_view[{i, j, 2}]; - CHECK(expected + 3 == val); + EXPECT_EQ(expected + 3, val); expected += 3; } @@ -1230,12 +1328,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 +1368,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 +1381,41 @@ 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) { { 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_EQ(empty_av.bounds().index_bounds(), multi_span_index<1>{0}); + EXPECT_DEATH(empty_av[0], ".*"); + EXPECT_DEATH(empty_av.begin()[0], ".*"); + EXPECT_DEATH(empty_av.cbegin()[0], ".*"); 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_EQ(empty_av.bounds().index_bounds(), multi_span_index<1>{0}); + EXPECT_DEATH(empty_av[0], ".*"); + EXPECT_DEATH(empty_av.begin()[0], ".*"); + EXPECT_DEATH(empty_av.cbegin()[0], ".*"); 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 +1429,77 @@ TEST_CASE("index_constructor") ptrdiff_t a[1] = {0}; multi_span_index<1> i = a; - CHECK(av[i] == 4); + EXPECT_EQ(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_EQ(av2[i2], 0); + EXPECT_EQ(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_EQ(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_EQ(i2[0], 0); // from array multi_span_index<3> i3 = {0, 1, 2}; - CHECK(i3[0] == 0); + EXPECT_EQ(i3[0], 0); // from other index of the same size type multi_span_index<3> i4 = i3; - CHECK(i4[0] == 0); + EXPECT_EQ(i4[0], 0); // default multi_span_index<3> i7; - CHECK(i7[0] == 0); + EXPECT_EQ(i7[0], 0); // default multi_span_index<3> i9 = {}; - CHECK(i9[0] == 0); + EXPECT_EQ(i9[0], 0); } { // components of the same type multi_span_index<1> i1(0); - CHECK(i1[0] == 0); + EXPECT_EQ(i1[0], 0); // components of different types std::size_t c0 = 0; multi_span_index<1> i2(c0); - CHECK(i2[0] == 0); + EXPECT_EQ(i2[0], 0); // from array multi_span_index<1> i3 = {0}; - CHECK(i3[0] == 0); + EXPECT_EQ(i3[0], 0); // from int multi_span_index<1> i4 = 0; - CHECK(i4[0] == 0); + EXPECT_EQ(i4[0], 0); // from other index of the same size type multi_span_index<1> i5 = i3; - CHECK(i5[0] == 0); + EXPECT_EQ(i5[0], 0); // default multi_span_index<1> i8; - CHECK(i8[0] == 0); + EXPECT_EQ(i8[0], 0); // default multi_span_index<1> i9 = {}; - CHECK(i9[0] == 0); + EXPECT_EQ(i9[0], 0); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -1427,122 +1513,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_EQ(i[0], 0); + EXPECT_EQ(i[1], 1); + EXPECT_EQ(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_EQ(i[0], 0); + EXPECT_EQ(i[1], 1); + EXPECT_EQ(i[2], 2); + EXPECT_EQ(k[0], 3); + EXPECT_EQ(k[1], 5); + EXPECT_EQ(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_EQ(i[0], 0); + EXPECT_EQ(i[1], 1); + EXPECT_EQ(i[2], 2); + EXPECT_EQ(k[0], 0); + EXPECT_EQ(k[1], 3); + EXPECT_EQ(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_EQ(i[0], 0); + EXPECT_EQ(i[1], 1); + EXPECT_EQ(i[2], 2); + EXPECT_EQ(k[0], 0); + EXPECT_EQ(k[1], 3); + EXPECT_EQ(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_EQ(i[0], 0); + EXPECT_EQ(i[1], 1); + EXPECT_EQ(i[2], 2); + EXPECT_EQ(k[0], 1); + EXPECT_EQ(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 +1594,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 +1624,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 +1634,9 @@ TEST_CASE("span_structure_size") double* v1; ptrdiff_t v2; }; - CHECK(sizeof(av1) == sizeof(EffectiveStructure)); + EXPECT_EQ(sizeof(av1), sizeof(EffectiveStructure)); - CHECK_THROWS_AS(av1[10][3][4], fail_fast); + EXPECT_DEATH(av1[10][3][4], ".*"); multi_span av2 = as_multi_span(av1, dim(5), dim<6>(), dim<4>()); @@ -1628,14 +1645,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_EQ(av4.length(), 4); // converting to dynamic_range a_v is always ok { @@ -1674,7 +1690,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 @@ -1713,7 +1729,7 @@ TEST_CASE("fixed_size_conversions") const multi_span av9 = {arr2, 2}; (void) av9; }; - CHECK_THROWS_AS(f(), fail_fast); + EXPECT_DEATH(f(), ".*"); } // this should fail - we are trying to assign a small dynamic a_v to a fixed_size larger one @@ -1722,11 +1738,10 @@ TEST_CASE("fixed_size_conversions") const multi_span av2 = av; (void) av2; }; - CHECK_THROWS_AS(f(), fail_fast); + EXPECT_DEATH(f(), ".*"); } -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 +1756,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_EQ(wav.length(), av.length()); + EXPECT_EQ(wav.length(), 0); + EXPECT_EQ(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_EQ(wav.data(), reinterpret_cast(&a[0])); + EXPECT_EQ(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 +1786,7 @@ TEST_CASE("iterator") } for (std::size_t i = 0; i < 4; ++i) { - CHECK(a[i] == 0); + EXPECT_EQ(a[i], 0); } } @@ -1785,7 +1796,7 @@ TEST_CASE("iterator") n = 1; } for (std::size_t i = 0; i < 4; ++i) { - CHECK(a[i] == 1); + EXPECT_EQ(a[i], 1); } } } diff --git a/tests/notnull_tests.cpp b/tests/notnull_tests.cpp index 010dd00..c2dfbdb 100644 --- a/tests/notnull_tests.cpp +++ b/tests/notnull_tests.cpp @@ -23,7 +23,7 @@ #pragma warning(disable : 4702) // unreachable code #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#include #include // for not_null, operator<, operator<=, operator> @@ -135,8 +135,7 @@ 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 @@ -158,13 +157,13 @@ TEST_CASE("TestNotNullConstructors") int i = 12; auto rp = RefCounted(&i); not_null p(rp); - CHECK(p.get() == &i); + EXPECT_EQ(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)), ".*"); } { @@ -175,7 +174,7 @@ TEST_CASE("TestNotNullConstructors") helper(&t); helper_const(&t); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -191,7 +190,7 @@ TEST_CASE("TestNotNullConstructors") helper(x); helper_const(x); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -205,7 +204,7 @@ TEST_CASE("TestNotNullConstructors") helper_const(cp); helper_const(x); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -215,19 +214,18 @@ TEST_CASE("TestNotNullConstructors") auto x = not_null{cp}; - CHECK(*x == 42); + EXPECT_EQ(*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()), ".*"); + EXPECT_DEATH(helper_const(return_pointer()), ".*"); } } template -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute void ostream_helper(T v) { not_null p(&v); @@ -236,18 +234,18 @@ void ostream_helper(T v) std::ostringstream ref; os << static_cast(p); ref << static_cast(&v); - CHECK(os.str() == ref.str()); + EXPECT_EQ(os.str(), ref.str()); } { std::ostringstream os; std::ostringstream ref; os << *p; ref << v; - CHECK(os.str() == ref.str()); + EXPECT_EQ(os.str(), ref.str()); } } -TEST_CASE("TestNotNullostream") +TEST(notnull_tests, TestNotNullostream) { ostream_helper(17); ostream_helper(21.5f); @@ -258,9 +256,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 +266,7 @@ TEST_CASE("TestNotNullCasting") not_null p{&derived}; not_null q(&base); q = p; // allowed with heterogeneous copy ctor - CHECK(q == p); + EXPECT_EQ(q, p); #ifdef CONFIRM_COMPILATION_ERRORS q = u; // no viable conversion possible between MyBase* and Unrelated* @@ -280,20 +276,20 @@ 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_EQ(reinterpret_cast(p.get()), reinterpret_cast(t.get())); } -TEST_CASE("TestNotNullAssignment") +TEST(notnull_tests, TestNotNullAssignment) { 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), ".*"); } -TEST_CASE("TestNotNullRawPointerComparison") +TEST(notnull_tests, TestNotNullRawPointerComparison) { int ints[2] = {42, 43}; int* p1 = &ints[0]; @@ -302,34 +298,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_EQ((NotNull1(p1) == NotNull1(p1)), true); + EXPECT_EQ((NotNull1(p1) == NotNull2(p2)), false); - CHECK((NotNull1(p1) != NotNull1(p1)) == false); - CHECK((NotNull1(p1) != NotNull2(p2)) == true); + EXPECT_EQ((NotNull1(p1) != NotNull1(p1)), false); + EXPECT_EQ((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_EQ((NotNull1(p1) < NotNull1(p1)), false); + EXPECT_EQ((NotNull1(p1) < NotNull2(p2)), (p1 < p2)); + EXPECT_EQ((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_EQ((NotNull1(p1) > NotNull1(p1)), false); + EXPECT_EQ((NotNull1(p1) > NotNull2(p2)), (p1 > p2)); + EXPECT_EQ((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_EQ((NotNull1(p1) <= NotNull1(p1)), true); + EXPECT_EQ((NotNull1(p1) <= NotNull2(p2)), (p1 <= p2)); + EXPECT_EQ((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_EQ(typeid(*sp1), typeid(*NotNullSp1(sp1))); + EXPECT_EQ(std::addressof(*NotNullSp1(sp1)), std::addressof(*sp1)); } { @@ -337,22 +332,22 @@ TEST_CASE("TestNotNullDereferenceOperator") CustomPtr p1(&ints[0]); using NotNull1 = not_null; - CHECK(typeid(*NotNull1(p1)) == typeid(*p1)); - CHECK(*NotNull1(p1) == 42); + EXPECT_EQ(typeid(*NotNull1(p1)), typeid(*p1)); + EXPECT_EQ(*NotNull1(p1), 42); *NotNull1(p1) = 43; - CHECK(ints[0] == 43); + EXPECT_EQ(ints[0], 43); } { int v = 42; gsl::not_null p(&v); - CHECK(typeid(*p) == typeid(*(&v))); + EXPECT_EQ(typeid(*p), typeid(*(&v))); *p = 43; - CHECK(v == 43); + EXPECT_EQ(v, 43); } } -TEST_CASE("TestNotNullSharedPtrComparison") +TEST(notnull_tests, TestNotNullSharedPtrComparison) { auto sp1 = std::make_shared(42); auto sp2 = std::make_shared(43); @@ -360,31 +355,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_EQ((NotNullSp1(sp1) == NotNullSp1(sp1)), true); + EXPECT_EQ((NotNullSp1(sp1) == NotNullSp2(sp2)), false); - CHECK((NotNullSp1(sp1) != NotNullSp1(sp1)) == false); - CHECK((NotNullSp1(sp1) != NotNullSp2(sp2)) == true); + EXPECT_EQ((NotNullSp1(sp1) != NotNullSp1(sp1)), false); + EXPECT_EQ((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_EQ((NotNullSp1(sp1) < NotNullSp1(sp1)), false); + EXPECT_EQ((NotNullSp1(sp1) < NotNullSp2(sp2)), (sp1 < sp2)); + EXPECT_EQ((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_EQ((NotNullSp1(sp1) > NotNullSp1(sp1)), false); + EXPECT_EQ((NotNullSp1(sp1) > NotNullSp2(sp2)), (sp1 > sp2)); + EXPECT_EQ((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_EQ((NotNullSp1(sp1) <= NotNullSp1(sp1)), true); + EXPECT_EQ((NotNullSp1(sp1) <= NotNullSp2(sp2)), (sp1 <= sp2)); + EXPECT_EQ((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_EQ((NotNullSp1(sp1) >= NotNullSp1(sp1)), true); + EXPECT_EQ((NotNullSp1(sp1) >= NotNullSp2(sp2)), (sp1 >= sp2)); + EXPECT_EQ((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 +387,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_EQ((NotNull1(p1) == NotNull1(p1)), "true"); + EXPECT_EQ((NotNull1(p1) == NotNull2(p2)), "false"); - CHECK((NotNull1(p1) != NotNull1(p1)) == "false"); - CHECK((NotNull1(p1) != NotNull2(p2)) == "true"); + EXPECT_EQ((NotNull1(p1) != NotNull1(p1)), "false"); + EXPECT_EQ((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_EQ((NotNull1(p1) < NotNull1(p1)), "false"); + EXPECT_EQ((NotNull1(p1) < NotNull2(p2)), (p1 < p2)); + EXPECT_EQ((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_EQ((NotNull1(p1) > NotNull1(p1)), "false"); + EXPECT_EQ((NotNull1(p1) > NotNull2(p2)), (p1 > p2)); + EXPECT_EQ((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_EQ((NotNull1(p1) <= NotNull1(p1)), "true"); + EXPECT_EQ((NotNull1(p1) <= NotNull2(p2)), (p1 <= p2)); + EXPECT_EQ((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_EQ((NotNull1(p1) >= NotNull1(p1)), "true"); + EXPECT_EQ((NotNull1(p1) >= NotNull2(p2)), (p1 >= p2)); + EXPECT_EQ((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 +421,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") helper(not_null{&i}); helper_const(not_null{&i}); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -439,7 +432,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") helper(not_null{p}); helper_const(not_null{p}); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -447,7 +440,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") int* p1 = nullptr; const not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { @@ -455,14 +448,14 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") const int* p1 = nullptr; const not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { 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}), ".*"); + EXPECT_DEATH(helper_const(not_null{p}), ".*"); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -475,7 +468,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction") } #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) -TEST_CASE("TestMakeNotNull") +TEST(notnull_tests, TestMakeNotNull) { { int i = 42; @@ -484,7 +477,7 @@ TEST_CASE("TestMakeNotNull") helper(make_not_null(&i)); helper_const(make_not_null(&i)); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -495,39 +488,39 @@ TEST_CASE("TestMakeNotNull") helper(make_not_null(p)); helper_const(make_not_null(p)); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { const auto workaround_macro = []() { int* p1 = nullptr; const auto x = make_not_null(p1); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { const auto workaround_macro = []() { const int* p1 = nullptr; const auto x = make_not_null(p1); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { 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)), ".*"); + EXPECT_DEATH(helper_const(make_not_null(p)), ".*"); } #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), ".*"); + EXPECT_DEATH(helper(make_not_null(nullptr)), ".*"); + EXPECT_DEATH(helper_const(make_not_null(nullptr)), ".*"); } #endif } diff --git a/tests/owner_tests.cpp b/tests/owner_tests.cpp index 9fff184..9babb38 100644 --- a/tests/owner_tests.cpp +++ b/tests/owner_tests.cpp @@ -21,7 +21,7 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#include #include // for owner @@ -30,19 +30,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_EQ(*p, 120); f(p); - CHECK(*p == 121); + EXPECT_EQ(*p, 121); delete p; } -TEST_CASE("check_pointer_constraint") +TEST(owner_tests, check_pointer_constraint) { #ifdef CONFIRM_COMPILATION_ERRORS { diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index d22dc08..15a5109 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -21,11 +21,10 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... - #include // for byte #include // for narrow_cast, at #include // for span, span_iterator, operator==, operator!= +#include #include // for array #include // for ptrdiff_t @@ -58,142 +57,128 @@ 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_EQ(s.size(), 0); + EXPECT_EQ(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_EQ(cs.size(), 0); + EXPECT_EQ(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_EQ(s.size(), 0); + EXPECT_EQ(s.data(), nullptr); - { - span s; - CHECK(sizeof(s) == sizeof(int*)); - } + span cs; + EXPECT_EQ(cs.size(), 0); + EXPECT_EQ(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_EQ(s.size(), 0); + EXPECT_EQ(s.data(), nullptr); + + span cs{}; + EXPECT_EQ(cs.size(), 0); + EXPECT_EQ(cs.data(), nullptr); +} + +TEST(span_test, size_optimization) +{ + span s; + EXPECT_EQ(sizeof(s), sizeof(int*) + sizeof(ptrdiff_t)); + + span se; + EXPECT_EQ(sizeof(se), sizeof(int*)); +} + +TEST(span_test, from_nullptr_size_constructor) { { span s{nullptr, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(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_EQ(cs.size(), 0); + EXPECT_EQ(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(), ".*"); } - { auto workaround_macro = []() { const span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); - 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(), ".*"); } - { auto workaround_macro = []() { const span s{nullptr, 1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); auto const_workaround_macro = []() { const span s{nullptr, 1}; }; - CHECK_THROWS_AS(const_workaround_macro(), fail_fast); + EXPECT_DEATH(const_workaround_macro(), ".*"); } - { span s{nullptr, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), nullptr); span cs{nullptr, narrow_cast::index_type>(0)}; - CHECK((cs.size() == 0 && cs.data() == nullptr)); + EXPECT_EQ(cs.size(), 0); + EXPECT_EQ(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) { 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_EQ(s.size(), i); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(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_EQ(arr[j], s[j]); + EXPECT_EQ(arr[j], s.at(j)); + EXPECT_EQ(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_EQ(s.size(), 4 - i); + EXPECT_EQ(s.data(), &arr[i]); + EXPECT_EQ(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_EQ(arr[j + i], s[j]); + EXPECT_EQ(arr[j + i], s.at(j)); + EXPECT_EQ(arr[j + i], s(j)); } } } @@ -201,1364 +186,1365 @@ 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_EQ(s.size(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[1], 2); } { int* p = nullptr; span s{p, narrow_cast::index_type>(0)}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(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(), ".*"); } { auto s = make_span(&arr[0], 2); - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_EQ(s.size(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[1], 2); } { int* p = nullptr; auto s = make_span(p, narrow_cast::index_type>(0)); - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), nullptr); } { int* p = nullptr; auto workaround_macro = [=]() { make_span(p, 2); }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } } - -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_EQ(s.size(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(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_EQ(s.size(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[1], 2); } { span s{&arr[0], &arr[0]}; - CHECK((s.size() == 0 && s.data() == &arr[0])); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), &arr[0]); } { span s{&arr[0], &arr[0]}; - CHECK((s.size() == 0 && s.data() == &arr[0])); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(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(), ".*"); //} // 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(), ".*"); //} { int* p = nullptr; span s{p, p}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), nullptr); } { int* p = nullptr; span s{p, p}; - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(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(), ".*"); //} { auto s = make_span(&arr[0], &arr[2]); - CHECK((s.size() == 2 && s.data() == &arr[0])); - CHECK((s[0] == 1 && s[1] == 2)); + EXPECT_EQ(s.size(), 2); + EXPECT_EQ(s.data(), &arr[0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[1], 2); } { auto s = make_span(&arr[0], &arr[0]); - CHECK((s.size() == 0 && s.data() == &arr[0])); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), &arr[0]); } { int* p = nullptr; auto s = make_span(p, p); - CHECK((s.size() == 0 && s.data() == nullptr)); + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(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_EQ(s.size(), 5); + EXPECT_EQ(s.data(), &arr[0]); + } + + { + const span s{arr}; + EXPECT_EQ(s.size(), 5); + EXPECT_EQ(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_EQ(s.size(), 0); + EXPECT_EQ(s.data(), &arr[0]); + } + + { + span s{arr2d}; + EXPECT_EQ(s.size(), 6); + EXPECT_EQ(s.data(), &arr2d[0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[5], 6); + } + + { + span s{arr2d}; + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), &arr2d[0][0]); + } + + { + span s{arr2d}; + } + #endif + { + const span s{std::addressof(arr2d[0]), 1}; + EXPECT_EQ(s.size(), 1); + EXPECT_EQ(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_EQ(s.size(), 12); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[11], 12); + } + + { + span s{arr3d}; + EXPECT_EQ(s.size(), 0); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); + } + + { + span s{arr3d}; + } + + { + span s{arr3d}; + EXPECT_EQ(s.size(), 12); + EXPECT_EQ(s.data(), &arr3d[0][0][0]); + EXPECT_EQ(s[0], 1); + EXPECT_EQ(s[5], 6); + } + #endif + { + const span s{std::addressof(arr3d[0]), 1}; + EXPECT_EQ(s.size(), 1); + } + + { + const auto s = make_span(arr); + EXPECT_EQ(s.size(), 5); + EXPECT_EQ(s.data(),std::addressof(arr[0])); + } + + { + const auto s = make_span(std::addressof(arr2d[0]), 1); + EXPECT_EQ(s.size(), 1); + EXPECT_EQ(s.data(), std::addressof(arr2d[0])); + } + + { + const auto s = make_span(std::addressof(arr3d[0]), 1); + EXPECT_EQ(s.size(), 1); + EXPECT_EQ(s.data(), std::addressof(arr3d[0])); + } + + AddressOverloaded ao_arr[5] = {}; + + { + const span s{ao_arr}; + EXPECT_EQ(s.size(), 5); + EXPECT_EQ(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_EQ(s.size(), 10); EXPECT_EQ(s.data(), &arr[0][0][0]); + } + + { + auto s = make_span(&arr[0][0][0], 10); + EXPECT_EQ(s.size(), 10); EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + + span cs{arr}; + EXPECT_EQ(cs.size(), narrow_cast(arr.size())); EXPECT_EQ(cs.data(), arr.data()); + } + + { + span s{arr}; + EXPECT_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + + span cs{arr}; + EXPECT_EQ(cs.size(), narrow_cast(arr.size())); EXPECT_EQ(cs.data(), arr.data()); + } + + { + std::array empty_arr{}; + span s{empty_arr}; + EXPECT_EQ(s.size(), 0); + EXPECT_TRUE(s.empty()); + } + + std::array ao_arr{}; + + { + span fs{ao_arr}; + EXPECT_EQ(fs.size(), narrow_cast(ao_arr.size())); + EXPECT_EQ(ao_arr.data(), fs.data()); + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_EQ(s.size(), 2); EXPECT_EQ(s.data(), arr.data()); + + span cs{arr}; + EXPECT_EQ(cs.size(), 2); EXPECT_EQ(cs.data(), arr.data()); + } + + { + span s{arr}; + EXPECT_EQ(s.size(), 0); EXPECT_EQ(s.data(), arr.data()); + + span cs{arr}; + EXPECT_EQ(cs.size(), 0); EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(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_EQ(s1.size(), 4); + EXPECT_EQ(s2.size(), 0); + #else + EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + } + + { + span s{arr}; + EXPECT_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + } + + const std::array ao_arr{}; + + { + span s{ao_arr}; + EXPECT_EQ(s.size(), narrow_cast(ao_arr.size())); + EXPECT_EQ(s.data(), ao_arr.data()); + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_EQ(s.size(), 2); EXPECT_EQ(s.data(), arr.data()); + } + + { + span s{arr}; + EXPECT_EQ(s.size(), 0); EXPECT_EQ(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_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + } + } + + TEST(span_test, from_std_array_const_constructor) + { + std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + } + + { + span s{arr}; + EXPECT_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(s.data(), arr.data()); + } + + #ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_EQ(s.size(), 2); EXPECT_EQ(s.data(), arr.data()); + } + + { + span s{arr}; + EXPECT_EQ(s.size(), 0); EXPECT_EQ(s.data(), arr.data()); + } + + { + span s{arr}; + } + + { + span s{arr}; + } + #endif + + { + auto s = make_span(arr); + EXPECT_EQ(s.size(), narrow_cast(arr.size())); EXPECT_EQ(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_EQ(s.size(), narrow_cast(v.size())); EXPECT_EQ(s.data(), v.data()); + + span cs{v}; + EXPECT_EQ(cs.size(), narrow_cast(v.size())); EXPECT_EQ(cs.data(), v.data()); + } + + std::string str = "hello"; + const std::string cstr = "hello"; + + { + #ifdef CONFIRM_COMPILATION_ERRORS + span s{str}; + EXPECT_EQ(s.size(), narrow_cast(str.size())); + EXPECT_EQ(s.data(), str.data())); + #endif + span cs{str}; + EXPECT_EQ(cs.size(), narrow_cast(str.size())); + EXPECT_EQ(cs.data(), str.data()); + } + + { + #ifdef CONFIRM_COMPILATION_ERRORS + span s{cstr}; + #endif + span cs{cstr}; + EXPECT_EQ(cs.size(), narrow_cast(cstr.size())); + EXPECT_EQ(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_EQ(s.size(), narrow_cast(v.size())); EXPECT_EQ(s.data(), v.data()); + + auto cs = make_span(cv); + EXPECT_EQ(cs.size(), narrow_cast(cv.size())); + EXPECT_EQ(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_EQ(s2.size(), 3); EXPECT_EQ(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_EQ(s.size(), 2); EXPECT_EQ(s.data(), &arr[1]); + }; use_span(get_temp_span()); + + s1 = get_temp_span(); + EXPECT_EQ(s1.size(), 2); EXPECT_EQ(s1.data(), &arr[1]); + } + + TEST(span_test, first) + { + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_EQ(av.first<2>().size(), 2); + EXPECT_EQ(av.first(2).size(), 2); + } + + { + span av = arr; + EXPECT_EQ(av.first<0>().size(), 0); + EXPECT_EQ(av.first(0).size(), 0); + } + + { + span av = arr; + EXPECT_EQ(av.first<5>().size(), 5); + EXPECT_EQ(av.first(5).size(), 5); + } + + { + span av = arr; + #ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(av.first<6>().size(), 6); + EXPECT_EQ(av.first<-1>().size(), -1); + #endif + EXPECT_DEATH(av.first(6).size(), ".*"); + } + + { + span av; + EXPECT_EQ(av.first<0>().size(), 0); + EXPECT_EQ(av.first(0).size(), 0); + } + } + + TEST(span_test, last) + { + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_EQ(av.last<2>().size(), 2); + EXPECT_EQ(av.last(2).size(), 2); + } + + { + span av = arr; + EXPECT_EQ(av.last<0>().size(), 0); + EXPECT_EQ(av.last(0).size(), 0); + } + + { + span av = arr; + EXPECT_EQ(av.last<5>().size(), 5); + EXPECT_EQ(av.last(5).size(), 5); + } + + { + span av = arr; + #ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(av.last<6>().size(), 6); + #endif + EXPECT_DEATH(av.last(6).size(), ".*"); + } + + { + span av; + EXPECT_EQ(av.last<0>().size(), 0); + EXPECT_EQ(av.last(0).size(), 0); + } + } + + TEST(span_test, subspan) + { + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_EQ((av.subspan<2, 2>().size()), 2); + EXPECT_EQ(decltype(av.subspan<2, 2>())::extent, 2); + EXPECT_EQ(av.subspan(2, 2).size(), 2); + EXPECT_EQ(av.subspan(2, 3).size(), 3); + } + + { + span av = arr; + EXPECT_EQ((av.subspan<0, 0>().size()), 0); + EXPECT_EQ(decltype(av.subspan<0, 0>())::extent, 0); + EXPECT_EQ(av.subspan(0, 0).size(), 0); + } + + { + span av = arr; + EXPECT_EQ((av.subspan<0, 5>().size()), 5); + EXPECT_EQ(decltype(av.subspan<0, 5>())::extent, 5); + EXPECT_EQ(av.subspan(0, 5).size(), 5); + + EXPECT_DEATH(av.subspan(0, 6).size(), ".*"); + EXPECT_DEATH(av.subspan(1, 5).size(), ".*"); + } + + { + span av = arr; + EXPECT_EQ((av.subspan<4, 0>().size()), 0); + EXPECT_EQ(decltype(av.subspan<4, 0>())::extent, 0); + EXPECT_EQ(av.subspan(4, 0).size(), 0); + EXPECT_EQ(av.subspan(5, 0).size(), 0); + EXPECT_DEATH(av.subspan(6, 0).size(), ".*"); + } + + { + span av = arr; + EXPECT_EQ(av.subspan<1>().size(), 4); + EXPECT_EQ(decltype(av.subspan<1>())::extent, 4); + } + + { + span av; + EXPECT_EQ((av.subspan<0, 0>().size()), 0); + EXPECT_EQ(decltype(av.subspan<0, 0>())::extent, 0); + EXPECT_EQ(av.subspan(0, 0).size(), 0); + EXPECT_DEATH((av.subspan<1, 0>().size()), ".*"); + } + + { + span av; + EXPECT_EQ(av.subspan(0).size(), 0); + EXPECT_DEATH(av.subspan(1).size(), ".*"); + } + + { + span av = arr; + EXPECT_EQ(av.subspan(0).size(), 5); + EXPECT_EQ(av.subspan(1).size(), 4); + EXPECT_EQ(av.subspan(4).size(), 1); + EXPECT_EQ(av.subspan(5).size(), 0); + EXPECT_DEATH(av.subspan(6).size(), ".*"); + const auto av2 = av.subspan(1); + for (int i = 0; i < 4; ++i) EXPECT_EQ(av2[i], i + 2); + } + + { + span av = arr; + EXPECT_EQ(av.subspan(0).size(), 5); + EXPECT_EQ(av.subspan(1).size(), 4); + EXPECT_EQ(av.subspan(4).size(), 1); + EXPECT_EQ(av.subspan(5).size(), 0); + EXPECT_DEATH(av.subspan(6).size(), ".*"); + const auto av2 = av.subspan(1); + for (int i = 0; i < 4; ++i) EXPECT_EQ(av2[i], i + 2); + } + } + + TEST(span_test, at_call) + { + int arr[4] = {1, 2, 3, 4}; + + { + span s = arr; + EXPECT_EQ(s.at(0), 1); + EXPECT_DEATH(s.at(5), ".*"); + } + + { + int arr2d[2] = {1, 6}; + span s = arr2d; + EXPECT_EQ(s.at(0), 1); + EXPECT_EQ(s.at(1), 6); + EXPECT_DEATH(s.at(2), ".*"); + } + } + + TEST(span_test, operator_function_call) + { + int arr[4] = {1, 2, 3, 4}; + + { + span s = arr; + EXPECT_EQ(s(0), 1); + EXPECT_DEATH(s(5), ".*"); + } + + { + int arr2d[2] = {1, 6}; + span s = arr2d; + EXPECT_EQ(s(0), 1); + EXPECT_EQ(s(1), 6); + EXPECT_DEATH(s(2), ".*"); + } + } + + TEST(span_test, iterator_default_init) + { + span::iterator it1; + span::iterator it2; + EXPECT_EQ(it1, it2); + } + + TEST(span_test, const_iterator_default_init) + { + span::const_iterator it1; + span::const_iterator it2; + EXPECT_EQ(it1, it2); + } + + TEST(span_test, iterator_conversions) + { + span::iterator badIt; + span::const_iterator badConstIt; + EXPECT_EQ(badIt, badConstIt); + + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.begin(); + auto cit = s.cbegin(); + + EXPECT_EQ(it, cit); + EXPECT_EQ(cit, it); + + span::const_iterator cit2 = it; + EXPECT_EQ(cit2, cit); + + span::const_iterator cit3 = it + 4; + EXPECT_EQ(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_EQ(it, cit); + EXPECT_EQ(cit, it); + EXPECT_EQ(it, it); + EXPECT_EQ(cit, cit); + EXPECT_EQ(cit, s.begin()); + EXPECT_EQ(s.begin(), cit); + EXPECT_EQ(s.cbegin(), cit); + EXPECT_EQ(it, s.begin()); + EXPECT_EQ(s.begin(), it); + + EXPECT_NE(it, it2); + EXPECT_NE(it2, it); + EXPECT_NE(it, s.end()); + EXPECT_NE(it2, s.end()); + EXPECT_NE(s.end(), it); + EXPECT_NE(it2, cit); + EXPECT_NE(cit, it2); + + EXPECT_LT(it, it2); + EXPECT_LE(it, it2); + EXPECT_LE(it2, s.end()); + EXPECT_LT(it, s.end()); + EXPECT_LE(it, cit); + EXPECT_LE(cit, it); + EXPECT_LT(cit, it2); + EXPECT_LE(cit, it2); + EXPECT_LT(cit, s.end()); + EXPECT_LE(cit, s.end()); + + EXPECT_GT(it2, it); + EXPECT_GE(it2, it); + EXPECT_GT(s.end(), it2); + EXPECT_GE(s.end(), it2); + EXPECT_GT(it2, cit); + EXPECT_GE(it2, cit); + } + } + + TEST(span_test, begin_end) + { + { + int a[] = {1, 2, 3, 4}; + span s = a; + + span::iterator it = s.begin(); + span::iterator it2 = std::begin(s); + EXPECT_EQ(it, it2); + + it = s.end(); + it2 = std::end(s); + EXPECT_EQ(it, it2); + } + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.begin(); + auto first = it; + EXPECT_EQ(it, first); + EXPECT_EQ(*it, 1); + + auto beyond = s.end(); + EXPECT_NE(it, beyond); + EXPECT_DEATH(*beyond, ".*"); + + EXPECT_EQ(beyond - first, 4); + EXPECT_EQ(first - first, 0); + EXPECT_EQ(beyond - beyond, 0); + + ++it; + EXPECT_EQ(it - first, 1); + EXPECT_EQ(*it, 2); + *it = 22; + EXPECT_EQ(*it, 22); + EXPECT_EQ(beyond - it, 3); + + it = first; + EXPECT_EQ(it, first); + while (it != s.end()) + { + *it = 5; + ++it; + } + + EXPECT_EQ(it, beyond); + EXPECT_EQ(it - beyond, 0); + + for (const auto& n : s) { EXPECT_EQ(n, 5); } + } + } + + TEST(span_test, cbegin_cend) + { + { + int a[] = {1, 2, 3, 4}; + span s = a; + + span::const_iterator cit = s.cbegin(); + span::const_iterator cit2 = std::cbegin(s); + EXPECT_EQ(cit, cit2); + + cit = s.cend(); + cit2 = std::cend(s); + EXPECT_EQ(cit, cit2); + } + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.cbegin(); + auto first = it; + EXPECT_EQ(it, first); + EXPECT_EQ(*it, 1); + + auto beyond = s.cend(); + EXPECT_NE(it, beyond); + EXPECT_DEATH(*beyond, ".*"); + + EXPECT_EQ(beyond - first, 4); + EXPECT_EQ(first - first, 0); + EXPECT_EQ(beyond - beyond, 0); + + ++it; + EXPECT_EQ(it - first, 1); + EXPECT_EQ(*it, 2); + EXPECT_EQ(beyond - it, 3); + + int last = 0; + it = first; + EXPECT_EQ(it, first); + while (it != s.cend()) + { + EXPECT_EQ(*it, last + 1); + + last = *it; + ++it; + } + + EXPECT_EQ(it, beyond); + EXPECT_EQ(it - beyond, 0); + } + } + + TEST(span_test, rbegin_rend) + { + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.rbegin(); + auto first = it; + EXPECT_EQ(it, first); + EXPECT_EQ(*it, 4); + + auto beyond = s.rend(); + EXPECT_NE(it, beyond); + //EXPECT_DEATH(*beyond, ".*"); + + EXPECT_EQ(beyond - first, 4); + EXPECT_EQ(first - first, 0); + EXPECT_EQ(beyond - beyond, 0); + + ++it; + EXPECT_EQ(it - first, 1); + EXPECT_EQ(*it, 3); + *it = 22; + EXPECT_EQ(*it, 22); + EXPECT_EQ(beyond - it, 3); + + it = first; + EXPECT_EQ(it, first); + while (it != s.rend()) + { + *it = 5; + ++it; + } + + EXPECT_EQ(it, beyond); + EXPECT_EQ(it - beyond, 0); + + for (const auto& n : s) { EXPECT_EQ(n, 5); } + } + } + + TEST(span_test, crbegin_crend) + { + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.crbegin(); + auto first = it; + EXPECT_EQ(it, first); + EXPECT_EQ(*it, 4); + + auto beyond = s.crend(); + EXPECT_NE(it, beyond); + //EXPECT_DEATH(*beyond, ".*"); + + EXPECT_EQ(beyond - first, 4); + EXPECT_EQ(first - first, 0); + EXPECT_EQ(beyond - beyond, 0); + + ++it; + EXPECT_EQ(it - first, 1); + EXPECT_EQ(*it, 3); + EXPECT_EQ(beyond - it, 3); + + it = first; + EXPECT_EQ(it, first); + int last = 5; + while (it != s.crend()) + { + EXPECT_EQ(*it, last - 1); + last = *it; + + ++it; + } + + EXPECT_EQ(it, beyond); + EXPECT_EQ(it - beyond, 0); + } + } + + TEST(span_test, comparison_operators) + { + { + span s1; + span s2; + EXPECT_EQ(s1, s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_LE(s1, s2); + EXPECT_FALSE(s1 > s2); + EXPECT_GE(s1, s2); + EXPECT_EQ(s2, s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 != s1); + EXPECT_LE(s2, s1); + EXPECT_FALSE(s2 > s1); + EXPECT_GE(s2, s1); + } + + { + int arr[] = {2, 1}; + span s1 = arr; + span s2 = arr; + + EXPECT_EQ(s1, s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_LE(s1, s2); + EXPECT_FALSE(s1 > s2); + EXPECT_GE(s1, s2); + EXPECT_EQ(s2, s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_LE(s2, s1); + EXPECT_FALSE(s2 > s1); + EXPECT_GE(s2, s1); + } + + { + int arr[] = {2, 1}; // bigger + + span s1; + span s2 = arr; + + EXPECT_NE(s1, s2); + EXPECT_NE(s2, s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_LT(s1, s2); + EXPECT_FALSE(s2 < s1); + EXPECT_LE(s1, s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_GT(s2, s1); + EXPECT_FALSE(s1 > s2); + EXPECT_GE(s2, s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; + int arr2[] = {1, 2}; + span s1 = arr1; + span s2 = arr2; + + EXPECT_EQ(s1, s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_LE(s1, s2); + EXPECT_FALSE(s1 > s2); + EXPECT_GE(s1, s2); + EXPECT_EQ(s2, s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_LE(s2, s1); + EXPECT_FALSE(s2 > s1); + EXPECT_GE(s2, s1); + } + + { + int arr[] = {1, 2, 3}; + + span s1 = {&arr[0], 2}; // shorter + span s2 = arr; // longer + + EXPECT_NE(s1, s2); + EXPECT_NE(s2, s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_LT(s1, s2); + EXPECT_FALSE(s2 < s1); + EXPECT_LE(s1, s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_GT(s2, s1); + EXPECT_FALSE(s1 > s2); + EXPECT_GE(s2, s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; // smaller + int arr2[] = {2, 1}; // bigger + + span s1 = arr1; + span s2 = arr2; + + EXPECT_NE(s1, s2); + EXPECT_NE(s2, s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_LT(s1, s2); + EXPECT_FALSE(s2 < s1); + EXPECT_LE(s1, s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_GT(s2, s1); + EXPECT_FALSE(s1 > s2); + EXPECT_GE(s2, s1); + EXPECT_FALSE(s1 >= s2); + } + } + + TEST(span_test, as_bytes) + { + int a[] = {1, 2, 3, 4}; + + { + const span s = a; + EXPECT_EQ(s.size(), 4); + const span bs = as_bytes(s); + EXPECT_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(bs.size(), s.size_bytes()); + } + + { + span s; + const auto bs = as_bytes(s); + EXPECT_EQ(bs.size(), s.size()); + EXPECT_EQ(bs.size(), 0); + EXPECT_EQ(bs.size_bytes(), 0); + EXPECT_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(bs.data(), nullptr); + } + + { + span s = a; + const auto bs = as_bytes(s); + EXPECT_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(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_EQ(s.size(), 4); + span bs = as_writeable_bytes(s); + EXPECT_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(bs.size(), s.size_bytes()); + #endif + } + + { + span s; + const auto bs = as_writeable_bytes(s); + EXPECT_EQ(bs.size(), s.size()); + EXPECT_EQ(bs.size(), 0); + EXPECT_EQ(bs.size_bytes(), 0); + EXPECT_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(bs.data(), nullptr); + } + + { + span s = a; + const auto bs = as_writeable_bytes(s); + EXPECT_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(bs.size(), s.size_bytes()); + } + } + + TEST(span_test, fixed_size_conversions) + { + int arr[] = {1, 2, 3, 4}; + + // converting to an span from an equal size array is ok + span s4 = arr; + EXPECT_EQ(s4.size(), 4); + + // converting to dynamic_range is always ok + { + span s = s4; + EXPECT_EQ(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(), ".*"); + } + + // 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(), ".*"); + } + + // 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(), ".*"); + } + + 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_EQ(match[0].first, s.begin()); + EXPECT_EQ(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_EQ(match[0].first, f_it); + EXPECT_EQ(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_EQ(at(s, 0), 1); EXPECT_EQ(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)); + } diff --git a/tests/strict_notnull_tests.cpp b/tests/strict_notnull_tests.cpp index 055afec..07aa957 100644 --- a/tests/strict_notnull_tests.cpp +++ b/tests/strict_notnull_tests.cpp @@ -23,7 +23,7 @@ #pragma warning(disable : 4702) // unreachable code #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#include #include // for not_null, operator<, operator<=, operator> namespace gsl @@ -35,19 +35,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 +67,7 @@ TEST_CASE("TestStrictNotNull") helper(snn1); helper_const(snn1); - CHECK(*snn1 == 42); + EXPECT_EQ(*snn1, 42); } { @@ -80,7 +81,7 @@ TEST_CASE("TestStrictNotNull") strict_helper_const(snn1); strict_helper_const(snn2); - CHECK(snn1 == snn2); + EXPECT_EQ(snn1, snn2); } { @@ -95,8 +96,8 @@ TEST_CASE("TestStrictNotNull") helper(snn); helper_const(snn); - CHECK(snn == nn1); - CHECK(snn == nn2); + EXPECT_EQ(snn, nn1); + EXPECT_EQ(snn, nn2); } { @@ -111,16 +112,16 @@ TEST_CASE("TestStrictNotNull") strict_helper(nn); strict_helper_const(nn); - CHECK(snn1 == nn); - CHECK(snn2 == nn); + EXPECT_EQ(snn1, nn); + EXPECT_EQ(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_EQ(hash_nn(snn1), hash_nn(nn)); + EXPECT_EQ(hash_snn(snn1), hash_nn(nn)); + EXPECT_EQ(hash_nn(snn1), hash_nn(snn2)); + EXPECT_EQ(hash_snn(snn1), hash_snn(nn)); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -132,8 +133,7 @@ TEST_CASE("TestStrictNotNull") #if defined(__cplusplus) && (__cplusplus >= 201703L) -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -TEST_CASE("TestStrictNotNullConstructorTypeDeduction") +TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) { { int i = 42; @@ -142,7 +142,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") helper(strict_not_null{&i}); helper_const(strict_not_null{&i}); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -153,7 +153,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") helper(strict_not_null{p}); helper_const(strict_not_null{p}); - CHECK(*x == 42); + EXPECT_EQ(*x, 42); } { @@ -161,7 +161,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction") int* p1 = nullptr; const strict_not_null x{p1}; }; - CHECK_THROWS_AS(workaround_macro(), fail_fast); + EXPECT_DEATH(workaround_macro(), ".*"); } { @@ -169,14 +169,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(), ".*"); } { 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}), ".*"); + EXPECT_DEATH(helper_const(strict_not_null{p}), ".*"); } #ifdef CONFIRM_COMPILATION_ERRORS diff --git a/tests/strided_span_tests.cpp b/tests/strided_span_tests.cpp index f201df4..460bb01 100644 --- a/tests/strided_span_tests.cpp +++ b/tests/strided_span_tests.cpp @@ -18,7 +18,7 @@ // 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 @@ -27,7 +27,7 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif -#include // for AssertionHandler, StringRef, CHECK, CHECK... +#include #include // for byte #include // for narrow_cast @@ -54,9 +54,66 @@ 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 +123,52 @@ 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_EQ(sav1[0], 1); EXPECT_EQ(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_EQ(sav2[0], 1); EXPECT_EQ(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_EQ((sav3[{0, 0}]), 1); + EXPECT_EQ((sav3[{0, 1}]), 3); + EXPECT_EQ((sav3[{1, 0}]), 7); } - // Check multi_span constructor + // EXPECT_TRUE multi_span constructor { int arr[] = {1, 2}; @@ -119,9 +177,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 +189,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 +199,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 +209,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 +219,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 +230,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 +240,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 +250,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 +260,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 +280,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_EQ((sav2[{0, 0}]), 1); + EXPECT_EQ((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 +316,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 +362,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,30 +383,29 @@ 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); @@ -356,88 +413,88 @@ TEST_CASE("strided_span_bounds") { // 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], ".*"); + EXPECT_DEATH(av.section(1, 0)[0], ".*"); + EXPECT_DEATH(av.section(1, 1)[1], ".*"); - 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), ".*"); + EXPECT_DEATH(av.section(5, 2), ".*"); + EXPECT_DEATH(av.section(5, 0), ".*"); + EXPECT_DEATH(av.section(0, 5), ".*"); + EXPECT_DEATH(av.section(5, 5), ".*"); } { // 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], ".*"); } { // zero extent strided_span sav{av, {{}, {1}}}; - CHECK_THROWS_AS(sav[0], fail_fast); + EXPECT_DEATH(sav[0], ".*"); } { // zero extent and stride strided_span sav{av, {{}, {}}}; - CHECK_THROWS_AS(sav[0], fail_fast); + EXPECT_DEATH(sav[0], ".*"); } { // 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], ".*"); } { // 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], ".*"); } { // 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], ".*"); } { // 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}}), ".*"); + EXPECT_DEATH((strided_span{arr, {3, 3}}), ".*"); + EXPECT_DEATH((strided_span{arr, {4, 5}}), ".*"); + EXPECT_DEATH((strided_span{arr, {5, 1}}), ".*"); + EXPECT_DEATH((strided_span{arr, {5, 5}}), ".*"); } { // 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}}), ".*"); + EXPECT_DEATH((strided_span{av, {3, 3}}), ".*"); + EXPECT_DEATH((strided_span{av, {4, 5}}), ".*"); + EXPECT_DEATH((strided_span{av, {5, 1}}), ".*"); + EXPECT_DEATH((strided_span{av, {5, 5}}), ".*"); } { // 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}}), ".*"); + EXPECT_DEATH((strided_span{av.data(), 4, {3, 3}}), ".*"); + EXPECT_DEATH((strided_span{av.data(), 4, {4, 5}}), ".*"); + EXPECT_DEATH((strided_span{av.data(), 4, {5, 1}}), ".*"); + EXPECT_DEATH((strided_span{av.data(), 4, {5, 5}}), ".*"); + EXPECT_DEATH((strided_span{av.data(), 2, {2, 2}}), ".*"); } #ifdef CONFIRM_COMPILATION_ERRORS @@ -464,8 +521,7 @@ 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); @@ -490,10 +546,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], ".*"); + EXPECT_DEATH(sav3[0][1], ".*"); } // retype strided array with regular strides - from multi_span @@ -503,10 +559,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], ".*"); + EXPECT_DEATH(sav3[0][1], ".*"); } // retype strided array with not enough elements - last dimension of the array is too small @@ -515,7 +571,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(), ".*"); } // retype strided array with not enough elements - strides are too small @@ -524,7 +580,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(), ".*"); } // retype strided array with not enough elements - last dimension does not divide by the new @@ -534,7 +590,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(), ".*"); } // retype strided array with not enough elements - strides does not divide by the new @@ -544,88 +600,58 @@ 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(), ".*"); } // 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(), ".*"); } // 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(), ".*"); } } -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) { { 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], ".*"); + EXPECT_DEATH(empty_sav.begin()[0], ".*"); + EXPECT_DEATH(empty_sav.cbegin()[0], ".*"); 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], ".*"); + EXPECT_DEATH(empty_sav.begin()[0], ".*"); + EXPECT_DEATH(empty_sav.cbegin()[0], ".*"); 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 +668,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 +682,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 +696,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,10 +728,7 @@ 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) { // get an multi_span of 'c' values from the list of X's @@ -767,8 +748,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 +759,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,12 +772,12 @@ 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], ".*"); int i = 0; for (auto& num : result) { - CHECK(num == arr[i].c); + EXPECT_TRUE(num == arr[i].c); i++; } } diff --git a/tests/string_span_tests.cpp b/tests/string_span_tests.cpp index fd3e3e6..2a56c46 100644 --- a/tests/string_span_tests.cpp +++ b/tests/string_span_tests.cpp @@ -21,7 +21,7 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#include #include // for Expects, fail_fast (ptr only) #include // for owner @@ -44,8 +44,6 @@ 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 +52,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 +59,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) @@ -815,89 +79,6 @@ 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) { Expects(span.size() > 1); @@ -915,45 +96,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 +113,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 +130,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,10 +146,919 @@ 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_EQ(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_EQ(v.length(), static_cast::index_type>(s.length())); +} + +TEST(string_span_tests, TestConstructFromStdVector) +{ + std::vector vec(5, 'h'); + string_span<> v{vec}; + EXPECT_EQ(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_EQ(v.length(), 5); + } + + { + cwstring_span<> v = stack_string; + EXPECT_EQ(v.length(), 5); + } + + { + wstring_span<> v = ensure_z(stack_string); + EXPECT_EQ(v.length(), 5); + } + + { + wstring_span<> v = stack_string; + EXPECT_EQ(v.length(), 5); + } +} + +TEST(string_span_tests, TestConstructFromConstCharPointer) +{ + const char* s = "Hello"; + cstring_span<> v = ensure_z(s); + EXPECT_EQ(v.length(), 5); +} + +TEST(string_span_tests, TestConversionToConst) +{ + char stack_string[] = "Hello"; + string_span<> v = ensure_z(stack_string); + cstring_span<> v2 = v; + EXPECT_EQ(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_EQ(s.length(), 0); + + char stack_string[] = "Hello"; + cstring_span<> v = ensure_z(stack_string); + auto s2 = gsl::to_string(v); + EXPECT_EQ(static_cast::index_type>(s2.length()), v.length()); + EXPECT_EQ(s2.length(), 5); +} + +TEST(string_span_tests, TestToBasicString) +{ + auto s = gsl::to_basic_string, ::std::allocator>( + cstring_span<>{}); + EXPECT_EQ(s.length(), 0); + + char stack_string[] = "Hello"; + cstring_span<> v = ensure_z(stack_string); + auto s2 = gsl::to_basic_string, ::std::allocator>(v); + EXPECT_EQ(static_cast::index_type>(s2.length()), v.length()); + EXPECT_EQ(s2.length(), 5); +} + +TEST(string_span_tests, EqualityAndImplicitConstructors) +{ + { + cstring_span<> span = "Hello"; + cstring_span<> span1; + + // comparison to empty span + EXPECT_NE(span1, span); + EXPECT_NE(span, span1); + } + + { + cstring_span<> span = "Hello"; + cstring_span<> span1 = "Hello1"; + + // comparison to different span + EXPECT_NE(span1, span); + EXPECT_NE(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_EQ(span, cstring_span<>("Hello")); + + // comparison to static array with no null termination + EXPECT_EQ(span, cstring_span<>(ar)); + + // comparison to static array with null at the end + EXPECT_EQ(span, cstring_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_EQ(span, cstring_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_EQ(span, cstring_span<>(ptr, 5)); + + // comparison to string + EXPECT_EQ(span, cstring_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_EQ(span, cstring_span<>(vec)); + + // comparison to span + EXPECT_EQ(span, cstring_span<>(sp)); + + // comparison to string_span + EXPECT_EQ(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_EQ(span, string_span<>(ar)); + + // comparison to static array with null at the end + EXPECT_EQ(span, string_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_EQ(span, string_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_EQ(span, string_span<>(ptr, 5)); + + // comparison to string + EXPECT_EQ(span, string_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_EQ(span, string_span<>(vec)); + + // comparison to span + EXPECT_EQ(span, string_span<>(sp)); + + // comparison to string_span + EXPECT_EQ(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_EQ(span, "Hello"); + EXPECT_EQ(span, ar); + EXPECT_EQ(span, ar1); + EXPECT_EQ(span, ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + const char* ptr = "Hello"; + EXPECT_EQ(span, ptr); +#endif + EXPECT_EQ(span, str); + EXPECT_EQ(span, vec); + EXPECT_EQ(span, sp); + + EXPECT_EQ("Hello", span); + EXPECT_EQ(ar, span); + EXPECT_EQ(ar1, span); + EXPECT_EQ(ar2, span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(ptr, span); +#endif + EXPECT_EQ(str, span); + EXPECT_EQ(vec, span); + EXPECT_EQ(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_EQ(span, _ar); + EXPECT_EQ(span, _ar1); + EXPECT_EQ(span, _ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(span, _ptr); +#endif + EXPECT_EQ(span, _str); + EXPECT_EQ(span, _vec); + EXPECT_EQ(span, _sp); + + EXPECT_EQ(_ar, span); + EXPECT_EQ(_ar1, span); + EXPECT_EQ(_ar2, span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(_ptr, span); +#endif + EXPECT_EQ(_str, span); + EXPECT_EQ(_vec, span); + EXPECT_EQ(_sp, span); + + string_span<> _span{_ptr, 5}; + + // non-const span, non-const other type + + EXPECT_EQ(_span, _ar); + EXPECT_EQ(_span, _ar1); + EXPECT_EQ(_span, _ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(_span, _ptr); +#endif + EXPECT_EQ(_span, _str); + EXPECT_EQ(_span, _vec); + EXPECT_EQ(_span, _sp); + + EXPECT_EQ(_ar, _span); + EXPECT_EQ(_ar1, _span); + EXPECT_EQ(_ar2, _span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(_ptr, _span); +#endif + EXPECT_EQ(_str, _span); + EXPECT_EQ(_vec, _span); + EXPECT_EQ(_sp, _span); + + // non-const span, const other type + + EXPECT_EQ(_span, "Hello"); + EXPECT_EQ(_span, ar); + EXPECT_EQ(_span, ar1); + EXPECT_EQ(_span, ar2); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(_span, ptr); +#endif + EXPECT_EQ(_span, str); + EXPECT_EQ(_span, vec); + EXPECT_EQ(_span, sp); + + EXPECT_EQ("Hello", _span); + EXPECT_EQ(ar, _span); + EXPECT_EQ(ar1, _span); + EXPECT_EQ(ar2, _span); +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_EQ(ptr, _span); +#endif + EXPECT_EQ(str, _span); + EXPECT_EQ(vec, _span); + EXPECT_EQ(sp, _span); + + // two spans + + EXPECT_EQ(_span, span); + EXPECT_EQ(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_EQ(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_LT(span, cstring_span<>("Helloo")); + EXPECT_GT(span, cstring_span<>("Hell")); + + // comparison to static array with no null termination + EXPECT_GE(span, cstring_span<>(ar)); + + // comparison to static array with null at the end + EXPECT_LE(span, cstring_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_GE(span, cstring_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_LE(span, cstring_span<>(ptr, 5)); + + // comparison to string + EXPECT_GE(span, cstring_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_LE(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_LE(span, string_span<>(ar)); + EXPECT_LT(span, string_span<>(rarr)); + EXPECT_GT(span, string_span<>(larr)); + + // comparison to static array with null at the end + EXPECT_GE(span, string_span<>(ar1)); + + // comparison to static array with null in the middle + EXPECT_LE(span, string_span<>(ar2)); + + // comparison to null-terminated c string + EXPECT_GE(span, string_span<>(ptr, 5)); + + // comparison to string + EXPECT_LE(span, string_span<>(str)); + + // comparison to vector of charaters with no null termination + EXPECT_GE(span, string_span<>(vec)); + } +} + +TEST(string_span_tests, ConstrutorsEnsureZ) +{ + // remove z from literals + { + cstring_span<> sp = "hello"; + EXPECT_EQ(sp.length(), 5); + } + + // take the string as is + { + auto str = std::string("hello"); + cstring_span<> sp = str; + EXPECT_EQ(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_EQ(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_EQ(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_EQ(span.length(), 6); + } +#endif + +// from string temporary +#ifdef CONFIRM_COMPILATION_ERRORS + { + cstring_span<> span = std::string("Hello"); + } +#endif + + // default + { + cstring_span<> span; + EXPECT_EQ(span.length(), 0); + } + + // from string literal + { + cstring_span<> span = "Hello"; + EXPECT_EQ(span.length(), 5); + } + + // from const static array + { + const char ar[] = {'H', 'e', 'l', 'l', 'o'}; + cstring_span<> span = ar; + EXPECT_EQ(span.length(), 5); + } + + // from non-const static array + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + cstring_span<> span = ar; + EXPECT_EQ(span.length(), 5); + } + + // from const ptr and length + { + const char* ptr = "Hello"; + cstring_span<> span{ptr, 5}; + EXPECT_EQ(span.length(), 5); + } + + // from const ptr and length, include 0 + { + const char* ptr = "Hello"; + cstring_span<> span{ptr, 6}; + EXPECT_EQ(span.length(), 6); + } + + // from const ptr and length, 0 inside + { + const char* ptr = "He\0lo"; + cstring_span<> span{ptr, 5}; + EXPECT_EQ(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_EQ(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_EQ(span.length(), 5); + } + + // from const string + { + const std::string str = "Hello"; + const cstring_span<> span = str; + EXPECT_EQ(span.length(), 5); + } + + // from non-const string + { + std::string str = "Hello"; + const cstring_span<> span = str; + EXPECT_EQ(span.length(), 5); + } + + // from const vector + { + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const cstring_span<> span = vec; + EXPECT_EQ(span.length(), 5); + } + + // from non-const vector + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + const cstring_span<> span = vec; + EXPECT_EQ(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_EQ(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_EQ(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_EQ(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_EQ(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_EQ(span.length(), 5); +#endif + } + + // from non-const static array + { + char ar[] = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = ar; + EXPECT_EQ(span.length(), 5); + } + + // from const ptr and length + { +#ifdef CONFIRM_COMPILATION_ERRORS + const char* ptr = "Hello"; + string_span<> span{ptr, 5}; + EXPECT_EQ(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_EQ(span.length(), 5); + } + + // from const string + { +#ifdef CONFIRM_COMPILATION_ERRORS + const std::string str = "Hello"; + string_span<> span = str; + EXPECT_EQ(span.length(), 5); +#endif + } + + // from non-const string + { + std::string str = "Hello"; + string_span<> span = str; + EXPECT_EQ(span.length(), 5); + } + + // from const vector + { +#ifdef CONFIRM_COMPILATION_ERRORS + const std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = vec; + EXPECT_EQ(span.length(), 5); +#endif + } + + // from non-const vector + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + string_span<> span = vec; + EXPECT_EQ(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_EQ(span.length(), 5); +#endif + } + + // from non-const span + { + std::vector vec = {'H', 'e', 'l', 'l', 'o'}; + span inner = vec; + string_span<> span = inner; + EXPECT_EQ(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_EQ(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_EQ(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_EQ(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_EQ(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_EQ(span.length(), 5); + } +} + +TEST(string_span_tests, MoveConstructors) +{ + // move string_span + { + cstring_span<> span = "Hello"; + const auto span1 = std::move(span); + EXPECT_EQ(span1.length(), 5); + } + { + cstring_span<> span = "Hello"; + const auto span1 = move_wrapper(std::move(span)); + EXPECT_EQ(span1.length(), 5); + } + { + cstring_span<> span = "Hello"; + const auto span1 = move_wrapper(std::move(span)); + EXPECT_EQ(span1.length(), 5); + } + + // move span + { + span span = ensure_z("Hello"); + const cstring_span<> span1 = std::move(span); + EXPECT_EQ(span1.length(), 5); + } + { + span span = ensure_z("Hello"); + const cstring_span<> span2 = move_wrapper(std::move(span)); + EXPECT_EQ(span2.length(), 5); + } + + // move string + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::string str = "Hello"; + string_span<> span = std::move(str); + EXPECT_EQ(span.length(), 5); +#endif + } + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::string str = "Hello"; + string_span<> span = move_wrapper(std::move(str)); + EXPECT_EQ(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_EQ(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_EQ(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_EQ(wspan.length(), 5); +#endif +} + +TEST(string_span_tests, zstring) +{ + + // create zspan from zero terminated string + { + char buf[1]; + buf[0] = '\0'; + + zstring_span<> zspan({buf, 1}); + + EXPECT_EQ(generic::strlen(zspan.assume_z()), 0); + EXPECT_EQ(zspan.as_string_span().size(), 0); + EXPECT_EQ(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(), ".*"); + } + + // 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_EQ(generic::strlen(str), 3); + EXPECT_EQ(*(str + 3), '\0'); + } + } +} + +TEST(string_span_tests, wzstring) +{ + + // create zspan from zero terminated string + { + wchar_t buf[1]; + buf[0] = L'\0'; + + wzstring_span<> zspan({buf, 1}); + + EXPECT_EQ(generic::strnlen(zspan.assume_z(), 1), 0); + EXPECT_EQ(zspan.as_string_span().size(), 0); + EXPECT_EQ(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(), ".*"); + } + + // 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_EQ(generic::strnlen(str, 10), 3); + EXPECT_EQ(*(str + 3), L'\0'); + } + } +} + +TEST(string_span_tests, u16zstring) +{ + + // create zspan from zero terminated string + { + char16_t buf[1]; + buf[0] = L'\0'; + + u16zstring_span<> zspan({buf, 1}); + + EXPECT_EQ(generic::strnlen(zspan.assume_z(), 1), 0); + EXPECT_EQ(zspan.as_string_span().size(), 0); + EXPECT_EQ(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(), ".*"); + } + + // 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_EQ(generic::strnlen(str, 10), 3); + EXPECT_EQ(*(str + 3), L'\0'); + } + } +} + +TEST(string_span_tests, u32zstring) { // create zspan from zero terminated string @@ -1095,9 +1068,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_EQ(generic::strnlen(zspan.assume_z(), 1), 0); + EXPECT_EQ(zspan.as_string_span().size(), 0); + EXPECT_EQ(zspan.ensure_z().size(), 0); } // create zspan from non-zero terminated string @@ -1106,7 +1079,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(), ".*"); } // usage scenario: create zero-terminated temp file name and pass to a legacy API @@ -1116,118 +1089,112 @@ 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_EQ(generic::strnlen(str, 10), 3); + EXPECT_EQ(*(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_EQ(foo["foo"], 0); + EXPECT_EQ(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_EQ(ss1.size(), 3); + EXPECT_EQ(ss1.size_bytes(), 6); std::u16string s1 = gsl::to_string(ss1); - CHECK(s1 == u"abc"); + EXPECT_EQ(s1, u"abc"); std::u16string s2 = u"abc"; gsl::u16string_span<> ss2 = s2; - CHECK(ss2.size() == 3); + EXPECT_EQ(ss2.size(), 3); gsl::u16string_span<> ss3 = ss2.subspan(1, 1); - CHECK(ss3.size() == 1); - CHECK(ss3[0] == u'b'); + EXPECT_EQ(ss3.size(), 1); + EXPECT_EQ(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_EQ(ss4[3], u'\0'); gsl::cu16zstring_span<> ss5(u"abc"); - CHECK(ss5.as_string_span().size() == 3); + EXPECT_EQ((ss5.as_string_span().size()), 3); gsl::cu16string_span<> ss6 = ss5.as_string_span(); - CHECK(ss6 == ss1); + EXPECT_EQ(ss6, ss1); std::vector v7 = {u'a', u'b', u'c'}; gsl::cu16string_span<> ss7{v7}; - CHECK(ss7 == ss1); + EXPECT_EQ(ss7, ss1); gsl::cu16string_span<> ss8 = gsl::ensure_z(u"abc"); gsl::cu16string_span<> ss9 = gsl::ensure_z(u"abc"); - CHECK(ss8 == ss9); + EXPECT_EQ(ss8, ss9); ss9 = gsl::ensure_z(u"abd"); - CHECK(ss8 < ss9); - CHECK(ss8 <= ss9); - CHECK(ss8 != ss9); + EXPECT_LT(ss8, ss9); + EXPECT_LE(ss8, ss9); + EXPECT_NE(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_EQ(ss1.size(), 3); + EXPECT_EQ(ss1.size_bytes(), 12); std::u32string s1 = gsl::to_string(ss1); - CHECK(s1 == U"abc"); + EXPECT_EQ(s1, U"abc"); std::u32string s2 = U"abc"; gsl::u32string_span<> ss2 = s2; - CHECK(ss2.size() == 3); + EXPECT_EQ(ss2.size(), 3); gsl::u32string_span<> ss3 = ss2.subspan(1, 1); - CHECK(ss3.size() == 1); - CHECK(ss3[0] == U'b'); + EXPECT_EQ(ss3.size(), 1); + EXPECT_EQ(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_EQ(ss4[3], u'\0'); gsl::cu32zstring_span<> ss5(U"abc"); - CHECK(ss5.as_string_span().size() == 3); + EXPECT_EQ(ss5.as_string_span().size(), 3); gsl::cu32string_span<> ss6 = ss5.as_string_span(); - CHECK(ss6 == ss1); + EXPECT_EQ(ss6, ss1); gsl::cu32string_span<> ss8 = gsl::ensure_z(U"abc"); gsl::cu32string_span<> ss9 = gsl::ensure_z(U"abc"); - CHECK(ss8 == ss9); + EXPECT_EQ(ss8, ss9); ss9 = gsl::ensure_z(U"abd"); - CHECK(ss8 < ss9); - CHECK(ss8 <= ss9); - CHECK(ss8 != ss9); + EXPECT_LT(ss8, ss9); + EXPECT_LE(ss8, ss9); + EXPECT_NE(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_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(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_EQ(static_cast(bs.data()), static_cast(s.data())); + EXPECT_EQ(bs.size(), s.size_bytes()); } diff --git a/tests/test.cpp b/tests/test.cpp index 47daf5c..735f85d 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -24,4 +24,3 @@ #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..a135749 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -21,7 +21,7 @@ #endif -#include // for AssertionHandler, StringRef, CHECK, TEST_... +#include #include // for narrow, finally, narrow_cast, narrowing_e... @@ -33,101 +33,100 @@ using namespace gsl; -TEST_CASE("sanity check for gsl::index typedef") +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_EQ(i, 0); } - CHECK(i == 1); + EXPECT_EQ(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_EQ(i, 0); } - CHECK(i == 1); + EXPECT_EQ(i, 1); { auto _2 = std::move(_1); - CHECK(i == 1); + EXPECT_EQ(i, 1); } - CHECK(i == 1); + EXPECT_EQ(i, 1); } - CHECK(i == 1); + EXPECT_EQ(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_EQ(i, 0); } - CHECK(i == 1); + EXPECT_EQ(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_EQ(j, 0); } - CHECK(j == 1); + EXPECT_EQ(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_EQ(c, 120); n = 300; unsigned char uc = narrow_cast(n); - CHECK(uc == 44); + EXPECT_EQ(uc, 44); } -GSL_SUPPRESS(con.5) // NO-FORMAT: attribute -TEST_CASE("narrow") +TEST(utils_tests, narrow) { int n = 120; const char c = narrow(n); - CHECK(c == 120); + EXPECT_EQ(c, 120); n = 300; - CHECK_THROWS_AS(narrow(n), narrowing_error); + EXPECT_DEATH(narrow(n), ".*"); 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)), ".*"); + EXPECT_DEATH(narrow(int32_min), ".*"); n = -42; - CHECK_THROWS_AS(narrow(n), narrowing_error); + EXPECT_DEATH(narrow(n), ".*"); #if GSL_CONSTEXPR_NARROW static_assert(narrow(120) == 120, "Fix GSL_CONSTEXPR_NARROW"); #endif + }