gtest migration

This commit is contained in:
Jordan Maples [MSFT] 2019-12-03 14:32:25 -08:00
parent 7e99e76c97
commit 2b10729386
17 changed files with 3453 additions and 3588 deletions

View File

@ -50,19 +50,6 @@
#endif #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_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
@ -94,10 +81,6 @@
namespace gsl namespace gsl
{ {
struct fail_fast : public std::logic_error
{
explicit fail_fast(char const* const message) : std::logic_error(message) {}
};
namespace details namespace details
{ {
@ -128,7 +111,6 @@ namespace details
#endif #endif
} }
#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
template <typename Exception> template <typename Exception>
[[noreturn]] void throw_exception(Exception&&) noexcept [[noreturn]] void throw_exception(Exception&&) noexcept
@ -136,37 +118,14 @@ namespace details
gsl::details::terminate(); gsl::details::terminate();
} }
#else
template <typename Exception>
[[noreturn]] void throw_exception(Exception&& exception)
{
throw std::forward<Exception>(exception);
}
#endif // GSL_TERMINATE_ON_CONTRACT_VIOLATION
} // namespace details } // namespace details
} // namespace gsl } // namespace gsl
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(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) \ #define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate()) (GSL_LIKELY(cond) ? static_cast<void>(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 Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) #define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)

View File

@ -5,27 +5,33 @@ project(GSLTests CXX)
# will make visual studio generated project group files # will make visual studio generated project group files
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CATCH_CMAKE_ARGS configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
"-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/external" execute_process(
"-DNO_SELFTEST=true" COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
) )
if(result)
if(GIT_FOUND) message(FATAL_ERROR "CMake step for googletest failed: ${result}")
# 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)
endif() 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)) if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-) set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
endif() endif()
@ -78,34 +84,20 @@ else()
) )
endif(MSVC) endif(MSVC)
# for tests to find the catch header # for tests to find the gtest header
target_include_directories(gsl_tests_config INTERFACE target_include_directories(gsl_tests_config SYSTEM INTERFACE
${CMAKE_BINARY_DIR}/external/include googletest/googletest/include
) )
# set definitions for tests set_property(TARGET PROPERTY FOLDER "GSL_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")
function(add_gsl_test name) function(add_gsl_test name)
add_executable(${name} ${name}.cpp) add_executable(${name} ${name}.cpp)
target_link_libraries(${name} target_link_libraries(${name}
GSL GSL
test_catch
gsl_tests_config gsl_tests_config
gtest_main
) )
add_dependencies(${name} catch)
add_test( add_test(
${name} ${name}
${name} ${name}
@ -141,9 +133,6 @@ endforeach(flag_var)
# please try to keep entries ordered =) # please try to keep entries ordered =)
add_library(gsl_tests_config_noexcept INTERFACE) add_library(gsl_tests_config_noexcept INTERFACE)
if(MSVC) # MSVC or simulating MSVC 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 target_compile_options(gsl_tests_config_noexcept INTERFACE
${GSL_CPLUSPLUS_OPT} ${GSL_CPLUSPLUS_OPT}
/W4 /W4
@ -184,16 +173,12 @@ else()
) )
endif(MSVC) 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) function(add_gsl_test_noexcept name)
add_executable(${name} ${name}.cpp) add_executable(${name} ${name}.cpp)
target_link_libraries(${name} target_link_libraries(${name}
GSL GSL
gsl_tests_config_noexcept gsl_tests_config_noexcept
gtest_main
) )
add_test( add_test(
${name} ${name}
@ -203,5 +188,5 @@ function(add_gsl_test_noexcept name)
set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests_noexcept") set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests_noexcept")
endfunction() endfunction()
add_gsl_test_noexcept(no_exception_throw_tests) # add_gsl_test_noexcept(no_exception_throw_tests)
add_gsl_test_noexcept(no_exception_ensure_tests) # add_gsl_test_noexcept(no_exception_ensure_tests)

14
tests/CMakeLists.txt.in Normal file
View File

@ -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 ""
)

View File

@ -20,7 +20,7 @@
#pragma warning(disable : 26440 26426) // from catch #pragma warning(disable : 26440 26426) // from catch
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHE... #include <gtest/gtest.h>
#include <gsl/gsl_algorithm> // for copy #include <gsl/gsl_algorithm> // for copy
#include <gsl/span> // for span #include <gsl/span> // for span
@ -35,9 +35,7 @@ struct fail_fast;
using namespace std; using namespace std;
using namespace gsl; using namespace gsl;
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute TEST(algorithm_tests, same_type)
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("same_type")
{ {
// dynamic source and destination span // dynamic source and destination span
{ {
@ -51,8 +49,8 @@ TEST_CASE("same_type")
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == 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())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == 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())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == 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())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == src[i]); EXPECT_EQ(dst[i + src.size()], src[i]);
} }
} }
} }
TEST(algorithm_tests, compatible_type)
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("compatible_type")
{ {
// dynamic source and destination span // dynamic source and destination span
{ {
@ -125,8 +120,8 @@ TEST_CASE("compatible_type")
copy(src_span, dst_span.subspan(src_span.size())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == 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())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == 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())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == 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())); copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) { for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]); EXPECT_EQ(dst[i], src[i]);
CHECK(dst[i + src.size()] == src[i]); EXPECT_EQ(dst[i + src.size()], src[i]);
} }
} }
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
TEST_CASE("incompatible_type") TEST(algorithm_tests, incompatible_type)
{ {
std::array<int, 4> src{1, 2, 3, 4}; std::array<int, 4> src{1, 2, 3, 4};
std::array<int*, 12> dst{}; std::array<int*, 12> dst{};
@ -201,7 +196,7 @@ TEST_CASE("incompatible_type")
} }
#endif #endif
TEST_CASE("small_destination_span") TEST(algorithm_tests, small_destination_span)
{ {
std::array<int, 12> src{1, 2, 3, 4}; std::array<int, 12> src{1, 2, 3, 4};
std::array<int, 4> dst{}; std::array<int, 4> dst{};
@ -211,9 +206,9 @@ TEST_CASE("small_destination_span")
const span<int> dst_span_dyn(dst); const span<int> dst_span_dyn(dst);
const span<int, 4> dst_span_static(dst); const span<int, 4> dst_span_static(dst);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_dyn), fail_fast); EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), ".*");
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_static), fail_fast); EXPECT_DEATH(copy(src_span_dyn, dst_span_static), ".*");
CHECK_THROWS_AS(copy(src_span_static, dst_span_dyn), fail_fast); EXPECT_DEATH(copy(src_span_static, dst_span_dyn), ".*");
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static); copy(src_span_static, dst_span_static);

View File

@ -20,33 +20,37 @@
#pragma warning(disable : 26440 26426) // from catch #pragma warning(disable : 26440 26426) // from catch
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK... #include <gtest/gtest.h>
#include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects #include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects
using namespace gsl; using namespace gsl;
namespace
{
int f(int i) int f(int i)
{ {
Expects(i > 0 && i < 10); Expects(i > 0 && i < 10);
return i; return i;
} }
TEST_CASE("expects")
{
CHECK(f(2) == 2);
CHECK_THROWS_AS(f(10), fail_fast);
}
int g(int i) int g(int i)
{ {
i++; i++;
Ensures(i > 0 && i < 10); Ensures(i > 0 && i < 10);
return i; return i;
} }
} // namespace
TEST_CASE("ensures") TEST(assertion_tests, expects)
{ {
CHECK(g(2) == 3); EXPECT_EQ(f(2), 2);
CHECK_THROWS_AS(g(9), fail_fast); EXPECT_DEATH(f(10), ".*");
}
TEST(assertion_tests, ensures)
{
EXPECT_EQ(g(2), 3);
EXPECT_DEATH(g(9), ".*");
} }

View File

