Merge pull request #831 from JordanMaples/dev/jomaples/gtest

Migrate from Catch to GoogleTest & always terminate on contract violation
This commit is contained in:
Jordan Maples [MSFT] 2020-01-07 15:41:25 -08:00 committed by GitHub
commit 7786da91c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 3999 additions and 3692 deletions

View File

@ -18,7 +18,7 @@ other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more inform
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
# Usage of Third Party Libraries
This project makes use of the [Catch](https://github.com/philsquared/catch) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Catch.
This project makes use of the [Google Test](https://github.com/google/gooletest) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Google Test.
# Quick Start
## Supported Platforms

View File

@ -2,38 +2,40 @@
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize
GSL: Guidelines Support Library incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.
GSL: Guidelines Support Library incorporates third party material from the projects listed below.
-------------------------------------------------------------------------------
Software: Google Test
Owner: Google Inc.
Source URL: github.com/google/googletest
License: BSD 3 - Clause
Text:
Copyright 2008, Google Inc.
All rights reserved.
1. Catch (https://github.com/philsquared/Catch)
%% Catch NOTICES, INFORMATION, AND LICENSE BEGIN HERE
=========================================
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=========================================
END OF Catch NOTICES, INFORMATION, AND LICENSE
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------

View File

@ -18,7 +18,6 @@
#define GSL_CONTRACTS_H
#include <exception>
#include <stdexcept> // for logic_error
//
// make suppress attributes parse for some compilers
@ -50,19 +49,6 @@
#endif
//
// There are three configuration options for this GSL implementation's behavior
// when pre/post conditions on the GSL types are violated:
//
// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default)
// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
//
#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \
defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
#endif
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
@ -94,10 +80,6 @@
namespace gsl
{
struct fail_fast : public std::logic_error
{
explicit fail_fast(char const* const message) : std::logic_error(message) {}
};
namespace details
{
@ -128,45 +110,21 @@ namespace details
#endif
}
#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
template <typename Exception>
[[deprecated("GSL no longer supports throwing for contract violations. Use gsl::details::terminate() instead.")]]
[[noreturn]] void throw_exception(Exception&&) noexcept
{
gsl::details::terminate();
}
#else
template <typename Exception>
[[noreturn]] void throw_exception(Exception&& exception)
{
throw std::forward<Exception>(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<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) \
(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 Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)

View File

@ -21,7 +21,6 @@
#include <array>
#include <cstddef> // for ptrdiff_t, size_t
#include <exception> // for exception
#include <initializer_list> // for initializer_list
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
@ -97,10 +96,6 @@ constexpr T narrow_cast(U&& u) noexcept
return static_cast<T>(std::forward<U>(u));
}
struct narrowing_error : public std::exception
{
};
namespace details
{
template <class T, class U>
@ -120,9 +115,9 @@ constexpr
T narrow(U u) noexcept(false)
{
T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error());
if (static_cast<U>(t) != u) gsl::details::terminate();
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
gsl::details::throw_exception(narrowing_error());
gsl::details::terminate();
return t;
}

View File

@ -5,27 +5,33 @@ project(GSLTests CXX)
# will make visual studio generated project group files
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CATCH_CMAKE_ARGS
"-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/external"
"-DNO_SELFTEST=true"
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
)
if(GIT_FOUND)
# add catch
ExternalProject_Add(
catch
PREFIX ${CMAKE_BINARY_DIR}/catch
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v2.0.1
CMAKE_ARGS ${CATCH_CMAKE_ARGS}
LOG_DOWNLOAD 1
UPDATE_DISCONNECTED 1
)
else()
# assume catch is installed in a system directory
add_custom_target(catch)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download
)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_subdirectory(
${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL
)
if (MSVC AND (GSL_CXX_STANDARD EQUAL 17))
set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-)
endif()
@ -78,37 +84,23 @@ else()
)
endif(MSVC)
# for tests to find the catch header
target_include_directories(gsl_tests_config INTERFACE
${CMAKE_BINARY_DIR}/external/include
# for tests to find the gtest header
target_include_directories(gsl_tests_config SYSTEM INTERFACE
googletest/googletest/include
)
# set definitions for tests
target_compile_definitions(gsl_tests_config INTERFACE
GSL_THROW_ON_CONTRACT_VIOLATION
)
# create the main executable for each test. this reduces the compile time
# of each test by pre-compiling catch.
add_library(test_catch STATIC test.cpp)
target_link_libraries(test_catch
GSL
gsl_tests_config
)
add_dependencies(test_catch catch)
set_property(TARGET test_catch PROPERTY FOLDER "GSL_tests")
set_property(TARGET PROPERTY FOLDER "GSL_tests")
function(add_gsl_test name)
add_executable(${name} ${name}.cpp)
target_link_libraries(${name}
GSL
test_catch
gsl_tests_config
gtest_main
)
add_dependencies(${name} catch)
add_test(
${name}
${name}
${name}
${name}
)
# group all tests under GSL_tests
set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests")
@ -141,11 +133,9 @@ endforeach(flag_var)
# please try to keep entries ordered =)
add_library(gsl_tests_config_noexcept INTERFACE)
if(MSVC) # MSVC or simulating MSVC
target_compile_definitions(gsl_tests_config_noexcept INTERFACE
_HAS_EXCEPTIONS=0
)
target_compile_options(gsl_tests_config_noexcept INTERFACE
${GSL_CPLUSPLUS_OPT}
/EHsc
/W4
/WX
$<$<CXX_COMPILER_ID:MSVC>:
@ -184,16 +174,12 @@ else()
)
endif(MSVC)
# set definitions for tests
target_compile_definitions(gsl_tests_config_noexcept INTERFACE
GSL_TERMINATE_ON_CONTRACT_VIOLATION
)
function(add_gsl_test_noexcept name)
add_executable(${name} ${name}.cpp)
target_link_libraries(${name}
GSL
gsl_tests_config_noexcept
gtest_main
)
add_test(
${name}

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,24 +20,38 @@
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHE...
#if __clang__ || __GNUC__
// disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/gsl_algorithm> // for copy
#include <gsl/span> // for span
#include <array> // for array
#include <cstddef> // for size_t
namespace gsl {
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
namespace gsl
{
struct fail_fast;
} // namespace gsl
} // namespace gsl
using namespace std;
using namespace gsl;
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("same_type")
TEST(algorithm_tests, same_type)
{
// dynamic source and destination span
{
@ -50,9 +64,10 @@ TEST_CASE("same_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
@ -67,9 +82,10 @@ TEST_CASE("same_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
@ -84,9 +100,10 @@ TEST_CASE("same_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
@ -101,17 +118,15 @@ TEST_CASE("same_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
}
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("compatible_type")
TEST(algorithm_tests, compatible_type)
{
// dynamic source and destination span
{
@ -124,9 +139,10 @@ TEST_CASE("compatible_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
@ -141,9 +157,10 @@ TEST_CASE("compatible_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
@ -158,9 +175,10 @@ TEST_CASE("compatible_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
@ -175,15 +193,16 @@ TEST_CASE("compatible_type")
copy(src_span, dst_span);
copy(src_span, dst_span.subspan(src_span.size()));
for (std::size_t i = 0; i < src.size(); ++i) {
CHECK(dst[i] == src[i]);
CHECK(dst[i + src.size()] == src[i]);
for (std::size_t i = 0; i < src.size(); ++i)
{
EXPECT_TRUE(dst[i] == src[i]);
EXPECT_TRUE(dst[i + src.size()] == src[i]);
}
}
}
#ifdef CONFIRM_COMPILATION_ERRORS
TEST_CASE("incompatible_type")
TEST(algorithm_tests, incompatible_type)
{
std::array<int, 4> src{1, 2, 3, 4};
std::array<int*, 12> dst{};
@ -201,8 +220,13 @@ TEST_CASE("incompatible_type")
}
#endif
TEST_CASE("small_destination_span")
TEST(algorithm_tests, small_destination_span)
{
std::set_terminate([] {
std::cerr << "Expected Death. small_destination_span";
std::abort();
});
std::array<int, 12> src{1, 2, 3, 4};
std::array<int, 4> dst{};
@ -211,11 +235,15 @@ TEST_CASE("small_destination_span")
const span<int> dst_span_dyn(dst);
const span<int, 4> dst_span_static(dst);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_dyn), fail_fast);
CHECK_THROWS_AS(copy(src_span_dyn, dst_span_static), fail_fast);
CHECK_THROWS_AS(copy(src_span_static, dst_span_dyn), fail_fast);
EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), deathstring);
EXPECT_DEATH(copy(src_span_dyn, dst_span_static), deathstring);
EXPECT_DEATH(copy(src_span_static, dst_span_dyn), deathstring);
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
#endif
}
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

View File

@ -20,33 +20,64 @@
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/gsl_assert> // for fail_fast (ptr only), Ensures, Expects
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
int f(int i)
{
Expects(i > 0 && i < 10);
return i;
}
TEST_CASE("expects")
{
CHECK(f(2) == 2);
CHECK_THROWS_AS(f(10), fail_fast);
}
int g(int i)
{
i++;
Ensures(i > 0 && i < 10);
return i;
}
} // namespace
TEST_CASE("ensures")
TEST(assertion_tests, expects)
{
CHECK(g(2) == 3);
CHECK_THROWS_AS(g(9), fail_fast);
std::set_terminate([] {
std::cerr << "Expected Death. expects";
std::abort();
});
EXPECT_TRUE(f(2) == 2);
EXPECT_DEATH(f(10), deathstring);
}
TEST(assertion_tests, ensures)
{
std::set_terminate([] {
std::cerr << "Expected Death. ensures";
std::abort();
});
EXPECT_TRUE(g(2) == 3);
EXPECT_DEATH(g(9), deathstring);
}
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

View File

@ -20,7 +20,19 @@
#pragma warning(disable : 26440 26426) // from catch
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK_THROW...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for at
@ -29,88 +41,95 @@
#include <initializer_list> // for initializer_list
#include <vector> // for vector
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
namespace gsl {
struct fail_fast;
} // namespace gsl
using gsl::fail_fast;
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("static_array")
TEST(at_tests, static_array)
{
int a[4] = {1, 2, 3, 4};
const int(&c_a)[4] = a;
for (int i = 0; i < 4; ++i) {
CHECK(&gsl::at(a, i) == &a[i]);
CHECK(&gsl::at(c_a, i) == &a[i]);
EXPECT_TRUE(&gsl::at(a, i) == &a[i]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]);
}
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast);
CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
std::set_terminate([] {
std::cerr << "Expected Death. static_array";
std::abort();
});
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
}
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("std_array")
TEST(at_tests, std_array)
{
std::array<int, 4> a = {1, 2, 3, 4};
const std::array<int, 4>& c_a = a;
for (int i = 0; i < 4; ++i) {
CHECK(&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_TRUE(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
}
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast);
CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
std::set_terminate([] {
std::cerr << "Expected Death. std_array";
std::abort();
});
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
}
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("StdVector")
TEST(at_tests, std_vector)
{
std::vector<int> a = {1, 2, 3, 4};
const std::vector<int>& c_a = a;
for (int i = 0; i < 4; ++i) {
CHECK(&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_TRUE(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
}
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast);
CHECK_THROWS_AS(gsl::at(c_a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(c_a, 4), fail_fast);
std::set_terminate([] {
std::cerr << "Expected Death. std_vector";
std::abort();
});
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
}
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("InitializerList")
TEST(at_tests, InitializerList)
{
const std::initializer_list<int> a = {1, 2, 3, 4};
for (int i = 0; i < 4; ++i) {
CHECK(gsl::at(a, i) == i + 1);
CHECK(gsl::at({1, 2, 3, 4}, i) == i + 1);
EXPECT_TRUE(gsl::at(a, i) == i + 1);
EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1);
}
CHECK_THROWS_AS(gsl::at(a, -1), fail_fast);
CHECK_THROWS_AS(gsl::at(a, 4), fail_fast);
CHECK_THROWS_AS(gsl::at({1, 2, 3, 4}, -1), fail_fast);
CHECK_THROWS_AS(gsl::at({1, 2, 3, 4}, 4), fail_fast);
std::set_terminate([] {
std::cerr << "Expected Death. InitializerList";
std::abort();
});
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), deathstring);
EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), deathstring);
}
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
static constexpr bool test_constexpr()
{
int a1[4] = {1, 2, 3, 4};
@ -133,3 +152,6 @@ static constexpr bool test_constexpr()
static_assert(test_constexpr(), "FAIL");
#endif
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

View File

@ -24,18 +24,23 @@
#if __clang__ || __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, TEST_CASE
//disable warnings from gtest
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/multi_span> // for static_bounds, static_bounds_dynamic_range_t
#include <cstddef> // for ptrdiff_t, size_t
namespace gsl {
struct fail_fast;
} // namespace gsl
using namespace std;
using namespace gsl;
@ -44,8 +49,7 @@ namespace
void use(std::ptrdiff_t&) {}
}
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
TEST_CASE("basic_bounds")
TEST(bounds_tests, basic_bounds)
{
for (auto point : static_bounds<dynamic_range, 3, 4>{2}) {
for (decltype(point)::size_type j = 0;
@ -57,9 +61,7 @@ TEST_CASE("basic_bounds")
}
}
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_basic")
TEST(bounds_tests, bounds_basic)
{
static_bounds<3, 4, 5> b;
const auto a = b.slice();
@ -68,9 +70,7 @@ TEST_CASE("bounds_basic")
x.slice().slice();
}
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("arrayview_iterator")
TEST(bounds_tests, arrayview_iterator)
{
static_bounds<4, dynamic_range, 2> bounds{3};
@ -88,8 +88,7 @@ TEST_CASE("arrayview_iterator")
#endif
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("bounds_convertible")
TEST(bounds_tests, bounds_convertible)
{
static_bounds<7, 4, 2> b1;
static_bounds<7, dynamic_range, 2> b2 = b1;
@ -102,18 +101,21 @@ TEST_CASE("bounds_convertible")
static_bounds<7, 4, 2> b4 = b3;
(void) b4;
static_bounds<dynamic_range> b11;
static_bounds<dynamic_range> b5;
static_bounds<34> b6;
std::set_terminate([] {
std::cerr << "Expected Death. bounds_convertible";
std::abort();
});
b5 = static_bounds<20>();
CHECK_THROWS_AS(b6 = b5, fail_fast);
EXPECT_DEATH(b6 = b5, ".*");
b5 = static_bounds<34>();
b6 = b5;
CHECK(b5 == b6);
CHECK(b5.size() == b6.size());
EXPECT_TRUE(b5 == b6);
EXPECT_TRUE(b5.size() == b6.size());
}
#ifdef CONFIRM_COMPILATION_ERRORS
@ -122,4 +124,4 @@ copy(src_span_static, dst_span_static);
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif
#endif // __clang__ || __GNUC__

View File

@ -17,10 +17,22 @@
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#pragma warning(disable : 26440 26426) // from catch
#endif
#pragma warning(disable : 26440 26426)
#endif // _MSC_VER
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for to_byte, to_integer, byte, operator&, ope...
@ -29,104 +41,103 @@ using namespace gsl;
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;
b = to_byte<5>();
return i;
}
GSL_SUPPRESS(type.1)
TEST_CASE("aliasing")
TEST(byte_tests, construction)
{
{
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};
const int res = modify_both(reinterpret_cast<byte&>(i), i);
CHECK(res == i);
EXPECT_TRUE(res == i);
}
}
@ -134,3 +145,7 @@ TEST_CASE("aliasing")
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);
#endif
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,19 @@
#pragma warning(disable : 4702) // unreachable code
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
@ -34,13 +46,13 @@
#include <string> // for basic_string, operator==, string, operator<<
#include <typeinfo> // for type_info
namespace gsl
{
struct fail_fast;
} // namespace gsl
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
} //namespace
struct MyBase
{
};
@ -133,10 +145,8 @@ GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; }
const int* return_pointer_const() { return nullptr; }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullConstructors")
TEST(notnull_tests, TestNotNullConstructors)
{
{
#ifdef CONFIRM_COMPILATION_ERRORS
@ -153,18 +163,22 @@ TEST_CASE("TestNotNullConstructors")
#endif
}
std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullConstructors";
std::abort();
});
{
// from shared pointer
int i = 12;
auto rp = RefCounted<int>(&i);
not_null<int*> p(rp);
CHECK(p.get() == &i);
EXPECT_TRUE(p.get() == &i);
not_null<std::shared_ptr<int>> x(
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
int* pi = nullptr;
CHECK_THROWS_AS(not_null<decltype(pi)>(pi), fail_fast);
EXPECT_DEATH((not_null<decltype(pi)>(pi)), deathstring);
}
{
@ -175,7 +189,7 @@ TEST_CASE("TestNotNullConstructors")
helper(&t);
helper_const(&t);
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -191,7 +205,7 @@ TEST_CASE("TestNotNullConstructors")
helper(x);
helper_const(x);
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -205,7 +219,7 @@ TEST_CASE("TestNotNullConstructors")
helper_const(cp);
helper_const(x);
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -215,19 +229,18 @@ TEST_CASE("TestNotNullConstructors")
auto x = not_null<const int*>{cp};
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
// from returned pointer
CHECK_THROWS_AS(helper(return_pointer()), fail_fast);
CHECK_THROWS_AS(helper_const(return_pointer()), fail_fast);
EXPECT_DEATH(helper(return_pointer()), deathstring);
EXPECT_DEATH(helper_const(return_pointer()), deathstring);
}
}
template <typename T>
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
void ostream_helper(T v)
{
not_null<T*> p(&v);
@ -236,18 +249,18 @@ void ostream_helper(T v)
std::ostringstream ref;
os << static_cast<void*>(p);
ref << static_cast<void*>(&v);
CHECK(os.str() == ref.str());
EXPECT_TRUE(os.str() == ref.str());
}
{
std::ostringstream os;
std::ostringstream ref;
os << *p;
ref << v;
CHECK(os.str() == ref.str());
EXPECT_TRUE(os.str() == ref.str());
}
}
TEST_CASE("TestNotNullostream")
TEST(notnull_tests, TestNotNullostream)
{
ostream_helper<int>(17);
ostream_helper<float>(21.5f);
@ -258,9 +271,7 @@ TEST_CASE("TestNotNullostream")
ostream_helper<std::string>("string");
}
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCasting")
TEST(notnull_tests, TestNotNullCasting)
{
MyBase base;
MyDerived derived;
@ -270,7 +281,7 @@ TEST_CASE("TestNotNullCasting")
not_null<MyDerived*> p{&derived};
not_null<MyBase*> q(&base);
q = p; // allowed with heterogeneous copy ctor
CHECK(q == p);
EXPECT_TRUE(q == p);
#ifdef CONFIRM_COMPILATION_ERRORS
q = u; // no viable conversion possible between MyBase* and Unrelated*
@ -280,20 +291,25 @@ TEST_CASE("TestNotNullCasting")
not_null<Unrelated*> s = reinterpret_cast<Unrelated*>(p);
#endif
not_null<Unrelated*> t(reinterpret_cast<Unrelated*>(p.get()));
CHECK(reinterpret_cast<void*>(p.get()) == reinterpret_cast<void*>(t.get()));
EXPECT_TRUE(reinterpret_cast<void*>(p.get()) == reinterpret_cast<void*>(t.get()));
}
TEST_CASE("TestNotNullAssignment")
TEST(notnull_tests, TestNotNullAssignment)
{
std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullAssignmentd";
std::abort();
});
int i = 12;
not_null<int*> p(&i);
CHECK(helper(p));
EXPECT_TRUE(helper(p));
int* q = nullptr;
CHECK_THROWS_AS(p = not_null<int*>(q), fail_fast);
EXPECT_DEATH(p = not_null<int*>(q), deathstring);
}
TEST_CASE("TestNotNullRawPointerComparison")
TEST(notnull_tests, TestNotNullRawPointerComparison)
{
int ints[2] = {42, 43};
int* p1 = &ints[0];
@ -302,34 +318,33 @@ TEST_CASE("TestNotNullRawPointerComparison")
using NotNull1 = not_null<decltype(p1)>;
using NotNull2 = not_null<decltype(p2)>;
CHECK((NotNull1(p1) == NotNull1(p1)) == true);
CHECK((NotNull1(p1) == NotNull2(p2)) == false);
EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == true);
EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == false);
CHECK((NotNull1(p1) != NotNull1(p1)) == false);
CHECK((NotNull1(p1) != NotNull2(p2)) == true);
EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == false);
EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == true);
CHECK((NotNull1(p1) < NotNull1(p1)) == false);
CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == false);
EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
CHECK((NotNull1(p1) > NotNull1(p1)) == false);
CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == false);
EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
CHECK((NotNull1(p1) <= NotNull1(p1)) == true);
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == true);
EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullDereferenceOperator")
TEST(notnull_tests, TestNotNullDereferenceOperator)
{
{
auto sp1 = std::make_shared<NonCopyableNonMovable>();
using NotNullSp1 = not_null<decltype(sp1)>;
CHECK(typeid(*sp1) == typeid(*NotNullSp1(sp1)));
CHECK(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1));
EXPECT_TRUE(typeid(*sp1) == typeid(*NotNullSp1(sp1)));
EXPECT_TRUE(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1));
}
{
@ -337,22 +352,22 @@ TEST_CASE("TestNotNullDereferenceOperator")
CustomPtr<int> p1(&ints[0]);
using NotNull1 = not_null<decltype(p1)>;
CHECK(typeid(*NotNull1(p1)) == typeid(*p1));
CHECK(*NotNull1(p1) == 42);
EXPECT_TRUE(typeid(*NotNull1(p1)) == typeid(*p1));
EXPECT_TRUE(*NotNull1(p1) == 42);
*NotNull1(p1) = 43;
CHECK(ints[0] == 43);
EXPECT_TRUE(ints[0] == 43);
}
{
int v = 42;
gsl::not_null<int*> p(&v);
CHECK(typeid(*p) == typeid(*(&v)));
EXPECT_TRUE(typeid(*p) == typeid(*(&v)));
*p = 43;
CHECK(v == 43);
EXPECT_TRUE(v == 43);
}
}
TEST_CASE("TestNotNullSharedPtrComparison")
TEST(notnull_tests, TestNotNullSharedPtrComparison)
{
auto sp1 = std::make_shared<int>(42);
auto sp2 = std::make_shared<const int>(43);
@ -360,31 +375,30 @@ TEST_CASE("TestNotNullSharedPtrComparison")
using NotNullSp1 = not_null<decltype(sp1)>;
using NotNullSp2 = not_null<decltype(sp2)>;
CHECK((NotNullSp1(sp1) == NotNullSp1(sp1)) == true);
CHECK((NotNullSp1(sp1) == NotNullSp2(sp2)) == false);
EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp1(sp1)) == true);
EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp2(sp2)) == false);
CHECK((NotNullSp1(sp1) != NotNullSp1(sp1)) == false);
CHECK((NotNullSp1(sp1) != NotNullSp2(sp2)) == true);
EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp1(sp1)) == false);
EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp2(sp2)) == true);
CHECK((NotNullSp1(sp1) < NotNullSp1(sp1)) == false);
CHECK((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2));
CHECK((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1));
EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp1(sp1)) == false);
EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2));
EXPECT_TRUE((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1));
CHECK((NotNullSp1(sp1) > NotNullSp1(sp1)) == false);
CHECK((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2));
CHECK((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1));
EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp1(sp1)) == false);
EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2));
EXPECT_TRUE((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1));
CHECK((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true);
CHECK((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2));
CHECK((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1));
EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true);
EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2));
EXPECT_TRUE((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1));
CHECK((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true);
CHECK((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2));
CHECK((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1));
EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true);
EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2));
EXPECT_TRUE((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1));
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullCustomPtrComparison")
TEST(notnull_tests, TestNotNullCustomPtrComparison)
{
int ints[2] = {42, 43};
CustomPtr<int> p1(&ints[0]);
@ -393,33 +407,32 @@ TEST_CASE("TestNotNullCustomPtrComparison")
using NotNull1 = not_null<decltype(p1)>;
using NotNull2 = not_null<decltype(p2)>;
CHECK((NotNull1(p1) == NotNull1(p1)) == "true");
CHECK((NotNull1(p1) == NotNull2(p2)) == "false");
EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == "true");
EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == "false");
CHECK((NotNull1(p1) != NotNull1(p1)) == "false");
CHECK((NotNull1(p1) != NotNull2(p2)) == "true");
EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == "false");
EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == "true");
CHECK((NotNull1(p1) < NotNull1(p1)) == "false");
CHECK((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
CHECK((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == "false");
EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2));
EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1));
CHECK((NotNull1(p1) > NotNull1(p1)) == "false");
CHECK((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
CHECK((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == "false");
EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2));
EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1));
CHECK((NotNull1(p1) <= NotNull1(p1)) == "true");
CHECK((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
CHECK((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == "true");
EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2));
EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1));
CHECK((NotNull1(p1) >= NotNull1(p1)) == "true");
CHECK((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2));
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
EXPECT_TRUE((NotNull1(p1) >= NotNull1(p1)) == "true");
EXPECT_TRUE((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2));
EXPECT_TRUE((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestNotNullConstructorTypeDeduction")
TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
{
{
int i = 42;
@ -428,7 +441,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
helper(not_null{&i});
helper_const(not_null{&i});
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -439,15 +452,20 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
helper(not_null{p});
helper_const(not_null{p});
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullConstructorTypeDeduction";
std::abort();
});
{
auto workaround_macro = []() {
int* p1 = nullptr;
const not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
EXPECT_DEATH(workaround_macro(), deathstring);
}
{
@ -455,14 +473,14 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
const int* p1 = nullptr;
const not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
EXPECT_DEATH(workaround_macro(), deathstring);
}
{
int* p = nullptr;
CHECK_THROWS_AS(helper(not_null{p}), fail_fast);
CHECK_THROWS_AS(helper_const(not_null{p}), fail_fast);
EXPECT_DEATH(helper(not_null{p}), deathstring);
EXPECT_DEATH(helper_const(not_null{p}), deathstring);
}
#ifdef CONFIRM_COMPILATION_ERRORS
@ -475,7 +493,7 @@ TEST_CASE("TestNotNullConstructorTypeDeduction")
}
#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)
TEST_CASE("TestMakeNotNull")
TEST(notnull_tests, TestMakeNotNull)
{
{
int i = 42;
@ -484,7 +502,7 @@ TEST_CASE("TestMakeNotNull")
helper(make_not_null(&i));
helper_const(make_not_null(&i));
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -495,42 +513,51 @@ TEST_CASE("TestMakeNotNull")
helper(make_not_null(p));
helper_const(make_not_null(p));
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
std::set_terminate([] {
std::cerr << "Expected Death. TestMakeNotNull";
std::abort();
});
{
const auto workaround_macro = []() {
int* p1 = nullptr;
const auto x = make_not_null(p1);
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
EXPECT_DEATH(workaround_macro(), deathstring);
}
{
const auto workaround_macro = []() {
const int* p1 = nullptr;
const auto x = make_not_null(p1);
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
EXPECT_DEATH(workaround_macro(), deathstring);
}
{
int* p = nullptr;
CHECK_THROWS_AS(helper(make_not_null(p)), fail_fast);
CHECK_THROWS_AS(helper_const(make_not_null(p)), fail_fast);
EXPECT_DEATH(helper(make_not_null(p)), deathstring);
EXPECT_DEATH(helper_const(make_not_null(p)), deathstring);
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
CHECK_THROWS_AS(make_not_null(nullptr), fail_fast);
CHECK_THROWS_AS(helper(make_not_null(nullptr)), fail_fast);
CHECK_THROWS_AS(helper_const(make_not_null(nullptr)), fail_fast);
EXPECT_DEATH(make_not_null(nullptr), deathstring);
EXPECT_DEATH(helper(make_not_null(nullptr)), deathstring);
EXPECT_DEATH(helper_const(make_not_null(nullptr)), deathstring);
}
#endif
}
static_assert(std::is_nothrow_move_constructible<not_null<void*>>::value,
"not_null must be no-throw move constructible");
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

View File

@ -21,7 +21,19 @@
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/pointers> // for owner
@ -30,19 +42,16 @@ using namespace gsl;
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
void f(int* i) { *i += 1; }
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute // TODO: false positive
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
TEST_CASE("basic_test")
TEST(owner_tests, basic_test)
{
owner<int*> p = new int(120);
CHECK(*p == 120);
EXPECT_TRUE(*p == 120);
f(p);
CHECK(*p == 121);
EXPECT_TRUE(*p == 121);
delete p;
}
TEST_CASE("check_pointer_constraint")
TEST(owner_tests, check_pointer_constraint)
{
#ifdef CONFIRM_COMPILATION_ERRORS
{
@ -51,3 +60,7 @@ TEST_CASE("check_pointer_constraint")
}
#endif
}
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,19 @@
#pragma warning(disable : 4702) // unreachable code
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
namespace gsl
@ -35,19 +47,20 @@ using namespace gsl;
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper(not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool helper_const(not_null<const int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool strict_helper(strict_not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
bool strict_helper_const(strict_not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; }
const int* return_pointer_const() { return nullptr; }
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestStrictNotNull")
TEST(strict_notnull_tests, TestStrictNotNull)
{
{
// raw ptr <-> strict_not_null
@ -66,7 +79,7 @@ TEST_CASE("TestStrictNotNull")
helper(snn1);
helper_const(snn1);
CHECK(*snn1 == 42);
EXPECT_TRUE(*snn1 == 42);
}
{
@ -80,7 +93,7 @@ TEST_CASE("TestStrictNotNull")
strict_helper_const(snn1);
strict_helper_const(snn2);
CHECK(snn1 == snn2);
EXPECT_TRUE(snn1 == snn2);
}
{
@ -95,8 +108,8 @@ TEST_CASE("TestStrictNotNull")
helper(snn);
helper_const(snn);
CHECK(snn == nn1);
CHECK(snn == nn2);
EXPECT_TRUE(snn == nn1);
EXPECT_TRUE(snn == nn2);
}
{
@ -111,16 +124,16 @@ TEST_CASE("TestStrictNotNull")
strict_helper(nn);
strict_helper_const(nn);
CHECK(snn1 == nn);
CHECK(snn2 == nn);
EXPECT_TRUE(snn1 == nn);
EXPECT_TRUE(snn2 == nn);
std::hash<strict_not_null<int*>> hash_snn;
std::hash<not_null<int*>> hash_nn;
CHECK(hash_nn(snn1) == hash_nn(nn));
CHECK(hash_snn(snn1) == hash_nn(nn));
CHECK(hash_nn(snn1) == hash_nn(snn2));
CHECK(hash_snn(snn1) == hash_snn(nn));
EXPECT_TRUE(hash_nn(snn1) == hash_nn(nn));
EXPECT_TRUE(hash_snn(snn1) == hash_nn(nn));
EXPECT_TRUE(hash_nn(snn1) == hash_nn(snn2));
EXPECT_TRUE(hash_snn(snn1) == hash_snn(nn));
}
#ifdef CONFIRM_COMPILATION_ERRORS
@ -131,10 +144,18 @@ TEST_CASE("TestStrictNotNull")
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
{
std::set_terminate([] {
std::cerr << "Expected Death. TestStrictNotNullConstructorTypeDeduction";
std::abort();
});
{
int i = 42;
@ -142,7 +163,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
helper(strict_not_null{&i});
helper_const(strict_not_null{&i});
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -153,7 +174,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
helper(strict_not_null{p});
helper_const(strict_not_null{p});
CHECK(*x == 42);
EXPECT_TRUE(*x == 42);
}
{
@ -161,7 +182,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
int* p1 = nullptr;
const strict_not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
EXPECT_DEATH(workaround_macro(), deathstring);
}
{
@ -169,14 +190,14 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
const int* p1 = nullptr;
const strict_not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
EXPECT_DEATH(workaround_macro(), deathstring);
}
{
int* p = nullptr;
CHECK_THROWS_AS(helper(strict_not_null{p}), fail_fast);
CHECK_THROWS_AS(helper_const(strict_not_null{p}), fail_fast);
EXPECT_DEATH(helper(strict_not_null{p}), deathstring);
EXPECT_DEATH(helper_const(strict_not_null{p}), deathstring);
}
#ifdef CONFIRM_COMPILATION_ERRORS
@ -191,3 +212,7 @@ TEST_CASE("TestStrictNotNullConstructorTypeDeduction")
static_assert(std::is_nothrow_move_constructible<strict_not_null<void*>>::value,
"strict_not_null must be no-throw move constructible");
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__

View File

@ -25,10 +25,17 @@
#if __clang__ || __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
//disable warnings from gtest
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, CHECK...
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast
#include <gsl/multi_span> // for strided_span, index, multi_span, strided_...
@ -39,24 +46,80 @@
#include <type_traits> // for integral_constant<>::value, is_convertible
#include <vector> // for vector
namespace gsl {
struct fail_fast;
} // namespace gsl
using namespace std;
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
struct BaseClass
{
};
struct DerivedClass : BaseClass
{
};
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
void iterate_every_other_element(multi_span<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]);
}
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<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];
@ -66,51 +129,54 @@ TEST_CASE("span_section_test")
(void) subsub;
}
TEST_CASE("span_section")
TEST(strided_span_tests, span_section)
{
std::vector<int> data(5 * 10);
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 strided_span<int, 2> 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<int, 2> 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<int, 1> sav1{arr, {{9}, {1}}}; // T -> T
CHECK(sav1.bounds().index_bounds() == multi_span_index<1>{9});
CHECK(sav1.bounds().stride() == 1);
CHECK((sav1[0] == 1 && sav1[8] == 9));
EXPECT_TRUE(sav1.bounds().index_bounds() == multi_span_index<1>{9});
EXPECT_TRUE(sav1.bounds().stride() == 1);
EXPECT_TRUE(sav1[0] == 1);
EXPECT_TRUE(sav1[8] == 9);
strided_span<const int, 1> sav2{carr, {{4}, {2}}}; // const T -> const T
CHECK(sav2.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav2.bounds().strides() == multi_span_index<1>{2});
CHECK((sav2[0] == 1 && sav2[3] == 7));
EXPECT_TRUE(sav2.bounds().index_bounds() == multi_span_index<1>{4});
EXPECT_TRUE(sav2.bounds().strides() == multi_span_index<1>{2});
EXPECT_TRUE(sav2[0] == 1);
EXPECT_TRUE(sav2[3] == 7);
strided_span<int, 2> sav3{arr, {{2, 2}, {6, 2}}}; // T -> const T
CHECK((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2}));
CHECK((sav3.bounds().strides() == multi_span_index<2>{6, 2}));
CHECK((sav3[{0, 0}] == 1 && sav3[{0, 1}] == 3 && sav3[{1, 0}] == 7));
EXPECT_TRUE((sav3.bounds().index_bounds() == multi_span_index<2>{2, 2}));
EXPECT_TRUE((sav3.bounds().strides() == multi_span_index<2>{6, 2}));
EXPECT_TRUE((sav3[{0, 0}]) == 1);
EXPECT_TRUE((sav3[{0, 1}]) == 3);
EXPECT_TRUE((sav3[{1, 0}]) == 7);
}
// Check multi_span constructor
// EXPECT_TRUE multi_span constructor
{
int arr[] = {1, 2};
@ -119,9 +185,9 @@ TEST_CASE("strided_span_constructors")
const multi_span<int> src = arr;
strided_span<int, 1> 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<const int, 1> sav_c{ {src}, {2, 1} };
@ -131,9 +197,9 @@ TEST_CASE("strided_span_constructors")
strided_span<const int, 1> sav_c{multi_span<const int>{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<volatile int, 1> sav_v{src, {2, 1}};
@ -141,9 +207,9 @@ TEST_CASE("strided_span_constructors")
strided_span<volatile int, 1> sav_v{multi_span<volatile int>{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<const volatile int, 1> sav_cv{src, {2, 1}};
@ -151,9 +217,9 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
EXPECT_TRUE(sav_cv[1] == 2);
}
// From const-qualified source
@ -161,9 +227,9 @@ TEST_CASE("strided_span_constructors")
const multi_span<const int> src{arr};
strided_span<const int, 1> 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<const volatile int, 1> sav_cv{src, {2, 1}};
@ -172,9 +238,9 @@ TEST_CASE("strided_span_constructors")
strided_bounds<1>{2, 1}};
#endif
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
EXPECT_TRUE(sav_cv[1] == 2);
}
// From volatile-qualified source
@ -182,9 +248,9 @@ TEST_CASE("strided_span_constructors")
const multi_span<volatile int> src{arr};
strided_span<volatile int, 1> 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<const volatile int, 1> sav_cv{src, {2, 1}};
@ -192,9 +258,9 @@ TEST_CASE("strided_span_constructors")
strided_span<const volatile int, 1> sav_cv{multi_span<const volatile int>{src},
strided_bounds<1>{2, 1}};
#endif
CHECK(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav_cv.bounds().strides() == multi_span_index<1>{1});
CHECK(sav_cv[1] == 2);
EXPECT_TRUE(sav_cv.bounds().index_bounds() == multi_span_index<1>{2});
EXPECT_TRUE(sav_cv.bounds().strides() == multi_span_index<1>{1});
EXPECT_TRUE(sav_cv[1] == 2);
}
// From cv-qualified source
@ -202,19 +268,19 @@ TEST_CASE("strided_span_constructors")
const multi_span<const volatile int> src{arr};
strided_span<const volatile int, 1> 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<int, 2> av(arr, 2);
multi_span<const int, 2> av2{av};
CHECK(av2[1] == 5);
EXPECT_TRUE(av2[1] == 5);
static_assert(
std::is_convertible<const multi_span<int, 2>, multi_span<const int, 2>>::value,
@ -222,34 +288,35 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr, {2, 1}};
strided_span<const int, 1> 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<const strided_span<int, 1>, strided_span<const int, 1>>::value,
"ctor is not implicit!");
}
// Check copy constructor
// EXPECT_TRUE copy constructor
{
int arr1[2] = {3, 4};
const strided_span<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> 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<const int, 2> src2{arr2, {{3, 2}, {2, 1}}};
strided_span<const int, 2> sav2{src2};
CHECK((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
CHECK((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
CHECK((sav2[{0, 0}] == 1 && sav2[{2, 0}] == 5));
EXPECT_TRUE((sav2.bounds().index_bounds() == multi_span_index<2>{3, 2}));
EXPECT_TRUE((sav2.bounds().strides() == multi_span_index<2>{2, 1}));
EXPECT_TRUE((sav2[{0, 0}]) == 1);
EXPECT_TRUE((sav2[{2, 0}]) == 5);
}
// Check const-casting assignment operator
// EXPECT_TRUE const-casting assignment operator
{
int arr1[2] = {1, 2};
int arr2[6] = {3, 4, 5, 6, 7, 8};
@ -257,38 +324,38 @@ TEST_CASE("strided_span_constructors")
const strided_span<int, 1> src{arr1, {{2}, {1}}};
strided_span<const int, 1> sav{arr2, {{3}, {2}}};
strided_span<const int, 1>& 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<int, 1> src1{arr1, {2, 1}};
strided_span<int, 1> sav1{arr1b, {1, 1}};
strided_span<int, 1>& 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<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_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<int> data(5 * 10);
std::iota(begin(data), end(data), 0);
@ -303,19 +370,18 @@ TEST_CASE("strided_span_slice")
{{5, 10}, {10, 1}}};
strided_span<int, 1> 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<const int, 1> csav_sl = sav[3];
CHECK(csav_sl[0] == 30);
CHECK(csav_sl[9] == 39);
EXPECT_TRUE(csav_sl[0] == 30);
EXPECT_TRUE(csav_sl[9] == 39);
CHECK(sav[4][0] == 40);
CHECK(sav[4][9] == 49);
EXPECT_TRUE(sav[4][0] == 40);
EXPECT_TRUE(sav[4][9] == 49);
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_column_major")
TEST(strided_span_tests, strided_span_column_major)
{
// strided_span may be used to accommodate more peculiar
// use cases, such as column-major multidimensional array
@ -325,119 +391,123 @@ TEST_CASE("strided_span_column_major")
strided_span<int, 2> 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<int, 1> 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<int, 2> 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<int> av(arr);
std::set_terminate([] {
std::cerr << "Expected Death. strided_span_bounds";
std::abort();
});
{
// incorrect sections
CHECK_THROWS_AS(av.section(0, 0)[0], fail_fast);
CHECK_THROWS_AS(av.section(1, 0)[0], fail_fast);
CHECK_THROWS_AS(av.section(1, 1)[1], fail_fast);
EXPECT_DEATH(av.section(0, 0)[0], deathstring);
EXPECT_DEATH(av.section(1, 0)[0], deathstring);
EXPECT_DEATH(av.section(1, 1)[1], deathstring);
CHECK_THROWS_AS(av.section(2, 5), fail_fast);
CHECK_THROWS_AS(av.section(5, 2), fail_fast);
CHECK_THROWS_AS(av.section(5, 0), fail_fast);
CHECK_THROWS_AS(av.section(0, 5), fail_fast);
CHECK_THROWS_AS(av.section(5, 5), fail_fast);
EXPECT_DEATH(av.section(2, 5), deathstring);
EXPECT_DEATH(av.section(5, 2), deathstring);
EXPECT_DEATH(av.section(5, 0), deathstring);
EXPECT_DEATH(av.section(0, 5), deathstring);
EXPECT_DEATH(av.section(5, 5), deathstring);
}
{
// zero stride
strided_span<int, 1> sav{av, {{4}, {}}};
CHECK(sav[0] == 0);
CHECK(sav[3] == 0);
CHECK_THROWS_AS(sav[4], fail_fast);
EXPECT_TRUE(sav[0] == 0);
EXPECT_TRUE(sav[3] == 0);
EXPECT_DEATH(sav[4], deathstring);
}
{
// zero extent
strided_span<int, 1> sav{av, {{}, {1}}};
CHECK_THROWS_AS(sav[0], fail_fast);
EXPECT_DEATH(sav[0], deathstring);
}
{
// zero extent and stride
strided_span<int, 1> sav{av, {{}, {}}};
CHECK_THROWS_AS(sav[0], fail_fast);
EXPECT_DEATH(sav[0], deathstring);
}
{
// strided array ctor with matching strided bounds
strided_span<int, 1> sav{arr, {4, 1}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{4});
CHECK(sav[3] == 3);
CHECK_THROWS_AS(sav[4], fail_fast);
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{4});
EXPECT_TRUE(sav[3] == 3);
EXPECT_DEATH(sav[4], deathstring);
}
{
// strided array ctor with smaller strided bounds
strided_span<int, 1> sav{arr, {2, 1}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[1] == 1);
CHECK_THROWS_AS(sav[2], fail_fast);
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
EXPECT_TRUE(sav[1] == 1);
EXPECT_DEATH(sav[2], deathstring);
}
{
// strided array ctor with fitting irregular bounds
strided_span<int, 1> sav{arr, {2, 3}};
CHECK(sav.bounds().index_bounds() == multi_span_index<1>{2});
CHECK(sav[0] == 0);
CHECK(sav[1] == 3);
CHECK_THROWS_AS(sav[2], fail_fast);
EXPECT_TRUE(sav.bounds().index_bounds() == multi_span_index<1>{2});
EXPECT_TRUE(sav[0] == 0);
EXPECT_TRUE(sav[1] == 3);
EXPECT_DEATH(sav[2], deathstring);
}
{
// bounds cross data boundaries - from static arrays
CHECK_THROWS_AS((strided_span<int, 1>{arr, {3, 2}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{arr, {3, 3}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{arr, {4, 5}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{arr, {5, 1}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{arr, {5, 5}}), fail_fast);
EXPECT_DEATH((strided_span<int, 1>{arr, {3, 2}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{arr, {3, 3}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{arr, {4, 5}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{arr, {5, 1}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{arr, {5, 5}}), deathstring);
}
{
// bounds cross data boundaries - from array view
CHECK_THROWS_AS((strided_span<int, 1>{av, {3, 2}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av, {3, 3}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av, {4, 5}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av, {5, 1}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av, {5, 5}}), fail_fast);
EXPECT_DEATH((strided_span<int, 1>{av, {3, 2}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av, {3, 3}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av, {4, 5}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av, {5, 1}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av, {5, 5}}), deathstring);
}
{
// bounds cross data boundaries - from dynamic arrays
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {3, 2}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {3, 3}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {4, 5}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {5, 1}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 4, {5, 5}}), fail_fast);
CHECK_THROWS_AS((strided_span<int, 1>{av.data(), 2, {2, 2}}), fail_fast);
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {3, 2}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {3, 3}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {4, 5}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {5, 1}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av.data(), 4, {5, 5}}), deathstring);
EXPECT_DEATH((strided_span<int, 1>{av.data(), 2, {2, 2}}), deathstring);
}
#ifdef CONFIRM_COMPILATION_ERRORS
@ -464,12 +534,16 @@ TEST_CASE("strided_span_bounds")
#endif
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("strided_span_type_conversion")
TEST(strided_span_tests, strided_span_type_conversion)
{
int arr[] = {0, 1, 2, 3};
multi_span<int> av(arr);
std::set_terminate([] {
std::cerr << "Expected Death. strided_span_type_conversion";
std::abort();
});
{
strided_span<int, 1> sav{av.data(), av.size(), {av.size() / 2, 2}};
#ifdef CONFIRM_COMPILATION_ERRORS
@ -490,10 +564,10 @@ TEST_CASE("strided_span_type_conversion")
strided_bounds<2> bounds{{2, bytes.size() / 4}, {bytes.size() / 2, 1}};
strided_span<const byte, 2> sav2{bytes.data(), bytes.size(), bounds};
strided_span<const int, 2> sav3 = sav2.as_strided_span<const int>();
CHECK(sav3[0][0] == 0);
CHECK(sav3[1][0] == 2);
CHECK_THROWS_AS(sav3[1][1], fail_fast);
CHECK_THROWS_AS(sav3[0][1], fail_fast);
EXPECT_TRUE(sav3[0][0] == 0);
EXPECT_TRUE(sav3[1][0] == 2);
EXPECT_DEATH(sav3[1][1], deathstring);
EXPECT_DEATH(sav3[0][1], deathstring);
}
// retype strided array with regular strides - from multi_span
@ -503,10 +577,10 @@ TEST_CASE("strided_span_type_conversion")
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
strided_span<const byte, 2> sav2{bytes2, bounds};
strided_span<int, 2> sav3 = sav2.as_strided_span<int>();
CHECK(sav3[0][0] == 0);
CHECK(sav3[1][0] == 2);
CHECK_THROWS_AS(sav3[1][1], fail_fast);
CHECK_THROWS_AS(sav3[0][1], fail_fast);
EXPECT_TRUE(sav3[0][0] == 0);
EXPECT_TRUE(sav3[1][0] == 2);
EXPECT_DEATH(sav3[1][1], deathstring);
EXPECT_DEATH(sav3[0][1], deathstring);
}
// retype strided array with not enough elements - last dimension of the array is too small
@ -515,7 +589,7 @@ TEST_CASE("strided_span_type_conversion")
multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
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>(), deathstring);
}
// retype strided array with not enough elements - strides are too small
@ -524,7 +598,7 @@ TEST_CASE("strided_span_type_conversion")
multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
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>(), deathstring);
}
// retype strided array with not enough elements - last dimension does not divide by the new
@ -534,7 +608,7 @@ TEST_CASE("strided_span_type_conversion")
multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
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>(), deathstring);
}
// retype strided array with not enough elements - strides does not divide by the new
@ -544,88 +618,63 @@ TEST_CASE("strided_span_type_conversion")
multi_span<const byte, 2, dynamic_range> bytes2 =
as_multi_span(bytes, dim<2>(), dim(bytes.size() / 2));
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>(), deathstring);
}
// retype strided array with irregular strides - from raw data
{
strided_bounds<1> bounds{bytes.size() / 2, 2};
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>(), deathstring);
}
// retype strided array with irregular strides - from multi_span
{
strided_bounds<1> bounds{bytes.size() / 2, 2};
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>(), deathstring);
}
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
TEST_CASE("empty_strided_spans")
TEST(strided_span_tests, empty_strided_spans)
{
std::set_terminate([] {
std::cerr << "Expected Death. empty_strided_spans";
std::abort();
});
{
multi_span<int, 0> empty_av(nullptr);
strided_span<int, 1> empty_sav{empty_av, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK(empty_sav.empty());
CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
EXPECT_TRUE(empty_sav.empty());
EXPECT_DEATH(empty_sav[0], deathstring);
EXPECT_DEATH(empty_sav.begin()[0], deathstring);
EXPECT_DEATH(empty_sav.cbegin()[0], deathstring);
for (const auto& v : empty_sav) {
(void) v;
CHECK(false);
EXPECT_TRUE(false);
}
}
{
strided_span<int, 1> empty_sav{nullptr, 0, {0, 1}};
CHECK(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
CHECK_THROWS_AS(empty_sav[0], fail_fast);
CHECK_THROWS_AS(empty_sav.begin()[0], fail_fast);
CHECK_THROWS_AS(empty_sav.cbegin()[0], fail_fast);
EXPECT_TRUE(empty_sav.bounds().index_bounds() == multi_span_index<1>{0});
EXPECT_DEATH(empty_sav[0], deathstring);
EXPECT_DEATH(empty_sav.begin()[0], deathstring);
EXPECT_DEATH(empty_sav.cbegin()[0], deathstring);
for (const auto& v : empty_sav) {
(void) v;
CHECK(false);
EXPECT_TRUE(false);
}
}
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
void iterate_every_other_element(multi_span<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")
TEST(strided_span_tests, strided_span_section_iteration)
{
int arr[8] = {4, 0, 5, 1, 6, 2, 7, 3};
@ -642,12 +691,7 @@ TEST_CASE("strided_span_section_iteration")
}
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
TEST_CASE("dynamic_strided_span_section_iteration")
TEST(strided_span_tests, dynamic_strided_span_section_iteration)
{
auto arr = new int[8];
for (int i = 0; i < 4; ++i) {
@ -661,39 +705,7 @@ TEST_CASE("dynamic_strided_span_section_iteration")
delete[] arr;
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // TODO: does not work
void iterate_second_slice(multi_span<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")
TEST(strided_span_tests, strided_span_section_iteration_3d)
{
int arr[3][4][2]{};
for (auto i = 0; i < 3; ++i) {
@ -707,12 +719,7 @@ TEST_CASE("strided_span_section_iteration_3d")
}
}
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(r.3) // NO-FORMAT: attribute
GSL_SUPPRESS(r.5) // NO-FORMAT: attribute
GSL_SUPPRESS(r.11) // NO-FORMAT: attribute
TEST_CASE("dynamic_strided_span_section_iteration_3d")
TEST(strided_span_tests, dynamic_strided_span_section_iteration_3d)
{
const auto height = 12, width = 2;
const auto size = height * width;
@ -744,11 +751,13 @@ TEST_CASE("dynamic_strided_span_section_iteration_3d")
delete[] arr;
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
TEST_CASE("strided_span_conversion")
TEST(strided_span_tests, strided_span_conversion)
{
std::set_terminate([] {
std::cerr << "Expected Death. strided_span_conversion";
std::abort();
});
// get an multi_span of 'c' values from the list of X's
struct X
@ -767,8 +776,8 @@ TEST_CASE("strided_span_conversion")
// convert to 4x12 array of bytes
auto av = as_multi_span(as_bytes(as_multi_span(&arr[0], 4)), dim(d1), dim(d2));
CHECK(av.bounds().index_bounds()[0] == 4);
CHECK(av.bounds().index_bounds()[1] == 12);
EXPECT_TRUE(av.bounds().index_bounds()[0] == 4);
EXPECT_TRUE(av.bounds().index_bounds()[1] == 12);
// get the last 4 columns
auto section = av.section({0, 2 * s}, {4, s}); // { { arr[0].c[0], arr[0].c[1], arr[0].c[2],
@ -778,8 +787,8 @@ TEST_CASE("strided_span_conversion")
// convert to array 4x1 array of integers
auto cs = section.as_strided_span<int>(); // { { arr[0].c }, {arr[1].c } , ... }
CHECK(cs.bounds().index_bounds()[0] == 4);
CHECK(cs.bounds().index_bounds()[1] == 1);
EXPECT_TRUE(cs.bounds().index_bounds()[0] == 4);
EXPECT_TRUE(cs.bounds().index_bounds()[1] == 1);
// transpose to 1x4 array
strided_bounds<2> reverse_bounds{
@ -791,16 +800,16 @@ TEST_CASE("strided_span_conversion")
// slice to get a one-dimensional array of c's
strided_span<int, 1> result = transposed[0];
CHECK(result.bounds().index_bounds()[0] == 4);
CHECK_THROWS_AS(result.bounds().index_bounds()[1], fail_fast);
EXPECT_TRUE(result.bounds().index_bounds()[0] == 4);
EXPECT_DEATH(result.bounds().index_bounds()[1], deathstring);
int i = 0;
for (auto& num : result) {
CHECK(num == arr[i].c);
EXPECT_TRUE(num == arr[i].c);
i++;
}
}
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif
#endif // __clang__ || __GNUC__

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
#define CATCH_CONFIG_MAIN
#ifdef _MSC_VER
// blanket turn off warnings from CppCoreCheck from catch
// so people aren't annoyed by them when running the tool.
#include <CodeAnalysis/Warnings.h>
#pragma warning(disable : ALL_CODE_ANALYSIS_WARNINGS) // from catch
#endif // _MSC_VER
#include <catch/catch.hpp>

View File

@ -21,7 +21,20 @@
#endif
#include <catch/catch.hpp> // for AssertionHandler, StringRef, CHECK, TEST_...
#if __clang__ || __GNUC__
//disable warnings from gtest
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif // __clang__ || __GNUC__
#if __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
#pragma GCC diagnostic ignored "-Wcovered-switch-default"
#endif // __clang__
#include <gtest/gtest.h>
#include <gsl/gsl_util> // for narrow, finally, narrow_cast, narrowing_e...
@ -33,101 +46,114 @@
using namespace gsl;
TEST_CASE("sanity check for gsl::index typedef")
namespace
{
static constexpr char deathstring[] = "Expected Death";
void f(int& i) { i += 1; }
static int j = 0;
void g() { j += 1; }
}
TEST(utils_tests, sanity_check_for_gsl_index_typedef)
{
static_assert(std::is_same<gsl::index, std::ptrdiff_t>::value,
"gsl::index represents wrong arithmetic type");
}
void f(int& i) { i += 1; }
TEST_CASE("finally_lambda")
TEST(utils_tests, finally_lambda)
{
int i = 0;
{
auto _ = finally([&]() { f(i); });
CHECK(i == 0);
EXPECT_TRUE(i == 0);
}
CHECK(i == 1);
EXPECT_TRUE(i == 1);
}
TEST_CASE("finally_lambda_move")
TEST(utils_tests, finally_lambda_move)
{
int i = 0;
{
auto _1 = finally([&]() { f(i); });
{
auto _2 = std::move(_1);
CHECK(i == 0);
EXPECT_TRUE(i == 0);
}
CHECK(i == 1);
EXPECT_TRUE(i == 1);
{
auto _2 = std::move(_1);
CHECK(i == 1);
EXPECT_TRUE(i == 1);
}
CHECK(i == 1);
EXPECT_TRUE(i == 1);
}
CHECK(i == 1);
EXPECT_TRUE(i == 1);
}
TEST_CASE("finally_function_with_bind")
TEST(utils_tests, finally_function_with_bind)
{
int i = 0;
{
auto _ = finally(std::bind(&f, std::ref(i)));
CHECK(i == 0);
EXPECT_TRUE(i == 0);
}
CHECK(i == 1);
EXPECT_TRUE(i == 1);
}
static int j = 0;
void g() { j += 1; }
TEST_CASE("finally_function_ptr")
TEST(utils_tests, finally_function_ptr)
{
j = 0;
{
auto _ = finally(&g);
CHECK(j == 0);
EXPECT_TRUE(j == 0);
}
CHECK(j == 1);
EXPECT_TRUE(j == 1);
}
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
TEST_CASE("narrow_cast")
TEST(utils_tests, narrow_cast)
{
int n = 120;
char c = narrow_cast<char>(n);
CHECK(c == 120);
EXPECT_TRUE(c == 120);
n = 300;
unsigned char uc = narrow_cast<unsigned char>(n);
CHECK(uc == 44);
EXPECT_TRUE(uc == 44);
}
GSL_SUPPRESS(con.5) // NO-FORMAT: attribute
TEST_CASE("narrow")
TEST(utils_tests, narrow)
{
std::set_terminate([] {
std::cerr << "Expected Death. narrow";
std::abort();
});
int n = 120;
const char c = narrow<char>(n);
CHECK(c == 120);
EXPECT_TRUE(c == 120);
n = 300;
CHECK_THROWS_AS(narrow<char>(n), narrowing_error);
EXPECT_DEATH(narrow<char>(n), deathstring);
const auto int32_max = std::numeric_limits<int32_t>::max();
const auto int32_min = std::numeric_limits<int32_t>::min();
CHECK(narrow<uint32_t>(int32_t(0)) == 0);
CHECK(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_t(0)) == 0);
EXPECT_TRUE(narrow<uint32_t>(int32_t(1)) == 1);
EXPECT_TRUE(narrow<uint32_t>(int32_max) == static_cast<uint32_t>(int32_max));
CHECK_THROWS_AS(narrow<uint32_t>(int32_t(-1)), narrowing_error);
CHECK_THROWS_AS(narrow<uint32_t>(int32_min), narrowing_error);
EXPECT_DEATH(narrow<uint32_t>(int32_t(-1)), deathstring);
EXPECT_DEATH(narrow<uint32_t>(int32_min), deathstring);
n = -42;
CHECK_THROWS_AS(narrow<unsigned>(n), narrowing_error);
EXPECT_DEATH(narrow<unsigned>(n), deathstring);
#if GSL_CONSTEXPR_NARROW
static_assert(narrow<char>(120) == 120, "Fix GSL_CONSTEXPR_NARROW");
#endif
}
#if __clang__ || __GNUC__
#pragma GCC diagnostic pop
#endif // __clang__ || __GNUC__