@ -20,7 +20,7 @@
#pragma warning(disable : 26440 26426) // from catch #pragma warning(disable : 26440 26426) // from catch
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK_THROW... #include <gtest/gtest.h>
#include <gsl/gsl_util> // for at #include <gsl/gsl_util> // for at
@ -29,88 +29,70 @@
#include <initializer_list> // for initializer_list #include <initializer_list> // for initializer_list
#include <vector> // for vector #include <vector> // for vector
TEST(at_tests, static_array)
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")
{ {
int a[4] = {1, 2, 3, 4}; int a[4] = {1, 2, 3, 4};
const int(&c_a)[4] = a; const int(&c_a)[4] = a;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(&gsl::at(a, i) == &a[i]); EXPECT_EQ(&gsl::at(a, i), &a[i]);
CHECK(&gsl::at(c_a, i) == &a[i]); EXPECT_EQ(&gsl::at(c_a, i), &a[i]);
} }
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); EXPECT_DEATH(gsl::at(a, -1), ".*");
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); EXPECT_DEATH(gsl::at(a, 4), ".*");
CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast); EXPECT_DEATH(gsl::at(c_a, -1), ".*");
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); EXPECT_DEATH(gsl::at(c_a, 4), ".*");
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute TEST(at_tests, std_array)
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("std_array")
{ {
std::array<int, 4> a = {1, 2, 3, 4}; std::array<int, 4> a = {1, 2, 3, 4};
const std::array<int, 4>& c_a = a; const std::array<int, 4>& c_a = a;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]); EXPECT_EQ(&gsl::at(a, i), &a[static_cast<std::size_t>(i)]);
CHECK(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]); EXPECT_EQ(&gsl::at(c_a, i), &a[static_cast<std::size_t>(i)]);
} }
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); EXPECT_DEATH(gsl::at(a, -1), ".*");
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); EXPECT_DEATH(gsl::at(a, 4), ".*");
CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast); EXPECT_DEATH(gsl::at(c_a, -1), ".*");
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); EXPECT_DEATH(gsl::at(c_a, 4), ".*");
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute TEST(at_tests, StdVector)
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("StdVector")
{ {
std::vector<int> a = {1, 2, 3, 4}; std::vector<int> a = {1, 2, 3, 4};
const std::vector<int>& c_a = a; const std::vector<int>& c_a = a;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]); EXPECT_EQ(&gsl::at(a, i), &a[static_cast<std::size_t>(i)]);
CHECK(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]); EXPECT_EQ(&gsl::at(c_a, i), &a[static_cast<std::size_t>(i)]);
} }
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); EXPECT_DEATH(gsl::at(a, -1), ".*");
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); EXPECT_DEATH(gsl::at(a, 4), ".*");
CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast); EXPECT_DEATH(gsl::at(c_a, -1), ".*");
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast); EXPECT_DEATH(gsl::at(c_a, 4), ".*");
} }
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute TEST(at_tests, InitializerList)
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("InitializerList")
{ {
const std::initializer_list<int> a = {1, 2, 3, 4}; const std::initializer_list<int> a = {1, 2, 3, 4};
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
CHECK(gsl::at(a, i) == i + 1); EXPECT_EQ(gsl::at(a, i), i + 1);
CHECK(gsl::at({1, 2, 3, 4}, i) == i + 1); EXPECT_EQ(gsl::at({1, 2, 3, 4}, i), i + 1);
} }
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast); EXPECT_DEATH(gsl::at(a, -1), ".*");
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast); EXPECT_DEATH(gsl::at(a, 4), ".*");
CHECK_THROWS_AS(gsl::at({1, 2, 3, 4}, -1), fail_fast); EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), ".*");
CHECK_THROWS_AS(gsl::at({1, 2, 3, 4}, 4), fail_fast); EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), ".*");
} }
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910 #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() static constexpr bool test_constexpr()
{ {
int a1[4] = {1, 2, 3, 4}; int a1[4] = {1, 2, 3, 4};

View File

@ -26,7 +26,7 @@
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, TEST_CASE #include <gtest/gtest.h>
#include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t #include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t
@ -44,8 +44,7 @@ namespace
void use(std::ptrdiff_t&) {} void use(std::ptrdiff_t&) {}
} }
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute TEST(bounds_tests, basic_bounds)
TEST_CASE("basic_bounds")
{ {
for (auto point : static_bounds<dynamic_range, 3, 4>{2}) { for (auto point : static_bounds<dynamic_range, 3, 4>{2}) {
for (decltype(point)::size_type j = 0; for (decltype(point)::size_type j = 0;
@ -57,9 +56,7 @@ TEST_CASE("basic_bounds")
} }
} }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute TEST(bounds_tests, bounds_basic)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_basic")
{ {
static_bounds<3, 4, 5> b; static_bounds<3, 4, 5> b;
const auto a = b.slice(); const auto a = b.slice();
@ -68,9 +65,7 @@ TEST_CASE("bounds_basic")
x.slice().slice(); x.slice().slice();
} }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute TEST(bounds_tests, arrayview_iterator)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("arrayview_iterator")
{ {
static_bounds<4, dynamic_range, 2> bounds{3}; static_bounds<4, dynamic_range, 2> bounds{3};
@ -88,8 +83,7 @@ TEST_CASE("arrayview_iterator")
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(bounds_tests, bounds_convertible)
TEST_CASE("bounds_convertible")
{ {
static_bounds<7, 4, 2> b1; static_bounds<7, 4, 2> b1;
static_bounds<7, dynamic_range, 2> b2 = b1; static_bounds<7, dynamic_range, 2> b2 = b1;
@ -108,12 +102,12 @@ TEST_CASE("bounds_convertible")
static_bounds<34> b6; static_bounds<34> b6;
b5 = static_bounds<20>(); b5 = static_bounds<20>();
CHECK_THROWS_AS(b6 = b5, fail_fast); EXPECT_DEATH(b6 = b5, ".*");
b5 = static_bounds<34>(); b5 = static_bounds<34>();
b6 = b5; b6 = b5;
CHECK(b5 == b6); EXPECT_EQ(b5, b6);
CHECK(b5.size() == b6.size()); EXPECT_EQ(b5.size(), b6.size());
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS

View File

@ -20,7 +20,7 @@
#pragma warning(disable : 26440 26426) // from catch #pragma warning(disable : 26440 26426) // from catch
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <gtest/gtest.h>
#include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope... #include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope...
@ -29,91 +29,6 @@ using namespace gsl;
namespace namespace
{ {
TEST_CASE("construction")
{
{
const byte b = static_cast<byte>(4);
CHECK(static_cast<unsigned char>(b) == 4);
}
GSL_SUPPRESS(es.49)
{
const byte b = byte(12);
CHECK(static_cast<unsigned char>(b) == 12);
}
{
const byte b = to_byte<12>();
CHECK(static_cast<unsigned char>(b) == 12);
}
{
const unsigned char uc = 12;
const byte b = to_byte(uc);
CHECK(static_cast<unsigned char>(b) == 12);
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
{
const byte b { 14 };
CHECK(static_cast<unsigned char>(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<char>(b));
CHECK(0x12 == gsl::to_integer<short>(b));
CHECK(0x12 == gsl::to_integer<long>(b));
CHECK(0x12 == gsl::to_integer<long long>(b));
CHECK(0x12 == gsl::to_integer<unsigned char>(b));
CHECK(0x12 == gsl::to_integer<unsigned short>(b));
CHECK(0x12 == gsl::to_integer<unsigned long>(b));
CHECK(0x12 == gsl::to_integer<unsigned long long>(b));
// CHECK(0x12 == gsl::to_integer<float>(b)); // expect compile-time error
// CHECK(0x12 == gsl::to_integer<double>(b)); // expect compile-time error
}
int modify_both(gsl::byte& b, int& i) int modify_both(gsl::byte& b, int& i)
{ {
i = 10; i = 10;
@ -121,12 +36,96 @@ int modify_both(gsl::byte & b, int& i)
return i; return i;
} }
GSL_SUPPRESS(type.1) TEST(byte_tests, construction)
TEST_CASE("aliasing") {
{
const byte b = static_cast<byte>(4);
EXPECT_TRUE(static_cast<unsigned char>(b) == 4);
}
GSL_SUPPRESS(es.49)
{
const byte b = byte(12);
EXPECT_TRUE(static_cast<unsigned char>(b) == 12);
}
{
const byte b = to_byte<12>();
EXPECT_TRUE(static_cast<unsigned char>(b) == 12);
}
{
const unsigned char uc = 12;
const byte b = to_byte(uc);
EXPECT_TRUE(static_cast<unsigned char>(b) == 12);
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
{
const byte b { 14 };
EXPECT_TRUE(static_cast<unsigned char>(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<char>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<short>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<long>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<long long>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<unsigned char>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<unsigned short>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<unsigned long>(b));
EXPECT_TRUE(0x12 == gsl::to_integer<unsigned long long>(b));
// EXPECT_TRUE(0x12 == gsl::to_integer<float>(b)); // expect compile-time error
// EXPECT_TRUE(0x12 == gsl::to_integer<double>(b)); // expect compile-time error
}
TEST(byte_tests, aliasing)
{ {
int i{0}; int i{0};
const int res = modify_both(reinterpret_cast<byte&>(i), i); const int res = modify_both(reinterpret_cast<byte&>(i), i);
CHECK(res == i); EXPECT_TRUE(res == i);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
#pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4702) // unreachable code
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <gtest/gtest.h>
#include <gsl/pointers> // for not_null, operator<, operator<=, operator> #include <gsl/pointers> // for not_null, operator<, operator<=, operator>
@ -135,8 +135,7 @@ bool helper_const(not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; } int* return_pointer() { return nullptr; }
const int* return_pointer_const() { return nullptr; } const int* return_pointer_const() { return nullptr; }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(notnull_tests, TestNotNullConstructors)
TEST_CASE("TestNotNullConstructors")
{ {
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
@ -158,13 +157,13 @@ TEST_CASE("TestNotNullConstructors")
int i = 12; int i = 12;
auto rp = RefCounted<int>(&i); auto rp = RefCounted<int>(&i);
not_null<int*> p(rp); not_null<int*> p(rp);
CHECK(p.get() == &i); EXPECT_EQ(p.get(), &i);
not_null<std::shared_ptr<int>> x( not_null<std::shared_ptr<int>> x(
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
int* pi = nullptr; int* pi = nullptr;
CHECK_THROWS_AS(not_null<decltype(pi)>(pi), fail_fast); EXPECT_DEATH((not_null<decltype(pi)>(pi)), ".*");
} }
{ {
@ -175,7 +174,7 @@ TEST_CASE("TestNotNullConstructors")
helper(&t); helper(&t);
helper_const(&t); helper_const(&t);
CHECK(*x == 42); EXPECT_EQ(*x, 42);
} }
{ {
@ -191,7 +190,7 @@ TEST_CASE("TestNotNullConstructors")
helper(x); helper(x);
helper_const(x); helper_const(x);
CHECK(*x == 42); EXPECT_EQ(*x, 42);
} }
{ {
@ -205,7 +204,7 @@ TEST_CASE("TestNotNullConstructors")
helper_const(cp); helper_const(cp);
helper_const(x); helper_const(x);
CHECK(*x == 42); EXPECT_EQ(*x, 42);
} }
{ {
@ -215,19 +214,18 @@ TEST_CASE("TestNotNullConstructors")
auto x = not_null<const int*>{cp}; auto x = not_null<const int*>{cp};
CHECK(*x == 42); EXPECT_EQ(*x, 42);
} }
{ {
// from returned pointer // from returned pointer
CHECK_THROWS_AS(helper(return_pointer()), fail_fast); EXPECT_DEATH(helper(return_pointer()), ".*");
CHECK_THROWS_AS(helper_const(return_pointer()), fail_fast); EXPECT_DEATH(helper_const(return_pointer()), ".*");
} }
} }
template <typename T> template <typename T>
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
void ostream_helper(T v) void ostream_helper(T v)
{ {
not_null<T*> p(&v); not_null<T*> p(&v);
@ -236,18 +234,18 @@ void ostream_helper(T v)
std::ostringstream ref; std::ostringstream ref;
os << static_cast<void*>(p); os << static_cast<void*>(p);
ref << static_cast<void*>(&v); ref << static_cast<void*>(&v);
CHECK(os.str() == ref.str()); EXPECT_EQ(os.str(), ref.str());
} }
{ {
std::ostringstream os; std::ostringstream os;
std::ostringstream ref; std::ostringstream ref;
os << *p; os << *p;
ref << v; ref << v;
CHECK(os.str() == ref.str()); EXPECT_EQ(os.str(), ref.str());
} }
} }
TEST_CASE("TestNotNullostream") TEST(notnull_tests, TestNotNullostream)
{ {
ostream_helper<int>(17); ostream_helper<int>(17);
ostream_helper<float>(21.5f); ostream_helper<float>(21.5f);
@ -258,9 +256,7 @@ TEST_CASE("TestNotNullostream")
ostream_helper<std::string>("string"); ostream_helper<std::string>("string");
} }
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute TEST(notnull_tests, TestNotNullCasting)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCasting")
{ {
MyBase base; MyBase base;
MyDerived derived; MyDerived derived;
@ -270,7 +266,7 @@ TEST_CASE("TestNotNullCasting")
not_null<MyDerived*> p{&derived}; not_null<MyDerived*> p{&derived};
not_null<MyBase*> q(&base); not_null<MyBase*> q(&base);
q = p; // allowed with heterogeneous copy ctor q = p; // allowed with heterogeneous copy ctor
CHECK(q == p); EXPECT_EQ(q, p);
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
q = u; // no viable conversion possible between MyBase* and Unrelated* q = u; // no viable conversion possible between MyBase* and Unrelated*
@ -280,20 +276,20 @@ TEST_CASE("TestNotNullCasting")
not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p); not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
#endif #endif
not_null<Unrelated*> t(reinterpret_cast<Unrelated*>(p.get())); not_null<Unrelated*> t(reinterpret_cast<Unrelated*>(p.get()));
CHECK(reinterpret_cast<void*>(p.get()) == reinterpret_cast<void*>(t.get())); EXPECT_EQ(reinterpret_cast<void*>(p.get()), reinterpret_cast<void*>(t.get()));
} }
TEST_CASE("TestNotNullAssignment") TEST(notnull_tests, TestNotNullAssignment)
{ {
int i = 12; int i = 12;
not_null<int*> p(&i); not_null<int*> p(&i);
CHECK(helper(p)); EXPECT_TRUE(helper(p));
int* q = nullptr; int* q = nullptr;
CHECK_THROWS_AS(p = not_null<int*>(q), fail_fast); EXPECT_DEATH(p = not_null<int*>(q), ".*");
} }
TEST_CASE("TestNotNullRawPointerComparison") TEST(notnull_tests, TestNotNullRawPointerComparison)
{ {
int ints[2] = {42, 43}; int ints[2] = {42, 43};
int* p1 = &ints[0]; int* p1 = &ints[0];
@ -302,34 +298,33 @@ TEST_CASE("TestNotNullRawPointerComparison")
using NotNull1 = not_null<decltype(p1)>; using NotNull1 = not_null<decltype(p1)>;
using NotNull2 = not_null<decltype(p2)>; using NotNull2 = not_null<decltype(p2)>;
CHECK((NotNull1(p1) == NotNull1(p1)) == true); EXPECT_EQ((NotNull1(p1) == NotNull1(p1)), true);
CHECK((NotNull1(p1) == NotNull2(p2)) == false); EXPECT_EQ((NotNull1(p1) == NotNull2(p2)), false);
CHECK((NotNull1(p1) != NotNull1(p1)) == false); EXPECT_EQ((NotNull1(p1) != NotNull1(p1)), false);
CHECK((NotNull1(p1) != NotNull2(p2)) == true); EXPECT_EQ((NotNull1(p1) != NotNull2(p2)), true);
CHECK((NotNull1(p1) < NotNull1(p1)) == false); EXPECT_EQ((NotNull1(p1) < NotNull1(p1)), false);
CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); EXPECT_EQ((NotNull1(p1) < NotNull2(p2)), (p1 < p2));
CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); EXPECT_EQ((NotNull2(p2) < NotNull1(p1)), (p2 < p1));
CHECK((NotNull1(p1) > NotNull1(p1)) == false); EXPECT_EQ((NotNull1(p1) > NotNull1(p1)), false);
CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); EXPECT_EQ((NotNull1(p1) > NotNull2(p2)), (p1 > p2));
CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); EXPECT_EQ((NotNull2(p2) > NotNull1(p1)), (p2 > p1));
CHECK((NotNull1(p1) <= NotNull1(p1)) == true); EXPECT_EQ((NotNull1(p1) <= NotNull1(p1)), true);
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); EXPECT_EQ((NotNull1(p1) <= NotNull2(p2)), (p1 <= p2));
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); EXPECT_EQ((NotNull2(p2) <= NotNull1(p1)), (p2 <= p1));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(notnull_tests, TestNotNullDereferenceOperator)
TEST_CASE("TestNotNullDereferenceOperator")
{ {
{ {
auto sp1 = std::make_shared<NonCopyableNonMovable>(); auto sp1 = std::make_shared<NonCopyableNonMovable>();
using NotNullSp1 = not_null<decltype(sp1)>; using NotNullSp1 = not_null<decltype(sp1)>;
CHECK(typeid(*sp1) == typeid(*NotNullSp1(sp1))); EXPECT_EQ(typeid(*sp1), typeid(*NotNullSp1(sp1)));
CHECK(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1)); EXPECT_EQ(std::addressof(*NotNullSp1(sp1)), std::addressof(*sp1));
} }
{ {
@ -337,22 +332,22 @@ TEST_CASE("TestNotNullDereferenceOperator")
CustomPtr<int> p1(&ints[0]); CustomPtr<int> p1(&ints[0]);
using NotNull1 = not_null<decltype(p1)>; using NotNull1 = not_null<decltype(p1)>;
CHECK(typeid(*NotNull1(p1)) == typeid(*p1)); EXPECT_EQ(typeid(*NotNull1(p1)), typeid(*p1));
CHECK(*NotNull1(p1) == 42); EXPECT_EQ(*NotNull1(p1), 42);
*NotNull1(p1) = 43; *NotNull1(p1) = 43;
CHECK(ints[0] == 43); EXPECT_EQ(ints[0], 43);
} }
{ {
int v = 42; int v = 42;
gsl::not_null<int*> p(&v); gsl::not_null<int*> p(&v);
CHECK(typeid(*p) == typeid(*(&v))); EXPECT_EQ(typeid(*p), typeid(*(&v)));
*p = 43; *p = 43;
CHECK(v == 43); EXPECT_EQ(v, 43);
} }
} }
TEST_CASE("TestNotNullSharedPtrComparison") TEST(notnull_tests, TestNotNullSharedPtrComparison)
{ {
auto sp1 = std::make_shared<int>(42); auto sp1 = std::make_shared<int>(42);
auto sp2 = std::make_shared<const int>(43); auto sp2 = std::make_shared<const int>(43);
@ -360,31 +355,30 @@ TEST_CASE("TestNotNullSharedPtrComparison")
using NotNullSp1 = not_null<decltype(sp1)>; using NotNullSp1 = not_null<decltype(sp1)>;
using NotNullSp2 = not_null<decltype(sp2)>; using NotNullSp2 = not_null<decltype(sp2)>;
CHECK((NotNullSp1(sp1) == NotNullSp1(sp1)) == true); EXPECT_EQ((NotNullSp1(sp1) == NotNullSp1(sp1)), true);
CHECK((NotNullSp1(sp1) == NotNullSp2(sp2)) == false); EXPECT_EQ((NotNullSp1(sp1) == NotNullSp2(sp2)), false);
CHECK((NotNullSp1(sp1) != NotNullSp1(sp1)) == false); EXPECT_EQ((NotNullSp1(sp1) != NotNullSp1(sp1)), false);
CHECK((NotNullSp1(sp1) != NotNullSp2(sp2)) == true); EXPECT_EQ((NotNullSp1(sp1) != NotNullSp2(sp2)), true);
CHECK((NotNullSp1(sp1) < NotNullSp1(sp1)) == false); EXPECT_EQ((NotNullSp1(sp1) < NotNullSp1(sp1)), false);
CHECK((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2)); EXPECT_EQ((NotNullSp1(sp1) < NotNullSp2(sp2)), (sp1 < sp2));
CHECK((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1)); EXPECT_EQ((NotNullSp2(sp2) < NotNullSp1(sp1)), (sp2 < sp1));
CHECK((NotNullSp1(sp1) > NotNullSp1(sp1)) == false); EXPECT_EQ((NotNullSp1(sp1) > NotNullSp1(sp1)), false);
CHECK((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2)); EXPECT_EQ((NotNullSp1(sp1) > NotNullSp2(sp2)), (sp1 > sp2));
CHECK((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1)); EXPECT_EQ((NotNullSp2(sp2) > NotNullSp1(sp1)), (sp2 > sp1));
CHECK((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true); EXPECT_EQ((NotNullSp1(sp1) <= NotNullSp1(sp1)), true);
CHECK((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2)); EXPECT_EQ((NotNullSp1(sp1) <= NotNullSp2(sp2)), (sp1 <= sp2));
CHECK((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1)); EXPECT_EQ((NotNullSp2(sp2) <= NotNullSp1(sp1)), (sp2 <= sp1));
CHECK((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true); EXPECT_EQ((NotNullSp1(sp1) >= NotNullSp1(sp1)), true);
CHECK((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2)); EXPECT_EQ((NotNullSp1(sp1) >= NotNullSp2(sp2)), (sp1 >= sp2));
CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1)); EXPECT_EQ((NotNullSp2(sp2) >= NotNullSp1(sp1)), (sp2 >= sp1));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(notnull_tests, TestNotNullCustomPtrComparison)
TEST_CASE("TestNotNullCustomPtrComparison")
{ {
int ints[2] = {42, 43}; int ints[2] = {42, 43};
CustomPtr<int> p1(&ints[0]); CustomPtr<int> p1(&ints[0]);
@ -393,33 +387,32 @@ TEST_CASE("TestNotNullCustomPtrComparison")
using NotNull1 = not_null<decltype(p1)>; using NotNull1 = not_null<decltype(p1)>;
using NotNull2 = not_null<decltype(p2)>; using NotNull2 = not_null<decltype(p2)>;
CHECK((NotNull1(p1) == NotNull1(p1)) == "true"); EXPECT_EQ((NotNull1(p1) == NotNull1(p1)), "true");
CHECK((NotNull1(p1) == NotNull2(p2)) == "false"); EXPECT_EQ((NotNull1(p1) == NotNull2(p2)), "false");
CHECK((NotNull1(p1) != NotNull1(p1)) == "false"); EXPECT_EQ((NotNull1(p1) != NotNull1(p1)), "false");
CHECK((NotNull1(p1) != NotNull2(p2)) == "true"); EXPECT_EQ((NotNull1(p1) != NotNull2(p2)), "true");
CHECK((NotNull1(p1) < NotNull1(p1)) == "false"); EXPECT_EQ((NotNull1(p1) < NotNull1(p1)), "false");
CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); EXPECT_EQ((NotNull1(p1) < NotNull2(p2)), (p1 < p2));
CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); EXPECT_EQ((NotNull2(p2) < NotNull1(p1)), (p2 < p1));
CHECK((NotNull1(p1) > NotNull1(p1)) == "false"); EXPECT_EQ((NotNull1(p1) > NotNull1(p1)), "false");
CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); EXPECT_EQ((NotNull1(p1) > NotNull2(p2)), (p1 > p2));
CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); EXPECT_EQ((NotNull2(p2) > NotNull1(p1)), (p2 > p1));
CHECK((NotNull1(p1) <= NotNull1(p1)) == "true"); EXPECT_EQ((NotNull1(p1) <= NotNull1(p1)), "true");
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); EXPECT_EQ((NotNull1(p1) <= NotNull2(p2)), (p1 <= p2));
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); EXPECT_EQ((NotNull2(p2) <= NotNull1(p1)), (p2 <= p1));
CHECK((NotNull1(p1) >= NotNull1(p1)) == "true"); EXPECT_EQ((NotNull1(p1) >= NotNull1(p1)), "true");
CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2)); EXPECT_EQ((NotNull1(p1) >= NotNull2(p2)), (p1 >= p2));
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1)); EXPECT_EQ((NotNull2(p2) >= NotNull1(p1)), (p2 >= p1));
} }
#if defined(__cplusplus) && (__cplusplus >= 201703L) #if defined(__cplusplus) && (__cplusplus >= 201703L)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
TEST_CASE("TestNotNullConstructorTypeDeduction")
{ {
{ {
int i = 42; int i = 42;
@ -428,7 +421,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
helper(not_null{&i}); helper(not_null{&i});
helper_const(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(not_null{p});
helper_const(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; int* p1 = nullptr;
const not_null x{p1}; 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 int* p1 = nullptr;
const not_null x{p1}; const not_null x{p1};
}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); EXPECT_DEATH(workaround_macro(), ".*");
} }
{ {
int* p = nullptr; int* p = nullptr;
CHECK_THROWS_AS(helper(not_null{p}), fail_fast); EXPECT_DEATH(helper(not_null{p}), ".*");
CHECK_THROWS_AS(helper_const(not_null{p}), fail_fast); EXPECT_DEATH(helper_const(not_null{p}), ".*");
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
@ -475,7 +468,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
} }
#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) #endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
TEST_CASE("TestMakeNotNull") TEST(notnull_tests, TestMakeNotNull)
{ {
{ {
int i = 42; int i = 42;
@ -484,7 +477,7 @@ TEST_CASE("TestMakeNotNull")
helper(make_not_null(&i)); helper(make_not_null(&i));
helper_const(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(make_not_null(p));
helper_const(make_not_null(p)); helper_const(make_not_null(p));
CHECK(*x == 42); EXPECT_EQ(*x, 42);
} }
{ {
const auto workaround_macro = []() { const auto workaround_macro = []() {
int* p1 = nullptr; int* p1 = nullptr;
const auto x = make_not_null(p1); 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 auto workaround_macro = []() {
const int* p1 = nullptr; const int* p1 = nullptr;
const auto x = make_not_null(p1); 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; int* p = nullptr;
CHECK_THROWS_AS(helper(make_not_null(p)), fail_fast); EXPECT_DEATH(helper(make_not_null(p)), ".*");
CHECK_THROWS_AS(helper_const(make_not_null(p)), fail_fast); EXPECT_DEATH(helper_const(make_not_null(p)), ".*");
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {
CHECK_THROWS_AS(make_not_null(nullptr), fail_fast); EXPECT_DEATH(make_not_null(nullptr), ".*");
CHECK_THROWS_AS(helper(make_not_null(nullptr)), fail_fast); EXPECT_DEATH(helper(make_not_null(nullptr)), ".*");
CHECK_THROWS_AS(helper_const(make_not_null(nullptr)), fail_fast); EXPECT_DEATH(helper_const(make_not_null(nullptr)), ".*");
} }
#endif #endif
} }

View File

@ -21,7 +21,7 @@
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <gtest/gtest.h>
#include <gsl/pointers> // for owner #include <gsl/pointers> // for owner
@ -30,19 +30,16 @@ using namespace gsl;
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
void f(int* i) { *i += 1; } void f(int* i) { *i += 1; }
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute TEST(owner_tests, basic_test)
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute // TODO: false positive
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
TEST_CASE("basic_test")
{ {
owner<int*> p = new int(120); owner<int*> p = new int(120);
CHECK(*p == 120); EXPECT_EQ(*p, 120);
f(p); f(p);
CHECK(*p == 121); EXPECT_EQ(*p, 121);
delete p; delete p;
} }
TEST_CASE("check_pointer_constraint") TEST(owner_tests, check_pointer_constraint)
{ {
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
{ {

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
#pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4702) // unreachable code
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <gtest/gtest.h>
#include <gsl/pointers> // for not_null, operator<, operator<=, operator> #include <gsl/pointers> // for not_null, operator<, operator<=, operator>
namespace gsl namespace gsl
@ -35,19 +35,20 @@ using namespace gsl;
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper(not_null<int*> p) { return *p == 12; } bool helper(not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p) { return *p == 12; } bool helper_const(not_null<const int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool strict_helper(strict_not_null<int*> p) { return *p == 12; } bool strict_helper(strict_not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool strict_helper_const(strict_not_null<const int*> p) { return *p == 12; } bool strict_helper_const(strict_not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; } int* return_pointer() { return nullptr; }
const int* return_pointer_const() { return nullptr; } const int* return_pointer_const() { return nullptr; }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strict_notnull_tests, TestStrictNotNull)
TEST_CASE("TestStrictNotNull")
{ {
{ {
// raw ptr <-> strict_not_null // raw ptr <-> strict_not_null
@ -66,7 +67,7 @@ TEST_CASE("TestStrictNotNull")
helper(snn1); helper(snn1);
helper_const(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(snn1);
strict_helper_const(snn2); strict_helper_const(snn2);
CHECK(snn1 == snn2); EXPECT_EQ(snn1, snn2);
} }
{ {
@ -95,8 +96,8 @@ TEST_CASE("TestStrictNotNull")
helper(snn); helper(snn);
helper_const(snn); helper_const(snn);
CHECK(snn == nn1); EXPECT_EQ(snn, nn1);
CHECK(snn == nn2); EXPECT_EQ(snn, nn2);
} }
{ {
@ -111,16 +112,16 @@ TEST_CASE("TestStrictNotNull")
strict_helper(nn); strict_helper(nn);
strict_helper_const(nn); strict_helper_const(nn);
CHECK(snn1 == nn); EXPECT_EQ(snn1, nn);
CHECK(snn2 == nn); EXPECT_EQ(snn2, nn);
std::hash<strict_not_null<int*>> hash_snn; std::hash<strict_not_null<int*>> hash_snn;
std::hash<not_null<int*>> hash_nn; std::hash<not_null<int*>> hash_nn;
CHECK(hash_nn(snn1) == hash_nn(nn)); EXPECT_EQ(hash_nn(snn1), hash_nn(nn));
CHECK(hash_snn(snn1) == hash_nn(nn)); EXPECT_EQ(hash_snn(snn1), hash_nn(nn));
CHECK(hash_nn(snn1) == hash_nn(snn2)); EXPECT_EQ(hash_nn(snn1), hash_nn(snn2));
CHECK(hash_snn(snn1) == hash_snn(nn)); EXPECT_EQ(hash_snn(snn1), hash_snn(nn));
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
@ -132,8 +133,7 @@ TEST_CASE("TestStrictNotNull")
#if defined(__cplusplus) && (__cplusplus >= 201703L) #if defined(__cplusplus) && (__cplusplus >= 201703L)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
{ {
{ {
int i = 42; int i = 42;
@ -142,7 +142,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
helper(strict_not_null{&i}); helper(strict_not_null{&i});
helper_const(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(strict_not_null{p});
helper_const(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; int* p1 = nullptr;
const strict_not_null x{p1}; 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 int* p1 = nullptr;
const strict_not_null x{p1}; const strict_not_null x{p1};
}; };
CHECK_THROWS_AS(workaround_macro(), fail_fast); EXPECT_DEATH(workaround_macro(), ".*");
} }
{ {
int* p = nullptr; int* p = nullptr;
CHECK_THROWS_AS(helper(strict_not_null{p}), fail_fast); EXPECT_DEATH(helper(strict_not_null{p}), ".*");
CHECK_THROWS_AS(helper_const(strict_not_null{p}), fail_fast); EXPECT_DEATH(helper_const(strict_not_null{p}), ".*");
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS

View File

@ -27,7 +27,7 @@
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK... #include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte #include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast #include <gsl/gsl_util> // for narrow_cast
@ -54,9 +54,66 @@ struct BaseClass
struct DerivedClass : 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<int, dynamic_range> 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<int, 1> 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]);
} }
TEST_CASE("span_section_test") int idx = 0;
for (auto num : strided) {
EXPECT_TRUE(num == av[2 * idx + 1]);
idx++;
}
}
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<int, dynamic_range, dynamic_range, dynamic_range> 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]; int a[30][4][5];
@ -66,51 +123,52 @@ TEST_CASE("span_section_test")
(void) subsub; (void) subsub;
} }
TEST_CASE("span_section") TEST(strided_span_tests, span_section)
{ {
std::vector<int> data(5 * 10); std::vector<int> data(5 * 10);
std::iota(begin(data), end(data), 0); std::iota(begin(data), end(data), 0);
const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>()); const multi_span<int, 5, 10> av = as_multi_span(multi_span<int>{data}, dim<5>(), dim<10>());
const strided_span<int, 2> av_section_1 = av.section({1, 2}, {3, 4}); const strided_span<int, 2> av_section_1 = av.section({1, 2}, {3, 4});
CHECK(!av_section_1.empty()); EXPECT_TRUE(!av_section_1.empty());
CHECK((av_section_1[{0, 0}] == 12)); EXPECT_TRUE((av_section_1[{0, 0}] == 12));
CHECK((av_section_1[{0, 1}] == 13)); EXPECT_TRUE((av_section_1[{0, 1}] == 13));
CHECK((av_section_1[{1, 0}] == 22)); EXPECT_TRUE((av_section_1[{1, 0}] == 22));
CHECK((av_section_1[{2, 3}] == 35)); EXPECT_TRUE((av_section_1[{2, 3}] == 35));
const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2}); const strided_span<int, 2> av_section_2 = av_section_1.section({1, 2}, {2, 2});
CHECK(!av_section_2.empty()); EXPECT_TRUE(!av_section_2.empty());
CHECK((av_section_2[{0, 0}] == 24)); EXPECT_TRUE((av_section_2[{0, 0}] == 24));
CHECK((av_section_2[{0, 1}] == 25)); EXPECT_TRUE((av_section_2[{0, 1}] == 25));
CHECK((av_section_2[{1, 0}] == 34)); EXPECT_TRUE((av_section_2[{1, 0}] == 34));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_constructors)
TEST_CASE("strided_span_constructors")
{ {
// Check stride constructor // EXPECT_TRUE stride constructor
{ {
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; const int carr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T strided_span<int, 1> sav1{arr, {{9}, {1}}}; // T -> T
CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{9}); EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{9});
CHECK(sav1.bounds().stride() == 1); EXPECT_TRUE(sav1.bounds().stride() == 1);
CHECK((sav1[0] == 1 && sav1[8] == 9)); EXPECT_EQ(sav1[0], 1); EXPECT_EQ(sav1[8], 9);
strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T
CHECK(sav2.bounds().index_bounds() == multi_span_index<1>{4}); EXPECT_TRUE(sav2.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav2.bounds().strides() == multi_span_index<1>{2}); EXPECT_TRUE(sav2.bounds().strides() == multi_span_index<1>{2});
CHECK((sav2[0] == 1 && sav2[3] == 7)); EXPECT_EQ(sav2[0], 1); EXPECT_EQ(sav2[3], 7);
strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T
CHECK((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2})); EXPECT_TRUE((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2}));
CHECK((sav3.bounds().strides() == multi_span_index<2>{6, 2})); EXPECT_TRUE((sav3.bounds().strides() == multi_span_index<2>{6, 2}));
CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7)); 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}; int arr[] = {1, 2};
@ -119,9 +177,9 @@ TEST_CASE("strided_span_constructors")
const multi_span<int> src = arr; const multi_span<int> src = arr;
strided_span<int, 1> sav{src, {2, 1}}; strided_span<int, 1> sav{src, {2, 1}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[1] == 2); EXPECT_TRUE(sav[1] == 2);
#if defined(_MSC_VER) && _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
// strided_span<const int, 1> sav_c{ {src}, {2, 1} }; // strided_span<const int, 1> sav_c{ {src}, {2, 1} };
@ -131,9 +189,9 @@ TEST_CASE("strided_span_constructors")
strided_span<const int, 1> sav_c{multi_span<const int>{src}, strided_span<const int, 1> sav_c{multi_span<const int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_c.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2); EXPECT_TRUE(sav_c[1] == 2);
#if defined(_MSC_VER) && _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<volatile int, 1> sav_v{src, {2, 1}}; strided_span<volatile int, 1> sav_v{src, {2, 1}};
@ -141,9 +199,9 @@ TEST_CASE("strided_span_constructors")
strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src}, strided_span<volatile int, 1> sav_v{multi_span<volatile int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_v.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2); EXPECT_TRUE(sav_v[1] == 2);
#if defined(_MSC_VER) && _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
@ -151,9 +209,9 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); EXPECT_TRUE(sav_cv[1] == 2);
} }
// From const-qualified source // From const-qualified source
@ -161,9 +219,9 @@ TEST_CASE("strided_span_constructors")
const multi_span<const int> src{arr}; const multi_span<const int> src{arr};
strided_span<const int, 1> sav_c{src, {2, 1}}; strided_span<const int, 1> sav_c{src, {2, 1}};
CHECK(sav_c.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_c.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_c.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_c.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_c[1] == 2); EXPECT_TRUE(sav_c[1] == 2);
#if defined(_MSC_VER) && _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
@ -172,9 +230,9 @@ TEST_CASE("strided_span_constructors")
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); EXPECT_TRUE(sav_cv[1] == 2);
} }
// From volatile-qualified source // From volatile-qualified source
@ -182,9 +240,9 @@ TEST_CASE("strided_span_constructors")
const multi_span<volatile int> src{arr}; const multi_span<volatile int> src{arr};
strided_span<volatile int, 1> sav_v{src, {2, 1}}; strided_span<volatile int, 1> sav_v{src, {2, 1}};
CHECK(sav_v.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_v.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_v.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_v.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_v[1] == 2); EXPECT_TRUE(sav_v[1] == 2);
#if defined(_MSC_VER) && _MSC_VER > 1800 #if defined(_MSC_VER) && _MSC_VER > 1800
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
@ -192,9 +250,9 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src}, strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}}; strided_bounds<1>{2, 1}};
#endif #endif
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); EXPECT_TRUE(sav_cv[1] == 2);
} }
// From cv-qualified source // From cv-qualified source
@ -202,19 +260,19 @@ TEST_CASE("strided_span_constructors")
const multi_span<const volatile int> src{arr}; const multi_span<const volatile int> src{arr};
strided_span<const volatile int, 1> sav_cv{src, {2, 1}}; strided_span<const volatile int, 1> sav_cv{src, {2, 1}};
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2); EXPECT_TRUE(sav_cv[1] == 2);
} }
} }
// Check const-casting constructor // EXPECT_TRUE const-casting constructor
{ {
int arr[2] = {4, 5}; int arr[2] = {4, 5};
const multi_span<int, 2> av(arr, 2); const multi_span<int, 2> av(arr, 2);
multi_span<const int, 2> av2{av}; multi_span<const int, 2> av2{av};
CHECK(av2[1] == 5); EXPECT_TRUE(av2[1] == 5);
static_assert( static_assert(
std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value, std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value,
@ -222,34 +280,35 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr, {2, 1}}; const strided_span<int, 1> src{arr, {2, 1}};
strided_span<const int, 1> sav{src}; strided_span<const int, 1> sav{src};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().stride() == 1); EXPECT_TRUE(sav.bounds().stride() == 1);
CHECK(sav[1] == 5); EXPECT_TRUE(sav[1] == 5);
static_assert( static_assert(
std::is_convertible<const strided_span<int, 1>, strided_span<const int, 1>>::value, std::is_convertible<const strided_span<int, 1>, strided_span<const int, 1>>::value,
"ctor is not implicit!"); "ctor is not implicit!");
} }
// Check copy constructor // EXPECT_TRUE copy constructor
{ {
int arr1[2] = {3, 4}; int arr1[2] = {3, 4};
const strided_span<int, 1> src1{arr1, {2, 1}}; const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{src1}; strided_span<int, 1> sav1{src1};
CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav1.bounds().stride() == 1); EXPECT_TRUE(sav1.bounds().stride() == 1);
CHECK(sav1[0] == 3); EXPECT_TRUE(sav1[0] == 3);
int arr2[6] = {1, 2, 3, 4, 5, 6}; int arr2[6] = {1, 2, 3, 4, 5, 6};
const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}}; const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{src2}; strided_span<const int, 2> sav2{src2};
CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2})); EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1})); EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); 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 arr1[2] = {1, 2};
int arr2[6] = {3, 4, 5, 6, 7, 8}; int arr2[6] = {3, 4, 5, 6, 7, 8};
@ -257,38 +316,38 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr1, {{2}, {1}}}; const strided_span<int, 1> src{arr1, {{2}, {1}}};
strided_span<const int, 1> sav{arr2, {{3}, {2}}}; strided_span<const int, 1> sav{arr2, {{3}, {2}}};
strided_span<const int, 1>& sav_ref = (sav = src); strided_span<const int, 1>& sav_ref = (sav = src);
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav.bounds().strides() == multi_span_index<1>{1});
CHECK(sav[0] == 1); EXPECT_TRUE(sav[0] == 1);
CHECK(&sav_ref == &sav); EXPECT_TRUE(&sav_ref == &sav);
} }
// Check copy assignment operator // EXPECT_TRUE copy assignment operator
{ {
int arr1[2] = {3, 4}; int arr1[2] = {3, 4};
int arr1b[1] = {0}; int arr1b[1] = {0};
const strided_span<int, 1> src1{arr1, {2, 1}}; const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{arr1b, {1, 1}}; strided_span<int, 1> sav1{arr1b, {1, 1}};
strided_span<int, 1>& sav1_ref = (sav1 = src1); strided_span<int, 1>& sav1_ref = (sav1 = src1);
CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav1.bounds().strides() == multi_span_index<1>{1}); EXPECT_TRUE(sav1.bounds().strides() == multi_span_index<1>{1});
CHECK(sav1[0] == 3); EXPECT_TRUE(sav1[0] == 3);
CHECK(&sav1_ref == &sav1); EXPECT_TRUE(&sav1_ref == &sav1);
const int arr2[6] = {1, 2, 3, 4, 5, 6}; const int arr2[6] = {1, 2, 3, 4, 5, 6};
const int arr2b[1] = {0}; const int arr2b[1] = {0};
const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}}; const strided_span<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{arr2b, {{1, 1}, {1, 1}}}; strided_span<const int, 2> sav2{arr2b, {{1, 1}, {1, 1}}};
strided_span<const int, 2>& sav2_ref = (sav2 = src2); strided_span<const int, 2>& sav2_ref = (sav2 = src2);
CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2})); EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1})); EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5)); EXPECT_TRUE((sav2[{0, 0}] == 1));
CHECK(&sav2_ref == &sav2); EXPECT_TRUE((sav2[{2, 0}] == 5));
EXPECT_TRUE(&sav2_ref == &sav2);
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_slice)
TEST_CASE("strided_span_slice")
{ {
std::vector<int> data(5 * 10); std::vector<int> data(5 * 10);
std::iota(begin(data), end(data), 0); std::iota(begin(data), end(data), 0);
@ -303,19 +362,18 @@ TEST_CASE("strided_span_slice")
{{5, 10}, {10, 1}}}; {{5, 10}, {10, 1}}};
strided_span<int, 1> sav_sl = sav[2]; strided_span<int, 1> sav_sl = sav[2];
CHECK(sav_sl[0] == 20); EXPECT_TRUE(sav_sl[0] == 20);
CHECK(sav_sl[9] == 29); EXPECT_TRUE(sav_sl[9] == 29);
strided_span<const int, 1> csav_sl = sav[3]; strided_span<const int, 1> csav_sl = sav[3];
CHECK(csav_sl[0] == 30); EXPECT_TRUE(csav_sl[0] == 30);
CHECK(csav_sl[9] == 39); EXPECT_TRUE(csav_sl[9] == 39);
CHECK(sav[4][0] == 40); EXPECT_TRUE(sav[4][0] == 40);
CHECK(sav[4][9] == 49); EXPECT_TRUE(sav[4][9] == 49);
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_column_major)
TEST_CASE("strided_span_column_major")
{ {
// strided_span may be used to accommodate more peculiar // strided_span may be used to accommodate more peculiar
// use cases, such as column-major multidimensional array // use cases, such as column-major multidimensional array
@ -325,30 +383,29 @@ TEST_CASE("strided_span_column_major")
strided_span<int, 2> cm_sav{cm_array, {{5, 3}, {1, 5}}}; strided_span<int, 2> cm_sav{cm_array, {{5, 3}, {1, 5}}};
// Accessing elements // Accessing elements
CHECK((cm_sav[{0, 0}] == 1)); EXPECT_TRUE((cm_sav[{0, 0}] == 1));
CHECK((cm_sav[{0, 1}] == 2)); EXPECT_TRUE((cm_sav[{0, 1}] == 2));
CHECK((cm_sav[{1, 0}] == 4)); EXPECT_TRUE((cm_sav[{1, 0}] == 4));
CHECK((cm_sav[{4, 2}] == 15)); EXPECT_TRUE((cm_sav[{4, 2}] == 15));
// Slice // Slice
strided_span<int, 1> cm_sl = cm_sav[3]; strided_span<int, 1> cm_sl = cm_sav[3];
CHECK(cm_sl[0] == 10); EXPECT_TRUE(cm_sl[0] == 10);
CHECK(cm_sl[1] == 11); EXPECT_TRUE(cm_sl[1] == 11);
CHECK(cm_sl[2] == 12); EXPECT_TRUE(cm_sl[2] == 12);
// Section // Section
strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2}); strided_span<int, 2> cm_sec = cm_sav.section({2, 1}, {3, 2});
CHECK((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2})); EXPECT_TRUE((cm_sec.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((cm_sec[{0, 0}] == 8)); EXPECT_TRUE((cm_sec[{0, 0}] == 8));
CHECK((cm_sec[{0, 1}] == 9)); EXPECT_TRUE((cm_sec[{0, 1}] == 9));
CHECK((cm_sec[{1, 0}] == 11)); EXPECT_TRUE((cm_sec[{1, 0}] == 11));
CHECK((cm_sec[{2, 1}] == 15)); EXPECT_TRUE((cm_sec[{2, 1}] == 15));
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_bounds)
TEST_CASE("strided_span_bounds")
{ {
int arr[] = {0, 1, 2, 3}; int arr[] = {0, 1, 2, 3};
multi_span<int> av(arr); multi_span<int> av(arr);
@ -356,88 +413,88 @@ TEST_CASE("strided_span_bounds")
{ {
// incorrect sections // incorrect sections
CHECK_THROWS_AS(av.section(0, 0)[0], fail_fast); EXPECT_DEATH(av.section(0, 0)[0], ".*");
CHECK_THROWS_AS(av.section(1, 0)[0], fail_fast); EXPECT_DEATH(av.section(1, 0)[0], ".*");
CHECK_THROWS_AS(av.section(1, 1)[1], fail_fast); EXPECT_DEATH(av.section(1, 1)[1], ".*");
CHECK_THROWS_AS(av.section(2, 5), fail_fast); EXPECT_DEATH(av.section(2, 5), ".*");
CHECK_THROWS_AS(av.section(5, 2), fail_fast); EXPECT_DEATH(av.section(5, 2), ".*");
CHECK_THROWS_AS(av.section(5, 0), fail_fast); EXPECT_DEATH(av.section(5, 0), ".*");
CHECK_THROWS_AS(av.section(0, 5), fail_fast); EXPECT_DEATH(av.section(0, 5), ".*");
CHECK_THROWS_AS(av.section(5, 5), fail_fast); EXPECT_DEATH(av.section(5, 5), ".*");
} }
{ {
// zero stride // zero stride
strided_span<int, 1> sav{av, {{4}, {}}}; strided_span<int, 1> sav{av, {{4}, {}}};
CHECK(sav[0] == 0); EXPECT_TRUE(sav[0] == 0);
CHECK(sav[3] == 0); EXPECT_TRUE(sav[3] == 0);
CHECK_THROWS_AS(sav[4], fail_fast); EXPECT_DEATH(sav[4], ".*");
} }
{ {
// zero extent // zero extent
strided_span<int, 1> sav{av, {{}, {1}}}; strided_span<int, 1> sav{av, {{}, {1}}};
CHECK_THROWS_AS(sav[0], fail_fast); EXPECT_DEATH(sav[0], ".*");
} }
{ {
// zero extent and stride // zero extent and stride
strided_span<int, 1> sav{av, {{}, {}}}; strided_span<int, 1> sav{av, {{}, {}}};
CHECK_THROWS_AS(sav[0], fail_fast); EXPECT_DEATH(sav[0], ".*");
} }
{ {
// strided array ctor with matching strided bounds // strided array ctor with matching strided bounds
strided_span<int, 1> sav{arr, {4, 1}}; strided_span<int, 1> sav{arr, {4, 1}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{4}); EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav[3] == 3); EXPECT_TRUE(sav[3] == 3);
CHECK_THROWS_AS(sav[4], fail_fast); EXPECT_DEATH(sav[4], ".*");
} }
{ {
// strided array ctor with smaller strided bounds // strided array ctor with smaller strided bounds
strided_span<int, 1> sav{arr, {2, 1}}; strided_span<int, 1> sav{arr, {2, 1}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[1] == 1); EXPECT_TRUE(sav[1] == 1);
CHECK_THROWS_AS(sav[2], fail_fast); EXPECT_DEATH(sav[2], ".*");
} }
{ {
// strided array ctor with fitting irregular bounds // strided array ctor with fitting irregular bounds
strided_span<int, 1> sav{arr, {2, 3}}; strided_span<int, 1> sav{arr, {2, 3}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2}); EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[0] == 0); EXPECT_TRUE(sav[0] == 0);
CHECK(sav[1] == 3); EXPECT_TRUE(sav[1] == 3);
CHECK_THROWS_AS(sav[2], fail_fast); EXPECT_DEATH(sav[2], ".*");
} }
{ {
// bounds cross data boundaries - from static arrays // bounds cross data boundaries - from static arrays
CHECK_THROWS_AS((strided_span<int, 1>{arr, {3, 2}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{arr, {3, 2}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{arr, {3, 3}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{arr, {3, 3}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{arr, {4, 5}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{arr, {4, 5}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{arr, {5, 1}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{arr, {5, 1}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{arr, {5, 5}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{arr, {5, 5}}), ".*");
} }
{ {
// bounds cross data boundaries - from array view // bounds cross data boundaries - from array view
CHECK_THROWS_AS((strided_span<int, 1>{av, {3, 2}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av, {3, 2}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av, {3, 3}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av, {3, 3}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av, {4, 5}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av, {4, 5}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av, {5, 1}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av, {5, 1}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av, {5, 5}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av, {5, 5}}), ".*");
} }
{ {
// bounds cross data boundaries - from dynamic arrays // bounds cross data boundaries - from dynamic arrays
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {3, 2}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {3, 2}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {3, 3}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {3, 3}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {4, 5}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {4, 5}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {5, 1}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {5, 1}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {5, 5}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {5, 5}}), ".*");
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 2, {2, 2}}), fail_fast); EXPECT_DEATH((strided_span<int, 1>{av.data(), 2, {2, 2}}), ".*");
} }
#ifdef CONFIRM_COMPILATION_ERRORS #ifdef CONFIRM_COMPILATION_ERRORS
@ -464,8 +521,7 @@ TEST_CASE("strided_span_bounds")
#endif #endif
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_type_conversion)
TEST_CASE("strided_span_type_conversion")
{ {
int arr[] = {0, 1, 2, 3}; int arr[] = {0, 1, 2, 3};
multi_span<int> av(arr); multi_span<int> 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_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}};
strided_span<const byte, 2> sav2{bytes.data(), bytes.size(), bounds}; strided_span<const byte, 2> sav2{bytes.data(), bytes.size(), bounds};
strided_span<const int, 2> sav3 = sav2.as_strided_span<const int>(); strided_span<const int, 2> sav3 = sav2.as_strided_span<const int>();
CHECK(sav3[0][0] == 0); EXPECT_TRUE(sav3[0][0] == 0);
CHECK(sav3[1][0] == 2); EXPECT_TRUE(sav3[1][0] == 2);
CHECK_THROWS_AS(sav3[1][1], fail_fast); EXPECT_DEATH(sav3[1][1], ".*");
CHECK_THROWS_AS(sav3[0][1], fail_fast); EXPECT_DEATH(sav3[0][1], ".*");
} }
// retype strided array with regular strides - from multi_span // 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)); as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds}; strided_span<const byte, 2> sav2{bytes2, bounds};
strided_span<int, 2> sav3 = sav2.as_strided_span<int>(); strided_span<int, 2> sav3 = sav2.as_strided_span<int>();
CHECK(sav3[0][0] == 0); EXPECT_TRUE(sav3[0][0] == 0);
CHECK(sav3[1][0] == 2); EXPECT_TRUE(sav3[1][0] == 2);
CHECK_THROWS_AS(sav3[1][1], fail_fast); EXPECT_DEATH(sav3[1][1], ".*");
CHECK_THROWS_AS(sav3[0][1], fail_fast); EXPECT_DEATH(sav3[0][1], ".*");
} }
// retype strided array with not enough elements - last dimension of the array is too small // 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<const byte, 2, dynamic_range> bytes2 = multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds}; strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROWS_AS(sav2.as_strided_span<int>(), fail_fast); EXPECT_DEATH(sav2.as_strided_span<int>(), ".*");
} }
// retype strided array with not enough elements - strides are too small // retype strided array with not enough elements - strides are too small
@ -524,7 +580,7 @@ TEST_CASE("strided_span_type_conversion")
multi_span<const byte, 2, dynamic_range> bytes2 = multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds}; strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROWS_AS(sav2.as_strided_span<int>(), fail_fast); EXPECT_DEATH(sav2.as_strided_span<int>(), ".*");
} }
// retype strided array with not enough elements - last dimension does not divide by the new // 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<const byte, 2, dynamic_range> bytes2 = multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds}; strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROWS_AS(sav2.as_strided_span<int>(), fail_fast); EXPECT_DEATH(sav2.as_strided_span<int>(), ".*");
} }
// retype strided array with not enough elements - strides does not divide by the new // 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<const byte, 2, dynamic_range> bytes2 = multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2)); as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds}; strided_span<const byte, 2> sav2{bytes2, bounds};
CHECK_THROWS_AS(sav2.as_strided_span<int>(), fail_fast); EXPECT_DEATH(sav2.as_strided_span<int>(), ".*");
} }
// retype strided array with irregular strides - from raw data // retype strided array with irregular strides - from raw data
{ {
strided_bounds<1> bounds{bytes.size() / 2, 2}; strided_bounds<1> bounds{bytes.size() / 2, 2};
strided_span<const byte, 1> sav2{bytes.data(), bytes.size(), bounds}; strided_span<const byte, 1> sav2{bytes.data(), bytes.size(), bounds};
CHECK_THROWS_AS(sav2.as_strided_span<int>(), fail_fast); EXPECT_DEATH(sav2.as_strided_span<int>(), ".*");
} }
// retype strided array with irregular strides - from multi_span // retype strided array with irregular strides - from multi_span
{ {
strided_bounds<1> bounds{bytes.size() / 2, 2}; strided_bounds<1> bounds{bytes.size() / 2, 2};
strided_span<const byte, 1> sav2{bytes, bounds}; strided_span<const byte, 1> sav2{bytes, bounds};
CHECK_THROWS_AS(sav2.as_strided_span<int>(), fail_fast); EXPECT_DEATH(sav2.as_strided_span<int>(), ".*");
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, empty_strided_spans)
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("empty_strided_spans")
{ {
{ {
multi_span<int, 0> empty_av(nullptr); multi_span<int, 0> empty_av(nullptr);
strided_span<int, 1> empty_sav{empty_av, {0, 1}}; strided_span<int, 1> empty_sav{empty_av, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK(empty_sav.empty()); EXPECT_TRUE(empty_sav.empty());
CHECK_THROWS_AS(empty_sav[0], fail_fast); EXPECT_DEATH(empty_sav[0], ".*");
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); EXPECT_DEATH(empty_sav.begin()[0], ".*");
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); EXPECT_DEATH(empty_sav.cbegin()[0], ".*");
for (const auto& v : empty_sav) { for (const auto& v : empty_sav) {
(void) v; (void) v;
CHECK(false); EXPECT_TRUE(false);
} }
} }
{ {
strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}}; strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0}); EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_sav[0], fail_fast); EXPECT_DEATH(empty_sav[0], ".*");
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast); EXPECT_DEATH(empty_sav.begin()[0], ".*");
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast); EXPECT_DEATH(empty_sav.cbegin()[0], ".*");
for (const auto& v : empty_sav) { for (const auto& v : empty_sav) {
(void) v; (void) v;
CHECK(false); EXPECT_TRUE(false);
} }
} }
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_section_iteration)
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
void iterate_every_other_element(multi_span<int, dynamic_range> 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<int, 1> 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")
{ {
int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3}; 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 TEST(strided_span_tests, dynamic_strided_span_section_iteration)
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")
{ {
auto arr = new int[8]; auto arr = new int[8];
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -661,39 +682,7 @@ TEST_CASE("dynamic_strided_span_section_iteration")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_section_iteration_3d)
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // TODO: does not work
void iterate_second_slice(multi_span<int, dynamic_range, dynamic_range, dynamic_range> 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")
{ {
int arr[3][4][2]{}; int arr[3][4][2]{};
for (auto i = 0; i < 3; ++i) { 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 TEST(strided_span_tests, dynamic_strided_span_section_iteration_3d)
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")
{ {
const auto height = 12, width = 2; const auto height = 12, width = 2;
const auto size = height * width; const auto size = height * width;
@ -744,10 +728,7 @@ TEST_CASE("dynamic_strided_span_section_iteration_3d")
delete[] arr; delete[] arr;
} }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute TEST(strided_span_tests, strided_span_conversion)
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("strided_span_conversion")
{ {
// get an multi_span of 'c' values from the list of X's // 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 // convert to 4x12 array of bytes
auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2)); auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2));
CHECK(av.bounds().index_bounds()[0] == 4); EXPECT_TRUE(av.bounds().index_bounds()[0] == 4);
CHECK(av.bounds().index_bounds()[1] == 12); EXPECT_TRUE(av.bounds().index_bounds()[1] == 12);
// get the last 4 columns // 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], 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 // convert to array 4x1 array of integers
auto cs = section.as_strided_span<int>(); // { { arr[0].c }, {arr[1].c } , ... } auto cs = section.as_strided_span<int>(); // { { arr[0].c }, {arr[1].c } , ... }
CHECK(cs.bounds().index_bounds()[0] == 4); EXPECT_TRUE(cs.bounds().index_bounds()[0] == 4);
CHECK(cs.bounds().index_bounds()[1] == 1); EXPECT_TRUE(cs.bounds().index_bounds()[1] == 1);
// transpose to 1x4 array // transpose to 1x4 array
strided_bounds<2> reverse_bounds{ strided_bounds<2> reverse_bounds{
@ -791,12 +772,12 @@ TEST_CASE("strided_span_conversion")
// slice to get a one-dimensional array of c's // slice to get a one-dimensional array of c's
strided_span<int, 1> result = transposed[0]; strided_span<int, 1> result = transposed[0];
CHECK(result.bounds().index_bounds()[0] == 4); EXPECT_TRUE(result.bounds().index_bounds()[0] == 4);
CHECK_THROWS_AS(result.bounds().index_bounds()[1], fail_fast); EXPECT_DEATH(result.bounds().index_bounds()[1], ".*");
int i = 0; int i = 0;
for (auto& num : result) { for (auto& num : result) {
CHECK(num == arr[i].c); EXPECT_TRUE(num == arr[i].c);
i++; i++;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -24,4 +24,3 @@
#pragma warning(disable : ALL_CODE_ANALYSIS_WARNINGS) // from catch #pragma warning(disable : ALL_CODE_ANALYSIS_WARNINGS) // from catch
#endif // _MSC_VER #endif // _MSC_VER
#include <catch/catch.hpp>

View File

@ -21,7 +21,7 @@
#endif #endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_... #include <gtest/gtest.h>
#include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e... #include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e...
@ -33,101 +33,100 @@
using namespace gsl; 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<gsl::index, std::ptrdiff_t>::value, static_assert(std::is_same<gsl::index, std::ptrdiff_t>::value,
"gsl::index represents wrong arithmetic type"); "gsl::index represents wrong arithmetic type");
} }
void f(int& i) { i += 1; } TEST(utils_tests, finally_lambda)
TEST_CASE("finally_lambda")
{ {
int i = 0; int i = 0;
{ {
auto _ = finally([&]() { f(i); }); 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; int i = 0;
{ {
auto _1 = finally([&]() { f(i); }); auto _1 = finally([&]() { f(i); });
{ {
auto _2 = std::move(_1); auto _2 = std::move(_1);
CHECK(i == 0); EXPECT_EQ(i, 0);
} }
CHECK(i == 1); EXPECT_EQ(i, 1);
{ {
auto _2 = std::move(_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; int i = 0;
{ {
auto _ = finally(std::bind(&f, std::ref(i))); 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; TEST(utils_tests, finally_function_ptr)
void g() { j += 1; }
TEST_CASE("finally_function_ptr")
{ {
j = 0; j = 0;
{ {
auto _ = finally(&g); 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(utils_tests, narrow_cast)
TEST_CASE("narrow_cast")
{ {
int n = 120; int n = 120;
char c = narrow_cast<char>(n); char c = narrow_cast<char>(n);
CHECK(c == 120); EXPECT_EQ(c, 120);
n = 300; n = 300;
unsigned char uc = narrow_cast<unsigned char>(n); unsigned char uc = narrow_cast<unsigned char>(n);
CHECK(uc == 44); EXPECT_EQ(uc, 44);
} }
GSL_SUPPRESS(con.5) // NO-FORMAT: attribute TEST(utils_tests, narrow)
TEST_CASE("narrow")
{ {
int n = 120; int n = 120;
const char c = narrow<char>(n); const char c = narrow<char>(n);
CHECK(c == 120); EXPECT_EQ(c, 120);
n = 300; n = 300;
CHECK_THROWS_AS(narrow<char>(n), narrowing_error); EXPECT_DEATH(narrow<char>(n), ".*");
const auto int32_max = std::numeric_limits<int32_t>::max(); const auto int32_max = std::numeric_limits<int32_t>::max();
const auto int32_min = std::numeric_limits<int32_t>::min(); const auto int32_min = std::numeric_limits<int32_t>::min();
CHECK(narrow<uint32_t>(int32_t(0)) == 0); EXPECT_TRUE(narrow<uint32_t>(int32_t(0)) == 0);
CHECK(narrow<uint32_t>(int32_t(1)) == 1); EXPECT_TRUE(narrow<uint32_t>(int32_t(1)) == 1);
CHECK(narrow<uint32_t>(int32_max) == static_cast<uint32_t>(int32_max)); EXPECT_TRUE(narrow<uint32_t>(int32_max) == static_cast<uint32_t>(int32_max));
CHECK_THROWS_AS(narrow<uint32_t>(int32_t(-1)), narrowing_error); EXPECT_DEATH(narrow<uint32_t>(int32_t(-1)), ".*");
CHECK_THROWS_AS(narrow<uint32_t>(int32_min), narrowing_error); EXPECT_DEATH(narrow<uint32_t>(int32_min), ".*");
n = -42; n = -42;
CHECK_THROWS_AS(narrow<unsigned>(n), narrowing_error); EXPECT_DEATH(narrow<unsigned>(n), ".*");
#if GSL_CONSTEXPR_NARROW #if GSL_CONSTEXPR_NARROW
static_assert(narrow<char>(120) == 120, "Fix GSL_CONSTEXPR_NARROW"); static_assert(narrow<char>(120) == 120, "Fix GSL_CONSTEXPR_NARROW");
#endif #endif
} }