mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-01 21:05:39 +02:00
Move tests from projects/ to tests/
This commit is contained in:
259
tests/CMakeLists.txt
Normal file
259
tests/CMakeLists.txt
Normal file
@@ -0,0 +1,259 @@
|
||||
include(MiscFunctions)
|
||||
|
||||
####
|
||||
# Temporary workaround for VS toolset changes in 2017
|
||||
# We need to disable <UseFullPaths> property, but CMake doesn't support it
|
||||
# until 3.13 (not yet released)
|
||||
####
|
||||
if (MSVC)
|
||||
configure_file(${CATCH_DIR}/misc/SelfTest.vcxproj.user
|
||||
${CMAKE_BINARY_DIR}/tests
|
||||
COPYONLY)
|
||||
endif(MSVC) #Temporary workaround
|
||||
|
||||
|
||||
# define the sources of the self test
|
||||
# Please keep these ordered alphabetically
|
||||
set(TEST_SOURCES
|
||||
${SELF_TEST_DIR}/TestMain.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Details.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/RandomNumberGeneration.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/StringManip.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
|
||||
${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Class.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Compilation.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Condition.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Generators.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringByte.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringOptional.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringVariant.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
|
||||
${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
|
||||
)
|
||||
CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
|
||||
|
||||
# A set of impl files that just #include a single header
|
||||
# Please keep these ordered alphabetically
|
||||
set(SURROGATE_SOURCES
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
|
||||
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
|
||||
)
|
||||
CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
|
||||
|
||||
|
||||
# Specify the headers, too, so CLion recognises them as project files
|
||||
set(HEADERS
|
||||
${TOP_LEVEL_HEADERS}
|
||||
${EXTERNAL_HEADERS}
|
||||
${INTERNAL_HEADERS}
|
||||
${REPORTER_HEADERS}
|
||||
${BENCHMARK_HEADERS}
|
||||
${BENCHMARK_SOURCES}
|
||||
)
|
||||
|
||||
# Provide some groupings for IDEs
|
||||
#SOURCE_GROUP("benchmark" FILES ${BENCHMARK_HEADERS} ${BENCHMARK_SOURCES})
|
||||
#SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
||||
#SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
||||
|
||||
include(CTest)
|
||||
|
||||
add_executable(SelfTest ${TEST_SOURCES})
|
||||
target_link_libraries(SelfTest PRIVATE Catch2)
|
||||
|
||||
# It took CMake until 3.8 to abandon the doomed approach of enumerating
|
||||
# required features so we just list bunch of C++11 and C++14 features.
|
||||
target_compile_features(SelfTest
|
||||
PRIVATE
|
||||
cxx_alignas
|
||||
cxx_alignof
|
||||
cxx_attributes
|
||||
cxx_auto_type
|
||||
cxx_constexpr
|
||||
cxx_defaulted_functions
|
||||
cxx_deleted_functions
|
||||
cxx_final
|
||||
cxx_lambdas
|
||||
cxx_noexcept
|
||||
cxx_override
|
||||
cxx_range_for
|
||||
cxx_rvalue_references
|
||||
cxx_static_assert
|
||||
cxx_strong_enums
|
||||
cxx_trailing_return_types
|
||||
cxx_unicode_literals
|
||||
cxx_user_literals
|
||||
cxx_variadic_macros
|
||||
cxx_variable_templates
|
||||
)
|
||||
|
||||
|
||||
if (CATCH_ENABLE_COVERAGE)
|
||||
set(ENABLE_COVERAGE ON CACHE BOOL "Enable coverage build." FORCE)
|
||||
find_package(codecov)
|
||||
add_coverage(SelfTest)
|
||||
list(APPEND LCOV_REMOVE_PATTERNS "'/usr/*'")
|
||||
coverage_evaluate()
|
||||
endif()
|
||||
|
||||
# Add per compiler options
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic -Wmissing-declarations )
|
||||
if (CATCH_ENABLE_WERROR)
|
||||
target_compile_options( SelfTest PRIVATE -Werror )
|
||||
endif()
|
||||
endif()
|
||||
# Clang specific options go here
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
|
||||
endif()
|
||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
||||
STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
|
||||
target_compile_options( SelfTest PRIVATE /w44265 /w44061 /w44062 /w45038 )
|
||||
if (CATCH_ENABLE_WERROR)
|
||||
target_compile_options( SelfTest PRIVATE /WX)
|
||||
endif()
|
||||
# Force MSVC to consider everything as encoded in utf-8
|
||||
target_compile_options( SelfTest PRIVATE /utf-8 )
|
||||
endif()
|
||||
|
||||
|
||||
# configure unit tests via CTest
|
||||
add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
|
||||
set_tests_properties(RunTests PROPERTIES
|
||||
FAIL_REGULAR_EXPRESSION "Filters:"
|
||||
)
|
||||
|
||||
# Because CTest does not allow us to check both return code _and_ expected
|
||||
# output in one test, we run these commands twice. First time we check
|
||||
# the output, the second time we check the exit code.
|
||||
add_test(NAME List::Tests::Output COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||
set_tests_properties(List::Tests::Output PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "[0-9]+ test cases"
|
||||
FAIL_REGULAR_EXPRESSION "Hidden Test"
|
||||
)
|
||||
add_test(NAME List::Tests::ExitCode COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||
add_test(NAME List::Tests::XmlOutput COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high -r xml)
|
||||
set_tests_properties(List::Tests::XmlOutput PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "<Line>[0-9]+</Line>"
|
||||
FAIL_REGULAR_EXPRESSION "[0-9]+ test cases"
|
||||
)
|
||||
|
||||
add_test(NAME List::Tags::Output COMMAND $<TARGET_FILE:SelfTest> --list-tags)
|
||||
set_tests_properties(List::Tags::Output PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "[0-9]+ tags"
|
||||
FAIL_REGULAR_EXPRESSION "\\[\\.\\]")
|
||||
add_test(NAME List::Tags::ExitCode COMMAND $<TARGET_FILE:SelfTest> --list-tags)
|
||||
add_test(NAME List::Tags::XmlOutput COMMAND $<TARGET_FILE:SelfTest> --list-tags -r xml)
|
||||
set_tests_properties(List::Tags::XmlOutput PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "<Count>18</Count>"
|
||||
FAIL_REGULAR_EXPRESSION "[0-9]+ tags"
|
||||
)
|
||||
|
||||
|
||||
add_test(NAME List::Reporters::Output COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
|
||||
set_tests_properties(List::Reporters::Output PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
|
||||
add_test(NAME List::Reporters::ExitCode COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
|
||||
add_test(NAME List::Reporters::XmlOutput COMMAND $<TARGET_FILE:SelfTest> --list-reporters -r xml)
|
||||
set_tests_properties(List::Reporters::XmlOutput PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "<Name>compact</Name>"
|
||||
FAIL_REGULAR_EXPRESSION "Available reporters:"
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
|
||||
set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")
|
||||
|
||||
add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> Tracker, "___nonexistent_test___")
|
||||
set_tests_properties(NoTest PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "No test cases matched '___nonexistent_test___'"
|
||||
FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
)
|
||||
|
||||
add_test(NAME WarnAboutNoTests COMMAND ${CMAKE_COMMAND} -P ${SELF_TEST_DIR}/WarnAboutNoTests.cmake $<TARGET_FILE:SelfTest>)
|
||||
|
||||
add_test(NAME UnmatchedOutputFilter COMMAND $<TARGET_FILE:SelfTest> [this-tag-does-not-exist] -w NoTests)
|
||||
set_tests_properties(UnmatchedOutputFilter
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "No test cases matched '\\[this-tag-does-not-exist\\]'"
|
||||
)
|
||||
|
||||
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
|
||||
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
||||
add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
|
||||
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
|
||||
|
||||
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
||||
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
||||
|
||||
add_test(NAME RegressionCheck-1670 COMMAND $<TARGET_FILE:SelfTest> "#1670 regression check" -c A -r compact)
|
||||
set_tests_properties(RegressionCheck-1670 PROPERTIES PASS_REGULAR_EXPRESSION "Passed 1 test case with 2 assertions.")
|
||||
|
||||
add_test(NAME VersionCheck COMMAND $<TARGET_FILE:SelfTest> -h)
|
||||
set_tests_properties(VersionCheck PROPERTIES PASS_REGULAR_EXPRESSION "Catch v${PROJECT_VERSION}")
|
||||
|
||||
add_test(NAME LibIdentityTest COMMAND $<TARGET_FILE:SelfTest> --libidentify)
|
||||
set_tests_properties(LibIdentityTest PROPERTIES PASS_REGULAR_EXPRESSION "description: A Catch2 test executable")
|
||||
|
||||
add_test(NAME FilenameAsTagsTest COMMAND $<TARGET_FILE:SelfTest> -\# --list-tags)
|
||||
set_tests_properties(FilenameAsTagsTest PROPERTIES PASS_REGULAR_EXPRESSION "\\[#Approx.tests\\]")
|
||||
|
||||
add_test(NAME EscapeSpecialCharactersInTestNames COMMAND $<TARGET_FILE:SelfTest> "Test with special\\, characters \"in name")
|
||||
set_tests_properties(EscapeSpecialCharactersInTestNames PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
||||
|
||||
add_test(NAME NegativeSpecNoHiddenTests COMMAND $<TARGET_FILE:SelfTest> --list-tests ~[approval])
|
||||
set_tests_properties(NegativeSpecNoHiddenTests PROPERTIES FAIL_REGULAR_EXPRESSION "\\[\\.\\]")
|
||||
|
||||
add_test(NAME TestsInFile::SimpleSpecs COMMAND $<TARGET_FILE:SelfTest> "-f ${SELF_TEST_DIR}/Misc/plain-old-tests.input")
|
||||
set_tests_properties(TestsInFile::SimpleSpecs PROPERTIES PASS_REGULAR_EXPRESSION "6 assertions in 2 test cases")
|
||||
|
||||
add_test(NAME TestsInFile::EscapeSpecialCharacters COMMAND $<TARGET_FILE:SelfTest> "-f ${SELF_TEST_DIR}/Misc/special-characters-in-file.input")
|
||||
set_tests_properties(TestsInFile::EscapeSpecialCharacters PROPERTIES PASS_REGULAR_EXPRESSION "1 assertion in 1 test case")
|
||||
|
||||
# CTest does not allow us to create an AND of required regular expressions,
|
||||
# so we have to split the test into 2 parts and look for parts of the expected
|
||||
# output separately.
|
||||
add_test(NAME TestsInFile::InvalidTestNames-1 COMMAND $<TARGET_FILE:SelfTest> "-f ${SELF_TEST_DIR}/Misc/invalid-test-names.input")
|
||||
set_tests_properties(TestsInFile::InvalidTestNames-1 PROPERTIES PASS_REGULAR_EXPRESSION "Invalid Filter: \"Test with special, characters in \\\\\" name\"")
|
||||
|
||||
add_test(NAME TestsInFile::InvalidTestNames-2 COMMAND $<TARGET_FILE:SelfTest> "-f ${SELF_TEST_DIR}/Misc/invalid-test-names.input")
|
||||
set_tests_properties(TestsInFile::InvalidTestNames-2 PROPERTIES PASS_REGULAR_EXPRESSION "No tests ran")
|
||||
|
||||
|
||||
if (CATCH_USE_VALGRIND)
|
||||
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
|
||||
add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
|
||||
set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
||||
add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
|
||||
set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
|
||||
endif()
|
158
tests/ExtraTests/CMakeLists.txt
Normal file
158
tests/ExtraTests/CMakeLists.txt
Normal file
@@ -0,0 +1,158 @@
|
||||
#
|
||||
# Build extra tests.
|
||||
#
|
||||
# Requires CATCH_BUILD_EXTRA_TESTS to be defined 'true', see ../CMakeLists.txt.
|
||||
#
|
||||
|
||||
cmake_minimum_required( VERSION 3.5 )
|
||||
|
||||
project( Catch2ExtraTests LANGUAGES CXX )
|
||||
|
||||
message( STATUS "Extra tests included" )
|
||||
|
||||
# define folders used:
|
||||
|
||||
set( TESTS_DIR ${CATCH_DIR}/projects/ExtraTests )
|
||||
set( SINGLE_INCLUDE_PATH ${CATCH_DIR}/single_include )
|
||||
|
||||
|
||||
add_executable(PrefixedMacros ${TESTS_DIR}/X01-PrefixedMacros.cpp)
|
||||
target_compile_definitions( PrefixedMacros PRIVATE CATCH_CONFIG_PREFIX_ALL )
|
||||
|
||||
add_test(NAME CATCH_CONFIG_PREFIX_ALL COMMAND PrefixedMacros -s)
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_PREFIX_ALL
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "CATCH_"
|
||||
FAIL_REGULAR_EXPRESSION
|
||||
# The spaces are important -> They disambiguate between CATCH_REQUIRE
|
||||
# and REQUIRE without prefix.
|
||||
" REQUIRE; REQUIRE_FALSE; REQUIRE_THROWS; REQUIRE_THROWS_AS; REQUIRE_THROWS_WITH; REQUIRE_THROWS_MATCHES; REQUIRE_NOTHROW; CHECK; CHECK_FALSE; CHECKED_IF; CHECKED_ELSE; CHECK_NOFAIL; CHECK_THROWS; CHECK_THROWS_AS; CHECK_THROWS_WITH; CHECK_THROWS_MATCHES; CHECK_NOTHROW; REQUIRE_THAT; CHECK_THAT"
|
||||
)
|
||||
|
||||
add_executable(DisabledMacros ${TESTS_DIR}/X02-DisabledMacros.cpp)
|
||||
target_compile_definitions( DisabledMacros PRIVATE CATCH_CONFIG_DISABLE )
|
||||
|
||||
add_test(NAME CATCH_CONFIG_DISABLE-1 COMMAND DisabledMacros -s)
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE-1
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "No tests ran"
|
||||
FAIL_REGULAR_EXPRESSION "This should not happen"
|
||||
)
|
||||
add_test(NAME CATCH_CONFIG_DISABLE-2 COMMAND DisabledMacros --list-tests)
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE-2
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "0 test cases"
|
||||
)
|
||||
|
||||
|
||||
add_executable( DisabledExceptions-DefaultHandler ${TESTS_DIR}/X03-DisabledExceptions-DefaultHandler.cpp )
|
||||
add_executable( DisabledExceptions-CustomHandler ${TESTS_DIR}/X04-DisabledExceptions-CustomHandler.cpp )
|
||||
|
||||
foreach(target DisabledExceptions-DefaultHandler DisabledExceptions-CustomHandler)
|
||||
target_compile_options( ${target}
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/EHs-c-;/D_HAS_EXCEPTIONS=0>
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:AppleClang>>:-fno-exceptions>
|
||||
# $<$<CXX_COMPILER_ID:Clang>:-fno-exceptions>
|
||||
# $<$<CXX_COMPILER_ID:GNU>:-fno-exceptions>
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
||||
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-1 COMMAND DisabledExceptions-DefaultHandler "Tests that run")
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE_EXCEPTIONS-1
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "assertions: 4 \| 2 passed \| 2 failed"
|
||||
FAIL_REGULAR_EXPRESSION "abort;terminate;fatal"
|
||||
)
|
||||
|
||||
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-2 COMMAND DisabledExceptions-DefaultHandler "Tests that abort")
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE_EXCEPTIONS-2
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "Catch will terminate"
|
||||
)
|
||||
|
||||
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-3 COMMAND DisabledExceptions-CustomHandler "Tests that run")
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE_EXCEPTIONS-3
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "assertions: 4 \| 2 passed \| 2 failed"
|
||||
FAIL_REGULAR_EXPRESSION "====== CUSTOM HANDLER ======"
|
||||
)
|
||||
|
||||
add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-4 COMMAND DisabledExceptions-CustomHandler "Tests that abort")
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE_EXCEPTIONS-4
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "====== CUSTOM HANDLER ======"
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_executable(FallbackStringifier ${TESTS_DIR}/X10-FallbackStringifier.cpp)
|
||||
target_compile_definitions( FallbackStringifier PRIVATE CATCH_CONFIG_FALLBACK_STRINGIFIER=fallbackStringifier )
|
||||
|
||||
add_test(NAME FallbackStringifier COMMAND FallbackStringifier -r compact -s)
|
||||
set_tests_properties(
|
||||
FallbackStringifier
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "foo{} for: { !!! }"
|
||||
)
|
||||
|
||||
|
||||
add_executable(DisableStringification ${TESTS_DIR}/X11-DisableStringification.cpp)
|
||||
target_compile_definitions( DisableStringification PRIVATE CATCH_CONFIG_DISABLE_STRINGIFICATION )
|
||||
add_test(NAME CATCH_CONFIG_DISABLE_STRINGIFICATION COMMAND DisableStringification -r compact -s)
|
||||
set_tests_properties(
|
||||
CATCH_CONFIG_DISABLE_STRINGIFICATION
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
|
||||
FAIL_REGULAR_EXPRESSION "Hidden{} == Hidden{}"
|
||||
)
|
||||
|
||||
|
||||
add_executable(BenchmarkingMacros ${TESTS_DIR}/X20-BenchmarkingMacros.cpp)
|
||||
target_compile_definitions( BenchmarkingMacros PRIVATE CATCH_CONFIG_ENABLE_BENCHMARKING )
|
||||
|
||||
add_test(NAME BenchmarkingMacros COMMAND BenchmarkingMacros -r console -s)
|
||||
set_tests_properties(
|
||||
BenchmarkingMacros
|
||||
PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated"
|
||||
)
|
||||
|
||||
# This test touches windows.h, so it should only be compiled under msvc
|
||||
if (MSVC)
|
||||
# This test fails if it does not compile and succeeds otherwise
|
||||
add_executable(WindowsHeader ${TESTS_DIR}/X90-WindowsHeaderInclusion.cpp)
|
||||
set_property( TARGET WindowsHeader PROPERTY CXX_STANDARD 14 )
|
||||
set_property( TARGET WindowsHeader PROPERTY CXX_STANDARD_REQUIRED ON )
|
||||
set_property( TARGET WindowsHeader PROPERTY CXX_EXTENSIONS OFF )
|
||||
target_include_directories( WindowsHeader PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||
add_test(NAME WindowsHeader COMMAND WindowsHeader -r compact)
|
||||
endif()
|
||||
|
||||
set( EXTRA_TEST_BINARIES
|
||||
PrefixedMacros
|
||||
DisabledMacros
|
||||
DisabledExceptions-DefaultHandler
|
||||
DisabledExceptions-CustomHandler
|
||||
FallbackStringifier
|
||||
DisableStringification
|
||||
BenchmarkingMacros
|
||||
)
|
||||
|
||||
# Shared config
|
||||
foreach( test ${EXTRA_TEST_BINARIES} )
|
||||
set_property( TARGET ${test} PROPERTY CXX_STANDARD 14 )
|
||||
set_property( TARGET ${test} PROPERTY CXX_STANDARD_REQUIRED ON )
|
||||
set_property( TARGET ${test} PROPERTY CXX_EXTENSIONS OFF )
|
||||
target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
|
||||
endforeach()
|
||||
|
||||
|
11
tests/ExtraTests/ToDo.txt
Normal file
11
tests/ExtraTests/ToDo.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Configuration options that are left default and thus are not properly tested
|
||||
yet:
|
||||
|
||||
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
|
||||
CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows
|
||||
CATCH_CONFIG_FAST_COMPILE // Sacrifices some (rather minor) features for compilation speed
|
||||
CATCH_CONFIG_DISABLE_MATCHERS // Do not compile Matchers in this compilation unit
|
||||
CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals
|
||||
CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap
|
||||
CATCH_CONFIG_DEFAULT_REPORTER
|
||||
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
|
81
tests/ExtraTests/X01-PrefixedMacros.cpp
Normal file
81
tests/ExtraTests/X01-PrefixedMacros.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// X11-DisableStringification.cpp
|
||||
// Test that Catch's prefixed macros compile and run properly.
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
// This won't provide full coverage, but it might be worth checking
|
||||
// the other branch as well
|
||||
#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
|
||||
[[noreturn]]
|
||||
void this_throws() {
|
||||
throw std::runtime_error("Some msg");
|
||||
}
|
||||
void this_doesnt_throw() {}
|
||||
|
||||
CATCH_TEST_CASE("PrefixedMacros") {
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
CATCH_REQUIRE( 1 == 1 );
|
||||
CATCH_REQUIRE_FALSE( 1 != 1 );
|
||||
|
||||
CATCH_REQUIRE_THROWS(this_throws());
|
||||
CATCH_REQUIRE_THROWS_AS(this_throws(), std::runtime_error);
|
||||
CATCH_REQUIRE_THROWS_WITH(this_throws(), "Some msg");
|
||||
CATCH_REQUIRE_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
|
||||
CATCH_REQUIRE_NOTHROW(this_doesnt_throw());
|
||||
|
||||
CATCH_CHECK( 1 == 1 );
|
||||
CATCH_CHECK_FALSE( 1 != 1 );
|
||||
CATCH_CHECKED_IF( 1 == 1 ) {
|
||||
CATCH_SUCCEED("don't care");
|
||||
} CATCH_CHECKED_ELSE ( 1 == 1 ) {
|
||||
CATCH_SUCCEED("don't care");
|
||||
}
|
||||
|
||||
CATCH_CHECK_NOFAIL(1 == 2);
|
||||
|
||||
CATCH_CHECK_THROWS(this_throws());
|
||||
CATCH_CHECK_THROWS_AS(this_throws(), std::runtime_error);
|
||||
CATCH_CHECK_THROWS_WITH(this_throws(), "Some msg");
|
||||
CATCH_CHECK_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
|
||||
CATCH_CHECK_NOTHROW(this_doesnt_throw());
|
||||
|
||||
CATCH_REQUIRE_THAT("abcd", Equals("abcd"));
|
||||
CATCH_CHECK_THAT("bdef", Equals("bdef"));
|
||||
|
||||
CATCH_INFO( "some info" );
|
||||
CATCH_UNSCOPED_INFO( "some info" );
|
||||
CATCH_WARN( "some warn" );
|
||||
CATCH_SECTION("some section") {
|
||||
int i = 1;
|
||||
CATCH_CAPTURE( i );
|
||||
CATCH_DYNAMIC_SECTION("Dynamic section: " << i) {
|
||||
CATCH_FAIL_CHECK( "failure" );
|
||||
}
|
||||
}
|
||||
|
||||
CATCH_STATIC_REQUIRE( std::is_void<void>::value );
|
||||
CATCH_STATIC_REQUIRE_FALSE( std::is_void<int>::value );
|
||||
CATCH_FAIL("");
|
||||
}
|
||||
|
||||
// Missing:
|
||||
|
||||
//
|
||||
// #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
|
||||
// #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
|
||||
// #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
|
||||
//
|
||||
// // "BDD-style" convenience wrappers
|
||||
// #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
|
||||
// #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
|
||||
// #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
|
||||
// #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
|
||||
// #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
|
||||
// #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
|
||||
// #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
|
||||
//
|
31
tests/ExtraTests/X02-DisabledMacros.cpp
Normal file
31
tests/ExtraTests/X02-DisabledMacros.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// X02-DisabledMacros.cpp
|
||||
// Test that CATCH_CONFIG_DISABLE turns off TEST_CASE autoregistration
|
||||
// and expressions in assertion macros are not run.
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
||||
// CATCH_CONFIG_DISABLE also prevents reporter registration.
|
||||
// We need to manually register at least one reporter for our tests
|
||||
static Catch::ReporterRegistrar<Catch::ConsoleReporter> temporary( "console" );
|
||||
|
||||
#include <iostream>
|
||||
|
||||
struct foo {
|
||||
foo(){
|
||||
REQUIRE_NOTHROW( print() );
|
||||
}
|
||||
void print() const {
|
||||
std::cout << "This should not happen\n";
|
||||
}
|
||||
};
|
||||
|
||||
// Construct foo, but `foo::print` should not be run
|
||||
foo f;
|
||||
|
||||
// This test should not be run, because it won't be registered
|
||||
TEST_CASE( "Disabled Macros" ) {
|
||||
std::cout << "This should not happen\n";
|
||||
FAIL();
|
||||
}
|
23
tests/ExtraTests/X03-DisabledExceptions-DefaultHandler.cpp
Normal file
23
tests/ExtraTests/X03-DisabledExceptions-DefaultHandler.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Tests that run") {
|
||||
// All of these should be run and be reported
|
||||
CHECK(1 == 2);
|
||||
CHECK(1 == 1);
|
||||
CHECK(1 != 3);
|
||||
CHECK(1 == 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Tests that abort") {
|
||||
// Avoid abort and other exceptional exits -- there is no way
|
||||
// to tell CMake that abort is the desired outcome of a test.
|
||||
std::set_terminate([](){exit(1);});
|
||||
REQUIRE(1 == 1);
|
||||
REQUIRE(1 != 2);
|
||||
REQUIRE(1 == 3);
|
||||
// We should not get here, because the test above aborts
|
||||
REQUIRE(1 != 4);
|
||||
}
|
33
tests/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp
Normal file
33
tests/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#define CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace Catch {
|
||||
[[noreturn]]
|
||||
void throw_exception(std::exception const& e) {
|
||||
Catch::cerr() << "====== CUSTOM HANDLER ====== run terminates because an exception was thrown.\n"
|
||||
<< "The message was: " << e.what() << '\n';
|
||||
// Avoid abort and other exceptional exits -- there is no way
|
||||
// to tell CMake that abort is the desired outcome of a test.
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Tests that run") {
|
||||
// All of these should be run and be reported
|
||||
CHECK(1 == 2);
|
||||
CHECK(1 == 1);
|
||||
CHECK(1 != 3);
|
||||
CHECK(1 == 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Tests that abort") {
|
||||
REQUIRE(1 == 1);
|
||||
REQUIRE(1 != 2);
|
||||
REQUIRE(1 == 3);
|
||||
// We should not get here, because the test above aborts
|
||||
REQUIRE(1 != 4);
|
||||
}
|
23
tests/ExtraTests/X10-FallbackStringifier.cpp
Normal file
23
tests/ExtraTests/X10-FallbackStringifier.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
// X10-FallbackStringifier.cpp
|
||||
// Test that defining fallbackStringifier compiles
|
||||
|
||||
#include <string>
|
||||
|
||||
// A catch-all stringifier
|
||||
template <typename T>
|
||||
std::string fallbackStringifier(T const&) {
|
||||
return "{ !!! }";
|
||||
}
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
struct foo {
|
||||
explicit operator bool() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("aa") {
|
||||
REQUIRE(foo{});
|
||||
}
|
16
tests/ExtraTests/X11-DisableStringification.cpp
Normal file
16
tests/ExtraTests/X11-DisableStringification.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// X11-DisableStringification.cpp
|
||||
// Test that stringification of original expression can be disabled
|
||||
// this is a workaround for VS 2017 issue with Raw String literal
|
||||
// and preprocessor token pasting. In other words, hopefully this test
|
||||
// will be deleted soon :-)
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
struct Hidden {};
|
||||
|
||||
bool operator==(Hidden, Hidden) { return true; }
|
||||
|
||||
TEST_CASE("DisableStringification") {
|
||||
REQUIRE( Hidden{} == Hidden{} );
|
||||
}
|
133
tests/ExtraTests/X20-BenchmarkingMacros.cpp
Normal file
133
tests/ExtraTests/X20-BenchmarkingMacros.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// X20-BenchmarkingMacros.cpp
|
||||
// Test that the benchmarking support macros compile properly with the single header
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace {
|
||||
std::uint64_t factorial(std::uint64_t number) {
|
||||
if (number < 2) {
|
||||
return 1;
|
||||
}
|
||||
return number * factorial(number - 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Benchmark factorial", "[benchmark]") {
|
||||
CHECK(factorial(0) == 1);
|
||||
// some more asserts..
|
||||
CHECK(factorial(10) == 3628800);
|
||||
|
||||
BENCHMARK("factorial 10") {
|
||||
return factorial(10);
|
||||
};
|
||||
|
||||
CHECK(factorial(14) == 87178291200ull);
|
||||
BENCHMARK("factorial 14") {
|
||||
return factorial(14);
|
||||
};
|
||||
//
|
||||
// BENCHMARK("factorial 20") {
|
||||
// return factorial(20);
|
||||
// };
|
||||
//
|
||||
// BENCHMARK("factorial 35") {
|
||||
// return factorial(35);
|
||||
// };
|
||||
}
|
||||
|
||||
TEST_CASE("Benchmark containers", "[.][benchmark]") {
|
||||
static const int size = 100;
|
||||
|
||||
std::vector<int> v;
|
||||
std::map<int, int> m;
|
||||
|
||||
SECTION("without generator") {
|
||||
BENCHMARK("Load up a vector") {
|
||||
v = std::vector<int>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
v.push_back(i);
|
||||
};
|
||||
REQUIRE(v.size() == size);
|
||||
|
||||
// test optimizer control
|
||||
BENCHMARK("Add up a vector's content") {
|
||||
uint64_t add = 0;
|
||||
for (int i = 0; i < size; ++i)
|
||||
add += v[i];
|
||||
return add;
|
||||
};
|
||||
|
||||
BENCHMARK("Load up a map") {
|
||||
m = std::map<int, int>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
m.insert({ i, i + 1 });
|
||||
};
|
||||
REQUIRE(m.size() == size);
|
||||
|
||||
BENCHMARK("Reserved vector") {
|
||||
v = std::vector<int>();
|
||||
v.reserve(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v.push_back(i);
|
||||
};
|
||||
REQUIRE(v.size() == size);
|
||||
|
||||
BENCHMARK("Resized vector") {
|
||||
v = std::vector<int>();
|
||||
v.resize(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i] = i;
|
||||
};
|
||||
REQUIRE(v.size() == size);
|
||||
|
||||
int array[size];
|
||||
BENCHMARK("A fixed size array that should require no allocations") {
|
||||
for (int i = 0; i < size; ++i)
|
||||
array[i] = i;
|
||||
};
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; ++i)
|
||||
sum += array[i];
|
||||
REQUIRE(sum > size);
|
||||
|
||||
SECTION("XYZ") {
|
||||
|
||||
BENCHMARK_ADVANCED("Load up vector with chronometer")(Catch::Benchmark::Chronometer meter) {
|
||||
std::vector<int> k;
|
||||
meter.measure([&](int idx) {
|
||||
k = std::vector<int>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
k.push_back(idx);
|
||||
});
|
||||
REQUIRE(k.size() == size);
|
||||
};
|
||||
|
||||
int runs = 0;
|
||||
BENCHMARK("Fill vector indexed", benchmarkIndex) {
|
||||
v = std::vector<int>();
|
||||
v.resize(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i] = benchmarkIndex;
|
||||
runs = benchmarkIndex;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
REQUIRE(v[i] == runs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("with generator") {
|
||||
auto generated = GENERATE(range(0, 10));
|
||||
BENCHMARK("Fill vector generated") {
|
||||
v = std::vector<int>();
|
||||
v.resize(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i] = generated;
|
||||
};
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
REQUIRE(v[i] == generated);
|
||||
}
|
||||
}
|
||||
}
|
12
tests/ExtraTests/X90-WindowsHeaderInclusion.cpp
Normal file
12
tests/ExtraTests/X90-WindowsHeaderInclusion.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// X90-WindowsHeaderInclusion.cpp
|
||||
// Test that the Catch2 header compiles even after including windows.h
|
||||
// without defining NOMINMAX first. As an FYI, if you do that, you are
|
||||
// wrong.
|
||||
|
||||
#include <windows.h>
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Catch2 did survive compilation with windows.h", "[compile-test]") {
|
||||
SUCCEED();
|
||||
}
|
168
tests/SelfTest/Baselines/automake.std.approved.txt
Normal file
168
tests/SelfTest/Baselines/automake.std.approved.txt
Normal file
@@ -0,0 +1,168 @@
|
||||
:test-result: PASS # A test name that starts with a #
|
||||
:test-result: PASS #542
|
||||
:test-result: PASS #809
|
||||
:test-result: FAIL 'Not' checks that should fail
|
||||
:test-result: PASS 'Not' checks that should succeed
|
||||
:test-result: PASS (unimplemented) static bools can be evaluated
|
||||
:test-result: FAIL A METHOD_AS_TEST_CASE based test run that fails
|
||||
:test-result: PASS A METHOD_AS_TEST_CASE based test run that succeeds
|
||||
:test-result: FAIL A TEST_CASE_METHOD based test run that fails
|
||||
:test-result: PASS A TEST_CASE_METHOD based test run that succeeds
|
||||
:test-result: FAIL A couple of nested sections followed by a failure
|
||||
:test-result: FAIL A failing expression with a non streamable type is still captured
|
||||
:test-result: PASS AllOf matcher
|
||||
:test-result: PASS An empty test with no assertions
|
||||
:test-result: PASS An expression with side-effects should only be evaluated once
|
||||
:test-result: FAIL An unchecked exception reports the line of the last assertion
|
||||
:test-result: PASS Anonymous test case 1
|
||||
:test-result: PASS AnyOf matcher
|
||||
:test-result: PASS Approximate PI
|
||||
:test-result: PASS Approximate comparisons with different epsilons
|
||||
:test-result: PASS Approximate comparisons with floats
|
||||
:test-result: PASS Approximate comparisons with ints
|
||||
:test-result: PASS Approximate comparisons with mixed numeric types
|
||||
:test-result: PASS Assertions then sections
|
||||
:test-result: PASS Character pretty printing
|
||||
:test-result: PASS Comparing function pointers
|
||||
:test-result: PASS Comparing member function pointers
|
||||
:test-result: PASS Comparisons between ints where one side is computed
|
||||
:test-result: PASS Comparisons between unsigned ints and negative signed ints match c++ standard behaviour
|
||||
:test-result: PASS Comparisons with int literals don't warn when mixing signed/ unsigned
|
||||
:test-result: FAIL Contains string matcher
|
||||
:test-result: FAIL Custom exceptions can be translated when testing for nothrow
|
||||
:test-result: FAIL Custom exceptions can be translated when testing for throwing as something else
|
||||
:test-result: FAIL Custom std-exceptions can be custom translated
|
||||
:test-result: PASS Demonstrate that a non-const == is not used
|
||||
:test-result: FAIL EndsWith string matcher
|
||||
:test-result: XFAIL Equality checks that should fail
|
||||
:test-result: PASS Equality checks that should succeed
|
||||
:test-result: PASS Equals
|
||||
:test-result: FAIL Equals string matcher
|
||||
:test-result: PASS Exception messages can be tested for
|
||||
:test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test
|
||||
:test-result: FAIL FAIL aborts the test
|
||||
:test-result: FAIL FAIL does not require an argument
|
||||
:test-result: PASS Factorials are computed
|
||||
:test-result: PASS Generator over a range of pairs
|
||||
:test-result: PASS Generators over two ranges
|
||||
:test-result: PASS Greater-than inequalities with different epsilons
|
||||
:test-result: PASS INFO and WARN do not abort tests
|
||||
:test-result: FAIL INFO gets logged on failure
|
||||
:test-result: FAIL INFO gets logged on failure, even if captured before successful assertions
|
||||
:test-result: XFAIL Inequality checks that should fail
|
||||
:test-result: PASS Inequality checks that should succeed
|
||||
:test-result: PASS Less-than inequalities with different epsilons
|
||||
:test-result: PASS Long strings can be wrapped
|
||||
:test-result: PASS Long text is truncated
|
||||
:test-result: PASS ManuallyRegistered
|
||||
:test-result: PASS Matchers can be (AllOf) composed with the && operator
|
||||
:test-result: PASS Matchers can be (AnyOf) composed with the || operator
|
||||
:test-result: PASS Matchers can be composed with both && and ||
|
||||
:test-result: FAIL Matchers can be composed with both && and || - failing
|
||||
:test-result: PASS Matchers can be negated (Not) with the ! operator
|
||||
:test-result: FAIL Matchers can be negated (Not) with the ! operator - failing
|
||||
:test-result: FAIL Mismatching exception messages failing the test
|
||||
:test-result: PASS Nice descriptive name
|
||||
:test-result: FAIL Non-std exceptions can be translated
|
||||
:test-result: PASS NotImplemented exception
|
||||
:test-result: PASS Objects that evaluated in boolean contexts can be checked
|
||||
:test-result: PASS Operators at different namespace levels not hijacked by Koenig lookup
|
||||
:test-result: FAIL Ordering comparison checks that should fail
|
||||
:test-result: PASS Ordering comparison checks that should succeed
|
||||
:test-result: FAIL Output from all sections is reported
|
||||
:test-result: PASS Parse test names and tags
|
||||
:test-result: PASS Parsing a std::pair
|
||||
:test-result: PASS Pointers can be compared to null
|
||||
:test-result: PASS Pointers can be converted to strings
|
||||
:test-result: PASS Process can be configured on command line
|
||||
:test-result: FAIL SCOPED_INFO is reset for each loop
|
||||
:test-result: PASS SUCCEED counts as a test pass
|
||||
:test-result: PASS SUCCESS does not require an argument
|
||||
:test-result: PASS Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods
|
||||
:test-result: PASS Scenario: Do that thing with the thing
|
||||
:test-result: PASS Scenario: This is a really long scenario name to see how the list command deals with wrapping
|
||||
:test-result: PASS Scenario: Vector resizing affects size and capacity
|
||||
A string sent directly to stdout
|
||||
A string sent directly to stderr
|
||||
:test-result: PASS Sends stuff to stdout and stderr
|
||||
:test-result: PASS Some simple comparisons between doubles
|
||||
Message from section one
|
||||
Message from section two
|
||||
:test-result: PASS Standard output from all sections is reported
|
||||
:test-result: FAIL StartsWith string matcher
|
||||
:test-result: PASS String matchers
|
||||
hello
|
||||
hello
|
||||
:test-result: PASS Strings can be rendered with colour
|
||||
:test-result: FAIL Tabs and newlines show in output
|
||||
:test-result: PASS Tag alias can be registered against tag patterns
|
||||
:test-result: PASS Test case with one argument
|
||||
:test-result: PASS Test enum bit values
|
||||
:test-result: PASS Text can be formatted using the Text class
|
||||
:test-result: PASS The NO_FAIL macro reports a failure but does not fail the test
|
||||
:test-result: FAIL This test 'should' fail but doesn't
|
||||
:test-result: PASS Tracker
|
||||
:test-result: FAIL Unexpected exceptions can be translated
|
||||
:test-result: PASS Use a custom approx
|
||||
:test-result: PASS Variadic macros
|
||||
:test-result: PASS When checked exceptions are thrown they can be expected or unexpected
|
||||
:test-result: FAIL When unchecked exceptions are thrown directly they are always failures
|
||||
:test-result: FAIL When unchecked exceptions are thrown during a CHECK the test should continue
|
||||
:test-result: FAIL When unchecked exceptions are thrown during a REQUIRE the test should abort fail
|
||||
:test-result: FAIL When unchecked exceptions are thrown from functions they are always failures
|
||||
:test-result: FAIL When unchecked exceptions are thrown from sections they are always failures
|
||||
:test-result: PASS When unchecked exceptions are thrown, but caught, they do not affect the test
|
||||
:test-result: PASS Where the LHS is not a simple value
|
||||
:test-result: PASS Where there is more to the expression after the RHS
|
||||
:test-result: PASS X/level/0/a
|
||||
:test-result: PASS X/level/0/b
|
||||
:test-result: PASS X/level/1/a
|
||||
:test-result: PASS X/level/1/b
|
||||
:test-result: PASS XmlEncode
|
||||
:test-result: PASS atomic if
|
||||
:test-result: PASS boolean member
|
||||
:test-result: PASS checkedElse
|
||||
:test-result: FAIL checkedElse, failing
|
||||
:test-result: PASS checkedIf
|
||||
:test-result: FAIL checkedIf, failing
|
||||
:test-result: PASS comparisons between const int variables
|
||||
:test-result: PASS comparisons between int variables
|
||||
:test-result: PASS even more nested SECTION tests
|
||||
:test-result: PASS first tag
|
||||
spanner:test-result: PASS has printf
|
||||
:test-result: FAIL just failure
|
||||
:test-result: PASS just info
|
||||
:test-result: FAIL looped SECTION tests
|
||||
:test-result: FAIL looped tests
|
||||
:test-result: FAIL more nested SECTION tests
|
||||
:test-result: PASS nested SECTION tests
|
||||
:test-result: PASS non streamable - with conv. op
|
||||
:test-result: PASS not allowed
|
||||
:test-result: PASS null strings
|
||||
:test-result: PASS pair<pair<int,const char *,pair<std::string,int> > -> toString
|
||||
:test-result: PASS pointer to class
|
||||
:test-result: PASS random SECTION tests
|
||||
:test-result: PASS replaceInPlace
|
||||
:test-result: PASS second tag
|
||||
:test-result: FAIL send a single char to INFO
|
||||
:test-result: FAIL sends information to INFO
|
||||
:test-result: PASS std::pair<int,const std::string> -> toString
|
||||
:test-result: PASS std::pair<int,std::string> -> toString
|
||||
:test-result: PASS std::vector<std::pair<std::string,int> > -> toString
|
||||
:test-result: FAIL string literals of different sizes can be compared
|
||||
:test-result: PASS toString on const wchar_t const pointer returns the string contents
|
||||
:test-result: PASS toString on const wchar_t pointer returns the string contents
|
||||
:test-result: PASS toString on wchar_t const pointer returns the string contents
|
||||
:test-result: PASS toString on wchar_t returns the string contents
|
||||
:test-result: PASS toString( has_maker )
|
||||
:test-result: PASS toString( has_maker_and_toString )
|
||||
:test-result: PASS toString( has_toString )
|
||||
:test-result: PASS toString( vectors<has_maker )
|
||||
:test-result: SKIP toString( vectors<has_maker_and_toString )
|
||||
:test-result: SKIP toString( vectors<has_toString )
|
||||
:test-result: PASS toString(enum w/operator<<)
|
||||
:test-result: PASS toString(enum)
|
||||
:test-result: PASS vector<int> -> toString
|
||||
:test-result: PASS vector<string> -> toString
|
||||
:test-result: PASS vectors can be sized and resized
|
||||
:test-result: PASS xmlentitycheck
|
1794
tests/SelfTest/Baselines/compact.sw.approved.txt
Normal file
1794
tests/SelfTest/Baselines/compact.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
1385
tests/SelfTest/Baselines/console.std.approved.txt
Normal file
1385
tests/SelfTest/Baselines/console.std.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
13221
tests/SelfTest/Baselines/console.sw.approved.txt
Normal file
13221
tests/SelfTest/Baselines/console.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
382
tests/SelfTest/Baselines/console.swa4.approved.txt
Normal file
382
tests/SelfTest/Baselines/console.swa4.approved.txt
Normal file
@@ -0,0 +1,382 @@
|
||||
Filters: ~[!nonportable]~[!benchmark]~[approvals] *
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
<exe-name> is a <version> host application.
|
||||
Run with -? for options
|
||||
|
||||
Randomness seeded to: 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
# A test name that starts with a #
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
yay
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1005: Comparing pointer to int and long (NULL can be either on various
|
||||
systems)
|
||||
-------------------------------------------------------------------------------
|
||||
Decomposition.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Decomposition.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( fptr == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
Decomposition.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( fptr == 0l )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1027
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( y.v == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( 0 == y.v )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1027: Bitfields can be captured
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( y.v == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( 0 == y.v )
|
||||
with expansion:
|
||||
0 == 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1147
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( t1 == t2 )
|
||||
with expansion:
|
||||
{?} == {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( t1 != t2 )
|
||||
with expansion:
|
||||
{?} != {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( t1 < t2 )
|
||||
with expansion:
|
||||
{?} < {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( t1 > t2 )
|
||||
with expansion:
|
||||
{?} > {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( t1 <= t2 )
|
||||
with expansion:
|
||||
{?} <= {?}
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( t1 >= t2 )
|
||||
with expansion:
|
||||
{?} >= {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1175 - Hidden Test
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1238
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
with messages:
|
||||
uarr := "123"
|
||||
sarr := "456"
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
|
||||
with expansion:
|
||||
0 == 0
|
||||
with messages:
|
||||
uarr := "123"
|
||||
sarr := "456"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1245
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1319: Sections can have description (even if it is not saved
|
||||
SectionName
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1403
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( h1 == h2 )
|
||||
with expansion:
|
||||
[1403 helper] == [1403 helper]
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1455 - INFO and WARN can start with a linebreak
|
||||
-------------------------------------------------------------------------------
|
||||
Message.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Message.tests.cpp:<line number>: warning:
|
||||
|
||||
This info message starts with a linebreak
|
||||
|
||||
This warning message starts with a linebreak
|
||||
|
||||
|
||||
No assertions in test case '#1455 - INFO and WARN can start with a linebreak'
|
||||
|
||||
This would not be caught previously
|
||||
Nor would this
|
||||
-------------------------------------------------------------------------------
|
||||
#1514: stderr/stdout is not captured in tests aborted by an exception
|
||||
-------------------------------------------------------------------------------
|
||||
Tricky.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Tricky.tests.cpp:<line number>: FAILED:
|
||||
explicitly with message:
|
||||
1514
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#1548
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( std::is_same<TypeList<int>, TypeList<int>>::value )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
outside assertions
|
||||
-------------------------------------------------------------------------------
|
||||
Exception.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Exception.tests.cpp:<line number>: FAILED:
|
||||
due to unexpected exception with messages:
|
||||
answer := 42
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
inside REQUIRE_NOTHROW
|
||||
-------------------------------------------------------------------------------
|
||||
Exception.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Exception.tests.cpp:<line number>: FAILED:
|
||||
REQUIRE_NOTHROW( thisThrows() )
|
||||
due to unexpected exception with messages:
|
||||
answer := 42
|
||||
expected exception
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#748 - captures with unexpected exceptions
|
||||
inside REQUIRE_THROWS
|
||||
-------------------------------------------------------------------------------
|
||||
Exception.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Exception.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS( thisThrows() )
|
||||
with message:
|
||||
answer := 42
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#809
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( 42 == f )
|
||||
with expansion:
|
||||
42 == {?}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#833
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( a == t )
|
||||
with expansion:
|
||||
3 == 3
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
CHECK( a == t )
|
||||
with expansion:
|
||||
3 == 3
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THROWS( throws_int(true) )
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
CHECK_THROWS_AS( throws_int(true), int )
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_NOTHROW( throws_int(false) )
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") )
|
||||
with expansion:
|
||||
"aaa" ends with: "aaa"
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( templated_tests<int>(3) )
|
||||
with expansion:
|
||||
true
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#835 -- errno should not be touched by Catch
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: FAILED:
|
||||
CHECK( f() == 0 )
|
||||
with expansion:
|
||||
1 == 0
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( errno == 1 )
|
||||
with expansion:
|
||||
1 == 1
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#872
|
||||
-------------------------------------------------------------------------------
|
||||
Compilation.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Compilation.tests.cpp:<line number>: PASSED:
|
||||
REQUIRE( x == 4 )
|
||||
with expansion:
|
||||
{?} == 4
|
||||
with message:
|
||||
dummy := 0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 0
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 1
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 2
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 3
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#961 -- Dynamically created sections should all be reported
|
||||
Looped section 4
|
||||
-------------------------------------------------------------------------------
|
||||
Misc.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Misc.tests.cpp:<line number>: PASSED:
|
||||
with message:
|
||||
Everything is OK
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
'Not' checks that should fail
|
||||
-------------------------------------------------------------------------------
|
||||
Condition.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Condition.tests.cpp:<line number>: FAILED:
|
||||
CHECK( false != false )
|
||||
|
||||
Condition.tests.cpp:<line number>: FAILED:
|
||||
CHECK( true != true )
|
||||
|
||||
===============================================================================
|
||||
test cases: 20 | 15 passed | 3 failed | 2 failed as expected
|
||||
assertions: 43 | 36 passed | 4 failed | 3 failed as expected
|
||||
|
1712
tests/SelfTest/Baselines/junit.sw.approved.txt
Normal file
1712
tests/SelfTest/Baselines/junit.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
1725
tests/SelfTest/Baselines/sonarqube.sw.approved.txt
Normal file
1725
tests/SelfTest/Baselines/sonarqube.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
15802
tests/SelfTest/Baselines/xml.sw.approved.txt
Normal file
15802
tests/SelfTest/Baselines/xml.sw.approved.txt
Normal file
File diff suppressed because it is too large
Load Diff
13
tests/SelfTest/CompileTimePerfTests/10.tests.cpp
Normal file
13
tests/SelfTest/CompileTimePerfTests/10.tests.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// Include set of usage tests multiple times - for compile-time performance testing
|
||||
// (do not run)
|
||||
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
||||
#include "All.tests.cpp"
|
13
tests/SelfTest/CompileTimePerfTests/100.tests.cpp
Normal file
13
tests/SelfTest/CompileTimePerfTests/100.tests.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// Include set of usage tests multiple times - for compile-time performance testing
|
||||
// (do not run)
|
||||
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
||||
#include "10.tests.cpp"
|
15
tests/SelfTest/CompileTimePerfTests/All.tests.cpp
Normal file
15
tests/SelfTest/CompileTimePerfTests/All.tests.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// include set of usage tests into one file for compiler performance test purposes
|
||||
// This whole file can now be included multiple times in 10.tests.cpp, and *that*
|
||||
// file included multiple times (in 100.tests.cpp)
|
||||
|
||||
// Note that the intention is only for these files to be compiled. They will
|
||||
// fail at runtime due to the re-user of test case names
|
||||
|
||||
#include "../UsageTests/Approx.tests.cpp"
|
||||
#include "../UsageTests/BDD.tests.cpp"
|
||||
#include "../UsageTests/Class.tests.cpp"
|
||||
#include "../UsageTests/Compilation.tests.cpp"
|
||||
#include "../UsageTests/Condition.tests.cpp"
|
||||
#include "../UsageTests/Exception.tests.cpp"
|
||||
#include "../UsageTests/Matchers.tests.cpp"
|
||||
#include "../UsageTests/Misc.tests.cpp"
|
516
tests/SelfTest/IntrospectiveTests/CmdLine.tests.cpp
Normal file
516
tests/SelfTest/IntrospectiveTests/CmdLine.tests.cpp
Normal file
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Created by Phil on 13/5/2013.
|
||||
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_test_spec_parser.h>
|
||||
#include <catch2/catch_test_case_info.h>
|
||||
#include <catch2/catch_config.hpp>
|
||||
#include <catch2/catch_commandline.h>
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
auto fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCaseInfo("", { name, desc }, CATCH_INTERNAL_LINEINFO); }
|
||||
}
|
||||
|
||||
TEST_CASE( "Parse test names and tags" ) {
|
||||
|
||||
using Catch::parseTestSpec;
|
||||
using Catch::TestSpec;
|
||||
|
||||
auto tcA = fakeTestCase( "a" );
|
||||
auto tcB = fakeTestCase( "b", "[one][x]" );
|
||||
auto tcC = fakeTestCase( "longer name with spaces", "[two][three][.][x]" );
|
||||
auto tcD = fakeTestCase( "zlonger name with spacesz" );
|
||||
|
||||
SECTION( "Empty test spec should have no filters" ) {
|
||||
TestSpec spec;
|
||||
CHECK( spec.hasFilters() == false );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
}
|
||||
|
||||
SECTION( "Test spec from empty string should have no filters" ) {
|
||||
TestSpec spec = parseTestSpec( "" );
|
||||
CHECK( spec.hasFilters() == false );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
}
|
||||
|
||||
SECTION( "Test spec from just a comma should have no filters" ) {
|
||||
TestSpec spec = parseTestSpec( "," );
|
||||
CHECK( spec.hasFilters() == false );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
}
|
||||
|
||||
SECTION( "Test spec from name should have one filter" ) {
|
||||
TestSpec spec = parseTestSpec( "b" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
}
|
||||
|
||||
SECTION( "Test spec from quoted name should have one filter" ) {
|
||||
TestSpec spec = parseTestSpec( "\"b\"" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
}
|
||||
|
||||
SECTION( "Test spec from name should have one filter" ) {
|
||||
TestSpec spec = parseTestSpec( "b" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
}
|
||||
|
||||
SECTION( "Wildcard at the start" ) {
|
||||
TestSpec spec = parseTestSpec( "*spaces" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
CHECK( parseTestSpec( "*a" ).matches( *tcA ) == true );
|
||||
}
|
||||
SECTION( "Wildcard at the end" ) {
|
||||
TestSpec spec = parseTestSpec( "long*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
CHECK( parseTestSpec( "a*" ).matches( *tcA ) == true );
|
||||
}
|
||||
SECTION( "Wildcard at both ends" ) {
|
||||
TestSpec spec = parseTestSpec( "*name*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
CHECK( parseTestSpec( "*a*" ).matches( *tcA ) == true );
|
||||
}
|
||||
SECTION( "Redundant wildcard at the start" ) {
|
||||
TestSpec spec = parseTestSpec( "*a" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
}
|
||||
SECTION( "Redundant wildcard at the end" ) {
|
||||
TestSpec spec = parseTestSpec( "a*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
}
|
||||
SECTION( "Redundant wildcard at both ends" ) {
|
||||
TestSpec spec = parseTestSpec( "*a*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
}
|
||||
SECTION( "Wildcard at both ends, redundant at start" ) {
|
||||
TestSpec spec = parseTestSpec( "*longer*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
}
|
||||
SECTION( "Just wildcard" ) {
|
||||
TestSpec spec = parseTestSpec( "*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
}
|
||||
|
||||
SECTION( "Single tag" ) {
|
||||
TestSpec spec = parseTestSpec( "[one]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
}
|
||||
SECTION( "Single tag, two matches" ) {
|
||||
TestSpec spec = parseTestSpec( "[x]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
}
|
||||
SECTION( "Two tags" ) {
|
||||
TestSpec spec = parseTestSpec( "[two][x]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
}
|
||||
SECTION( "Two tags, spare separated" ) {
|
||||
TestSpec spec = parseTestSpec( "[two] [x]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
}
|
||||
SECTION( "Wildcarded name and tag" ) {
|
||||
TestSpec spec = parseTestSpec( "*name*[x]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "Single tag exclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "~[one]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
}
|
||||
SECTION( "One tag exclusion and one tag inclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "~[two][x]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
}
|
||||
SECTION( "One tag exclusion and one wldcarded name inclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "~[two]*name*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
}
|
||||
SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "exclude:[two]*name*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
}
|
||||
SECTION( "name exclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "~b" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
}
|
||||
SECTION( "wildcarded name exclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "~*name*" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "wildcarded name exclusion with tag inclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "~*name*,[three]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "exclude:*name*,[three]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == true );
|
||||
CHECK( spec.matches( *tcB ) == true );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "two wildcarded names" ) {
|
||||
TestSpec spec = parseTestSpec( "\"longer*\"\"*spaces\"" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == true );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "empty tag" ) {
|
||||
TestSpec spec = parseTestSpec( "[]" );
|
||||
CHECK( spec.hasFilters() == false );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "empty quoted name" ) {
|
||||
TestSpec spec = parseTestSpec( "\"\"" );
|
||||
CHECK( spec.hasFilters() == false );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == false );
|
||||
}
|
||||
SECTION( "quoted string followed by tag exclusion" ) {
|
||||
TestSpec spec = parseTestSpec( "\"*name*\"~[.]" );
|
||||
CHECK( spec.hasFilters() == true );
|
||||
CHECK( spec.matches( *tcA ) == false );
|
||||
CHECK( spec.matches( *tcB ) == false );
|
||||
CHECK( spec.matches( *tcC ) == false );
|
||||
CHECK( spec.matches( *tcD ) == true );
|
||||
}
|
||||
SECTION( "Leading and trailing spaces in test spec" ) {
|
||||
TestSpec spec = parseTestSpec( "\" aardvark \"" );
|
||||
CHECK( spec.matches( *fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( " aardvark" ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( "aardvark " ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( "aardvark" ) ) );
|
||||
|
||||
}
|
||||
SECTION( "Leading and trailing spaces in test name" ) {
|
||||
TestSpec spec = parseTestSpec( "aardvark" );
|
||||
CHECK( spec.matches( *fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( " aardvark" ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( " aardvark " ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( "aardvark " ) ) );
|
||||
CHECK( spec.matches( *fakeTestCase( "aardvark" ) ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) {
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
using namespace Catch::Matchers;
|
||||
#endif
|
||||
|
||||
Catch::ConfigData config;
|
||||
auto cli = Catch::makeCommandLineParser(config);
|
||||
|
||||
SECTION("empty args don't cause a crash") {
|
||||
auto result = cli.parse({""});
|
||||
CHECK(result);
|
||||
CHECK(config.processName == "");
|
||||
}
|
||||
|
||||
SECTION("default - no arguments") {
|
||||
auto result = cli.parse({"test"});
|
||||
CHECK(result);
|
||||
CHECK(config.processName == "test");
|
||||
CHECK(config.shouldDebugBreak == false);
|
||||
CHECK(config.abortAfter == -1);
|
||||
CHECK(config.noThrow == false);
|
||||
CHECK(config.reporterName == "console");
|
||||
|
||||
Catch::Config cfg(config);
|
||||
CHECK_FALSE(cfg.hasTestFilters());
|
||||
}
|
||||
|
||||
SECTION("test lists") {
|
||||
SECTION("Specify one test case using") {
|
||||
auto result = cli.parse({"test", "test1"});
|
||||
CHECK(result);
|
||||
|
||||
Catch::Config cfg(config);
|
||||
REQUIRE(cfg.hasTestFilters());
|
||||
REQUIRE(cfg.testSpec().matches(*fakeTestCase("notIncluded")) == false);
|
||||
REQUIRE(cfg.testSpec().matches(*fakeTestCase("test1")));
|
||||
}
|
||||
SECTION("Specify one test case exclusion using exclude:") {
|
||||
auto result = cli.parse({"test", "exclude:test1"});
|
||||
CHECK(result);
|
||||
|
||||
Catch::Config cfg(config);
|
||||
REQUIRE(cfg.hasTestFilters());
|
||||
REQUIRE(cfg.testSpec().matches(*fakeTestCase("test1")) == false);
|
||||
REQUIRE(cfg.testSpec().matches(*fakeTestCase("alwaysIncluded")));
|
||||
}
|
||||
|
||||
SECTION("Specify one test case exclusion using ~") {
|
||||
auto result = cli.parse({"test", "~test1"});
|
||||
CHECK(result);
|
||||
|
||||
Catch::Config cfg(config);
|
||||
REQUIRE(cfg.hasTestFilters());
|
||||
REQUIRE(cfg.testSpec().matches(*fakeTestCase("test1")) == false);
|
||||
REQUIRE(cfg.testSpec().matches(*fakeTestCase("alwaysIncluded")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SECTION("reporter") {
|
||||
SECTION("-r/console") {
|
||||
CHECK(cli.parse({"test", "-r", "console"}));
|
||||
|
||||
REQUIRE(config.reporterName == "console");
|
||||
}
|
||||
SECTION("-r/xml") {
|
||||
CHECK(cli.parse({"test", "-r", "xml"}));
|
||||
|
||||
REQUIRE(config.reporterName == "xml");
|
||||
}
|
||||
SECTION("--reporter/junit") {
|
||||
CHECK(cli.parse({"test", "--reporter", "junit"}));
|
||||
|
||||
REQUIRE(config.reporterName == "junit");
|
||||
}
|
||||
SECTION("Only one reporter is accepted") {
|
||||
REQUIRE_FALSE(cli.parse({ "test", "-r", "xml", "-r", "junit" }));
|
||||
}
|
||||
SECTION("must match one of the available ones") {
|
||||
auto result = cli.parse({"test", "--reporter", "unsupported"});
|
||||
CHECK(!result);
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
REQUIRE_THAT(result.errorMessage(), Contains("Unrecognized reporter"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("debugger") {
|
||||
SECTION("-b") {
|
||||
CHECK(cli.parse({"test", "-b"}));
|
||||
|
||||
REQUIRE(config.shouldDebugBreak == true);
|
||||
}
|
||||
SECTION("--break") {
|
||||
CHECK(cli.parse({"test", "--break"}));
|
||||
|
||||
REQUIRE(config.shouldDebugBreak);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SECTION("abort") {
|
||||
SECTION("-a aborts after first failure") {
|
||||
CHECK(cli.parse({"test", "-a"}));
|
||||
|
||||
REQUIRE(config.abortAfter == 1);
|
||||
}
|
||||
SECTION("-x 2 aborts after two failures") {
|
||||
CHECK(cli.parse({"test", "-x", "2"}));
|
||||
|
||||
REQUIRE(config.abortAfter == 2);
|
||||
}
|
||||
SECTION("-x must be numeric") {
|
||||
auto result = cli.parse({"test", "-x", "oops"});
|
||||
CHECK(!result);
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("nothrow") {
|
||||
SECTION("-e") {
|
||||
CHECK(cli.parse({"test", "-e"}));
|
||||
|
||||
REQUIRE(config.noThrow);
|
||||
}
|
||||
SECTION("--nothrow") {
|
||||
CHECK(cli.parse({"test", "--nothrow"}));
|
||||
|
||||
REQUIRE(config.noThrow);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("output filename") {
|
||||
SECTION("-o filename") {
|
||||
CHECK(cli.parse({"test", "-o", "filename.ext"}));
|
||||
|
||||
REQUIRE(config.outputFilename == "filename.ext");
|
||||
}
|
||||
SECTION("--out") {
|
||||
CHECK(cli.parse({"test", "--out", "filename.ext"}));
|
||||
|
||||
REQUIRE(config.outputFilename == "filename.ext");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("combinations") {
|
||||
SECTION("Single character flags can be combined") {
|
||||
CHECK(cli.parse({"test", "-abe"}));
|
||||
|
||||
CHECK(config.abortAfter == 1);
|
||||
CHECK(config.shouldDebugBreak);
|
||||
CHECK(config.noThrow == true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SECTION( "use-colour") {
|
||||
|
||||
using Catch::UseColour;
|
||||
|
||||
SECTION( "without option" ) {
|
||||
CHECK(cli.parse({"test"}));
|
||||
|
||||
REQUIRE( config.useColour == UseColour::Auto );
|
||||
}
|
||||
|
||||
SECTION( "auto" ) {
|
||||
CHECK(cli.parse({"test", "--use-colour", "auto"}));
|
||||
|
||||
REQUIRE( config.useColour == UseColour::Auto );
|
||||
}
|
||||
|
||||
SECTION( "yes" ) {
|
||||
CHECK(cli.parse({"test", "--use-colour", "yes"}));
|
||||
|
||||
REQUIRE( config.useColour == UseColour::Yes );
|
||||
}
|
||||
|
||||
SECTION( "no" ) {
|
||||
CHECK(cli.parse({"test", "--use-colour", "no"}));
|
||||
|
||||
REQUIRE( config.useColour == UseColour::No );
|
||||
}
|
||||
|
||||
SECTION( "error" ) {
|
||||
auto result = cli.parse({"test", "--use-colour", "wrong"});
|
||||
CHECK( !result );
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Benchmark options") {
|
||||
SECTION("samples") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-samples=200" }));
|
||||
|
||||
REQUIRE(config.benchmarkSamples == 200);
|
||||
}
|
||||
|
||||
SECTION("resamples") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-resamples=20000" }));
|
||||
|
||||
REQUIRE(config.benchmarkResamples == 20000);
|
||||
}
|
||||
|
||||
SECTION("resamples") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-confidence-interval=0.99" }));
|
||||
|
||||
REQUIRE(config.benchmarkConfidenceInterval == Catch::Detail::Approx(0.99));
|
||||
}
|
||||
|
||||
SECTION("resamples") {
|
||||
CHECK(cli.parse({ "test", "--benchmark-no-analysis" }));
|
||||
|
||||
REQUIRE(config.benchmarkNoAnalysis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test with special, characters \"in name", "[cli][regression]") {
|
||||
// This test case succeeds if we can invoke it from the CLI
|
||||
SUCCEED();
|
||||
}
|
23
tests/SelfTest/IntrospectiveTests/Details.tests.cpp
Normal file
23
tests/SelfTest/IntrospectiveTests/Details.tests.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4702) // unreachable code in the macro expansions
|
||||
#endif
|
||||
|
||||
TEST_CASE("Check that our error handling macros throw the right exceptions", "[!throws][internals][approvals]") {
|
||||
REQUIRE_THROWS_AS(CATCH_INTERNAL_ERROR(""), std::logic_error);
|
||||
REQUIRE_THROWS_AS(CATCH_ERROR(""), std::domain_error);
|
||||
REQUIRE_THROWS_AS(CATCH_RUNTIME_ERROR(""), std::runtime_error);
|
||||
REQUIRE_THROWS_AS([](){CATCH_ENFORCE(false, "");}(), std::domain_error);
|
||||
REQUIRE_NOTHROW([](){CATCH_ENFORCE(true, "");}());
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop) // unreachable code in the macro expansions
|
||||
#endif
|
337
tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
Normal file
337
tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
Normal file
@@ -0,0 +1,337 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
// Tests of generator implementation details
|
||||
TEST_CASE("Generators internals", "[generators][internals]") {
|
||||
using namespace Catch::Generators;
|
||||
|
||||
SECTION("Single value") {
|
||||
auto gen = value(123);
|
||||
REQUIRE(gen.get() == 123);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Preset values") {
|
||||
auto gen = values({ 1, 3, 5 });
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 3);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 5);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Generator combinator") {
|
||||
auto gen = makeGenerators(1, 5, values({ 2, 4 }), 0);
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 5);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 4);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 0);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Explicitly typed generator sequence") {
|
||||
auto gen = makeGenerators(as<std::string>{}, "aa", "bb", "cc");
|
||||
// This just checks that the type is std::string:
|
||||
REQUIRE(gen.get().size() == 2);
|
||||
// Iterate over the generator
|
||||
REQUIRE(gen.get() == "aa");
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == "bb");
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == "cc");
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Filter generator") {
|
||||
// Normal usage
|
||||
auto gen = filter([] (int i) { return i != 2; }, values({ 2, 1, 2, 3, 2, 2 }));
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 3);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
|
||||
// Completely filtered-out generator should throw on construction
|
||||
REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), Catch::GeneratorException);
|
||||
}
|
||||
SECTION("Take generator") {
|
||||
SECTION("Take less") {
|
||||
auto gen = take(2, values({ 1, 2, 3 }));
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Take more") {
|
||||
auto gen = take(2, value(1));
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
SECTION("Map with explicit return type") {
|
||||
auto gen = map<double>([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
|
||||
REQUIRE(gen.get() == 2.0);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 4.0);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 6.0);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Map with deduced return type") {
|
||||
auto gen = map([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
|
||||
REQUIRE(gen.get() == 2.0);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 4.0);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 6.0);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Repeat") {
|
||||
SECTION("Singular repeat") {
|
||||
auto gen = repeat(1, value(3));
|
||||
REQUIRE(gen.get() == 3);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Actual repeat") {
|
||||
auto gen = repeat(2, values({ 1, 2, 3 }));
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 3);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 3);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
SECTION("Range") {
|
||||
SECTION("Positive auto step") {
|
||||
SECTION("Integer") {
|
||||
auto gen = range(-2, 2);
|
||||
REQUIRE(gen.get() == -2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 0);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
SECTION("Negative auto step") {
|
||||
SECTION("Integer") {
|
||||
auto gen = range(2, -2);
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 0);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
SECTION("Positive manual step") {
|
||||
SECTION("Integer") {
|
||||
SECTION("Exact") {
|
||||
auto gen = range(-7, 5, 3);
|
||||
REQUIRE(gen.get() == -7);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -4);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Slightly over end") {
|
||||
auto gen = range(-7, 4, 3);
|
||||
REQUIRE(gen.get() == -7);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -4);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Slightly under end") {
|
||||
auto gen = range(-7, 6, 3);
|
||||
REQUIRE(gen.get() == -7);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -4);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 5);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Floating Point") {
|
||||
SECTION("Exact") {
|
||||
const auto rangeStart = -1.;
|
||||
const auto rangeEnd = 1.;
|
||||
const auto step = .1;
|
||||
|
||||
auto gen = range(rangeStart, rangeEnd, step);
|
||||
auto expected = rangeStart;
|
||||
while( (rangeEnd - expected) > step ) {
|
||||
INFO( "Current expected value is " << expected );
|
||||
REQUIRE(gen.get() == Approx(expected));
|
||||
REQUIRE(gen.next());
|
||||
|
||||
expected += step;
|
||||
}
|
||||
REQUIRE(gen.get() == Approx( rangeEnd ) );
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Slightly over end") {
|
||||
const auto rangeStart = -1.;
|
||||
const auto rangeEnd = 1.;
|
||||
const auto step = .3;
|
||||
|
||||
auto gen = range(rangeStart, rangeEnd, step);
|
||||
auto expected = rangeStart;
|
||||
while( (rangeEnd - expected) > step ) {
|
||||
INFO( "Current expected value is " << expected );
|
||||
REQUIRE(gen.get() == Approx(expected));
|
||||
REQUIRE(gen.next());
|
||||
|
||||
expected += step;
|
||||
}
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Slightly under end") {
|
||||
const auto rangeStart = -1.;
|
||||
const auto rangeEnd = .9;
|
||||
const auto step = .3;
|
||||
|
||||
auto gen = range(rangeStart, rangeEnd, step);
|
||||
auto expected = rangeStart;
|
||||
while( (rangeEnd - expected) > step ) {
|
||||
INFO( "Current expected value is " << expected );
|
||||
REQUIRE(gen.get() == Approx(expected));
|
||||
REQUIRE(gen.next());
|
||||
|
||||
expected += step;
|
||||
}
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
SECTION("Negative manual step") {
|
||||
SECTION("Integer") {
|
||||
SECTION("Exact") {
|
||||
auto gen = range(5, -7, -3);
|
||||
REQUIRE(gen.get() == 5);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -4);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Slightly over end") {
|
||||
auto gen = range(5, -6, -3);
|
||||
REQUIRE(gen.get() == 5);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -4);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
SECTION("Slightly under end") {
|
||||
auto gen = range(5, -8, -3);
|
||||
REQUIRE(gen.get() == 5);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == 2);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -1);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -4);
|
||||
REQUIRE(gen.next());
|
||||
REQUIRE(gen.get() == -7);
|
||||
REQUIRE_FALSE(gen.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// todo: uncopyable type used in a generator
|
||||
// idea: uncopyable tag type for a stupid generator
|
||||
|
||||
namespace {
|
||||
struct non_copyable {
|
||||
non_copyable() = default;
|
||||
non_copyable(non_copyable const&) = delete;
|
||||
non_copyable& operator=(non_copyable const&) = delete;
|
||||
int value = -1;
|
||||
};
|
||||
|
||||
// This class shows how to implement a simple generator for Catch tests
|
||||
class TestGen : public Catch::Generators::IGenerator<int> {
|
||||
int current_number;
|
||||
public:
|
||||
|
||||
TestGen(non_copyable const& nc):
|
||||
current_number(nc.value) {}
|
||||
|
||||
int const& get() const override;
|
||||
bool next() override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Avoids -Wweak-vtables
|
||||
int const& TestGen::get() const {
|
||||
return current_number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("GENERATE capture macros", "[generators][internals][approvals]") {
|
||||
auto value = GENERATE(take(10, random(0, 10)));
|
||||
|
||||
non_copyable nc; nc.value = value;
|
||||
// neither `GENERATE_COPY` nor plain `GENERATE` would compile here
|
||||
auto value2 = GENERATE_REF(Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new TestGen(nc))));
|
||||
REQUIRE(value == value2);
|
||||
}
|
||||
|
||||
TEST_CASE("Multiple random generators in one test case output different values", "[generators][internals][approvals]") {
|
||||
SECTION("Integer") {
|
||||
auto random1 = Catch::Generators::random(0, 1000);
|
||||
auto random2 = Catch::Generators::random(0, 1000);
|
||||
size_t same = 0;
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
same += random1.get() == random2.get();
|
||||
random1.next(); random2.next();
|
||||
}
|
||||
// 0.5% seems like a sane bound for random identical elements within 1000 runs
|
||||
REQUIRE(same < 5);
|
||||
}
|
||||
SECTION("Float") {
|
||||
auto random1 = Catch::Generators::random(0., 1000.);
|
||||
auto random2 = Catch::Generators::random(0., 1000.);
|
||||
size_t same = 0;
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
same += random1.get() == random2.get();
|
||||
random1.next(); random2.next();
|
||||
}
|
||||
// 0.5% seems like a sane bound for random identical elements within 1000 runs
|
||||
REQUIRE(same < 5);
|
||||
}
|
||||
}
|
405
tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp
Normal file
405
tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Created by Joachim on 16/04/2019.
|
||||
* Adapted from donated nonius code.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||
namespace {
|
||||
struct manual_clock {
|
||||
public:
|
||||
using duration = std::chrono::nanoseconds;
|
||||
using time_point = std::chrono::time_point<manual_clock, duration>;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
enum { is_steady = true };
|
||||
|
||||
static time_point now() {
|
||||
return time_point(duration(tick()));
|
||||
}
|
||||
|
||||
static void advance(int ticks = 1) {
|
||||
tick() += ticks;
|
||||
}
|
||||
|
||||
private:
|
||||
static rep& tick() {
|
||||
static rep the_tick = 0;
|
||||
return the_tick;
|
||||
}
|
||||
};
|
||||
|
||||
struct counting_clock {
|
||||
public:
|
||||
using duration = std::chrono::nanoseconds;
|
||||
using time_point = std::chrono::time_point<counting_clock, duration>;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
enum { is_steady = true };
|
||||
|
||||
static time_point now() {
|
||||
static rep ticks = 0;
|
||||
return time_point(duration(ticks += rate()));
|
||||
}
|
||||
|
||||
static void set_rate(rep new_rate) { rate() = new_rate; }
|
||||
|
||||
private:
|
||||
static rep& rate() {
|
||||
static rep the_rate = 1;
|
||||
return the_rate;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestChronometerModel : Catch::Benchmark::Detail::ChronometerConcept {
|
||||
int started = 0;
|
||||
int finished = 0;
|
||||
|
||||
void start() override { ++started; }
|
||||
void finish() override { ++finished; }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("warmup", "[benchmark]") {
|
||||
auto rate = 1000;
|
||||
counting_clock::set_rate(rate);
|
||||
|
||||
auto start = counting_clock::now();
|
||||
auto iterations = Catch::Benchmark::Detail::warmup<counting_clock>();
|
||||
auto end = counting_clock::now();
|
||||
|
||||
REQUIRE((iterations * rate) > Catch::Benchmark::Detail::warmup_time.count());
|
||||
REQUIRE((end - start) > Catch::Benchmark::Detail::warmup_time);
|
||||
}
|
||||
|
||||
TEST_CASE("resolution", "[benchmark]") {
|
||||
auto rate = 1000;
|
||||
counting_clock::set_rate(rate);
|
||||
|
||||
size_t count = 10;
|
||||
auto res = Catch::Benchmark::Detail::resolution<counting_clock>(static_cast<int>(count));
|
||||
|
||||
REQUIRE(res.size() == count);
|
||||
|
||||
for (size_t i = 1; i < count; ++i) {
|
||||
REQUIRE(res[i] == rate);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("estimate_clock_resolution", "[benchmark]") {
|
||||
auto rate = 1000;
|
||||
counting_clock::set_rate(rate);
|
||||
|
||||
int iters = 160000;
|
||||
auto res = Catch::Benchmark::Detail::estimate_clock_resolution<counting_clock>(iters);
|
||||
|
||||
REQUIRE(res.mean.count() == rate);
|
||||
REQUIRE(res.outliers.total() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("benchmark function call", "[benchmark]") {
|
||||
SECTION("without chronometer") {
|
||||
auto called = 0;
|
||||
auto model = TestChronometerModel{};
|
||||
auto meter = Catch::Benchmark::Chronometer{ model, 1 };
|
||||
auto fn = Catch::Benchmark::Detail::BenchmarkFunction{ [&] {
|
||||
CHECK(model.started == 1);
|
||||
CHECK(model.finished == 0);
|
||||
++called;
|
||||
} };
|
||||
|
||||
fn(meter);
|
||||
|
||||
CHECK(model.started == 1);
|
||||
CHECK(model.finished == 1);
|
||||
CHECK(called == 1);
|
||||
}
|
||||
|
||||
SECTION("with chronometer") {
|
||||
auto called = 0;
|
||||
auto model = TestChronometerModel{};
|
||||
auto meter = Catch::Benchmark::Chronometer{ model, 1 };
|
||||
auto fn = Catch::Benchmark::Detail::BenchmarkFunction{ [&](Catch::Benchmark::Chronometer) {
|
||||
CHECK(model.started == 0);
|
||||
CHECK(model.finished == 0);
|
||||
++called;
|
||||
} };
|
||||
|
||||
fn(meter);
|
||||
|
||||
CHECK(model.started == 0);
|
||||
CHECK(model.finished == 0);
|
||||
CHECK(called == 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("uniform samples", "[benchmark]") {
|
||||
std::vector<double> samples(100);
|
||||
std::fill(samples.begin(), samples.end(), 23);
|
||||
|
||||
using it = std::vector<double>::iterator;
|
||||
auto e = Catch::Benchmark::Detail::bootstrap(0.95, samples.begin(), samples.end(), samples, [](it a, it b) {
|
||||
auto sum = std::accumulate(a, b, 0.);
|
||||
return sum / (b - a);
|
||||
});
|
||||
CHECK(e.point == 23);
|
||||
CHECK(e.upper_bound == 23);
|
||||
CHECK(e.lower_bound == 23);
|
||||
CHECK(e.confidence_interval == 0.95);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("normal_cdf", "[benchmark]") {
|
||||
using Catch::Benchmark::Detail::normal_cdf;
|
||||
CHECK(normal_cdf(0.000000) == Approx(0.50000000000000000));
|
||||
CHECK(normal_cdf(1.000000) == Approx(0.84134474606854293));
|
||||
CHECK(normal_cdf(-1.000000) == Approx(0.15865525393145705));
|
||||
CHECK(normal_cdf(2.809729) == Approx(0.99752083845315409));
|
||||
CHECK(normal_cdf(-1.352570) == Approx(0.08809652095066035));
|
||||
}
|
||||
|
||||
TEST_CASE("erfc_inv", "[benchmark]") {
|
||||
using Catch::Benchmark::Detail::erfc_inv;
|
||||
CHECK(erfc_inv(1.103560) == Approx(-0.09203687623843015));
|
||||
CHECK(erfc_inv(1.067400) == Approx(-0.05980291115763361));
|
||||
CHECK(erfc_inv(0.050000) == Approx(1.38590382434967796));
|
||||
}
|
||||
|
||||
TEST_CASE("normal_quantile", "[benchmark]") {
|
||||
using Catch::Benchmark::Detail::normal_quantile;
|
||||
CHECK(normal_quantile(0.551780) == Approx(0.13015979861484198));
|
||||
CHECK(normal_quantile(0.533700) == Approx(0.08457408802851875));
|
||||
CHECK(normal_quantile(0.025000) == Approx(-1.95996398454005449));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("mean", "[benchmark]") {
|
||||
std::vector<double> x{ 10., 20., 14., 16., 30., 24. };
|
||||
|
||||
auto m = Catch::Benchmark::Detail::mean(x.begin(), x.end());
|
||||
|
||||
REQUIRE(m == 19.);
|
||||
}
|
||||
|
||||
TEST_CASE("weighted_average_quantile", "[benchmark]") {
|
||||
std::vector<double> x{ 10., 20., 14., 16., 30., 24. };
|
||||
|
||||
auto q1 = Catch::Benchmark::Detail::weighted_average_quantile(1, 4, x.begin(), x.end());
|
||||
auto med = Catch::Benchmark::Detail::weighted_average_quantile(1, 2, x.begin(), x.end());
|
||||
auto q3 = Catch::Benchmark::Detail::weighted_average_quantile(3, 4, x.begin(), x.end());
|
||||
|
||||
REQUIRE(q1 == 14.5);
|
||||
REQUIRE(med == 18.);
|
||||
REQUIRE(q3 == 23.);
|
||||
}
|
||||
|
||||
TEST_CASE("classify_outliers", "[benchmark]") {
|
||||
auto require_outliers = [](Catch::Benchmark::OutlierClassification o, int los, int lom, int him, int his) {
|
||||
REQUIRE(o.low_severe == los);
|
||||
REQUIRE(o.low_mild == lom);
|
||||
REQUIRE(o.high_mild == him);
|
||||
REQUIRE(o.high_severe == his);
|
||||
REQUIRE(o.total() == los + lom + him + his);
|
||||
};
|
||||
|
||||
SECTION("none") {
|
||||
std::vector<double> x{ 10., 20., 14., 16., 30., 24. };
|
||||
|
||||
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
|
||||
|
||||
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
|
||||
require_outliers(o, 0, 0, 0, 0);
|
||||
}
|
||||
SECTION("low severe") {
|
||||
std::vector<double> x{ -12., 20., 14., 16., 30., 24. };
|
||||
|
||||
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
|
||||
|
||||
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
|
||||
require_outliers(o, 1, 0, 0, 0);
|
||||
}
|
||||
SECTION("low mild") {
|
||||
std::vector<double> x{ 1., 20., 14., 16., 30., 24. };
|
||||
|
||||
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
|
||||
|
||||
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
|
||||
require_outliers(o, 0, 1, 0, 0);
|
||||
}
|
||||
SECTION("high mild") {
|
||||
std::vector<double> x{ 10., 20., 14., 16., 36., 24. };
|
||||
|
||||
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
|
||||
|
||||
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
|
||||
require_outliers(o, 0, 0, 1, 0);
|
||||
}
|
||||
SECTION("high severe") {
|
||||
std::vector<double> x{ 10., 20., 14., 16., 49., 24. };
|
||||
|
||||
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
|
||||
|
||||
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
|
||||
require_outliers(o, 0, 0, 0, 1);
|
||||
}
|
||||
SECTION("mixed") {
|
||||
std::vector<double> x{ -20., 20., 14., 16., 39., 24. };
|
||||
|
||||
auto o = Catch::Benchmark::Detail::classify_outliers(x.begin(), x.end());
|
||||
|
||||
REQUIRE(o.samples_seen == static_cast<int>(x.size()));
|
||||
require_outliers(o, 1, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("analyse", "[benchmark]") {
|
||||
Catch::ConfigData data{};
|
||||
data.benchmarkConfidenceInterval = 0.95;
|
||||
data.benchmarkNoAnalysis = false;
|
||||
data.benchmarkResamples = 1000;
|
||||
data.benchmarkSamples = 99;
|
||||
Catch::Config config{data};
|
||||
|
||||
using Duration = Catch::Benchmark::FloatDuration<Catch::Benchmark::default_clock>;
|
||||
|
||||
Catch::Benchmark::Environment<Duration> env;
|
||||
std::vector<Duration> samples(99);
|
||||
for (size_t i = 0; i < samples.size(); ++i) {
|
||||
samples[i] = Duration(23 + (i % 3 - 1));
|
||||
}
|
||||
|
||||
auto analysis = Catch::Benchmark::Detail::analyse(config, env, samples.begin(), samples.end());
|
||||
CHECK(analysis.mean.point.count() == 23);
|
||||
CHECK(analysis.mean.lower_bound.count() < 23);
|
||||
CHECK(analysis.mean.lower_bound.count() > 22);
|
||||
CHECK(analysis.mean.upper_bound.count() > 23);
|
||||
CHECK(analysis.mean.upper_bound.count() < 24);
|
||||
|
||||
CHECK(analysis.standard_deviation.point.count() > 0.5);
|
||||
CHECK(analysis.standard_deviation.point.count() < 1);
|
||||
CHECK(analysis.standard_deviation.lower_bound.count() > 0.5);
|
||||
CHECK(analysis.standard_deviation.lower_bound.count() < 1);
|
||||
CHECK(analysis.standard_deviation.upper_bound.count() > 0.5);
|
||||
CHECK(analysis.standard_deviation.upper_bound.count() < 1);
|
||||
|
||||
CHECK(analysis.outliers.total() == 0);
|
||||
CHECK(analysis.outliers.low_mild == 0);
|
||||
CHECK(analysis.outliers.low_severe == 0);
|
||||
CHECK(analysis.outliers.high_mild == 0);
|
||||
CHECK(analysis.outliers.high_severe == 0);
|
||||
CHECK(analysis.outliers.samples_seen == samples.size());
|
||||
|
||||
CHECK(analysis.outlier_variance < 0.5);
|
||||
CHECK(analysis.outlier_variance > 0);
|
||||
}
|
||||
|
||||
TEST_CASE("analyse no analysis", "[benchmark]") {
|
||||
Catch::ConfigData data{};
|
||||
data.benchmarkConfidenceInterval = 0.95;
|
||||
data.benchmarkNoAnalysis = true;
|
||||
data.benchmarkResamples = 1000;
|
||||
data.benchmarkSamples = 99;
|
||||
Catch::Config config{ data };
|
||||
|
||||
using Duration = Catch::Benchmark::FloatDuration<Catch::Benchmark::default_clock>;
|
||||
|
||||
Catch::Benchmark::Environment<Duration> env;
|
||||
std::vector<Duration> samples(99);
|
||||
for (size_t i = 0; i < samples.size(); ++i) {
|
||||
samples[i] = Duration(23 + (i % 3 - 1));
|
||||
}
|
||||
|
||||
auto analysis = Catch::Benchmark::Detail::analyse(config, env, samples.begin(), samples.end());
|
||||
CHECK(analysis.mean.point.count() == 23);
|
||||
CHECK(analysis.mean.lower_bound.count() == 23);
|
||||
CHECK(analysis.mean.upper_bound.count() == 23);
|
||||
|
||||
CHECK(analysis.standard_deviation.point.count() == 0);
|
||||
CHECK(analysis.standard_deviation.lower_bound.count() == 0);
|
||||
CHECK(analysis.standard_deviation.upper_bound.count() == 0);
|
||||
|
||||
CHECK(analysis.outliers.total() == 0);
|
||||
CHECK(analysis.outliers.low_mild == 0);
|
||||
CHECK(analysis.outliers.low_severe == 0);
|
||||
CHECK(analysis.outliers.high_mild == 0);
|
||||
CHECK(analysis.outliers.high_severe == 0);
|
||||
CHECK(analysis.outliers.samples_seen == 0);
|
||||
|
||||
CHECK(analysis.outlier_variance == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("run_for_at_least, int", "[benchmark]") {
|
||||
manual_clock::duration time(100);
|
||||
|
||||
int old_x = 1;
|
||||
auto Timing = Catch::Benchmark::Detail::run_for_at_least<manual_clock>(time, 1, [&old_x](int x) -> int {
|
||||
CHECK(x >= old_x);
|
||||
manual_clock::advance(x);
|
||||
old_x = x;
|
||||
return x + 17;
|
||||
});
|
||||
|
||||
REQUIRE(Timing.elapsed >= time);
|
||||
REQUIRE(Timing.result == Timing.iterations + 17);
|
||||
REQUIRE(Timing.iterations >= time.count());
|
||||
}
|
||||
|
||||
TEST_CASE("run_for_at_least, chronometer", "[benchmark]") {
|
||||
manual_clock::duration time(100);
|
||||
|
||||
int old_runs = 1;
|
||||
auto Timing = Catch::Benchmark::Detail::run_for_at_least<manual_clock>(time, 1, [&old_runs](Catch::Benchmark::Chronometer meter) -> int {
|
||||
CHECK(meter.runs() >= old_runs);
|
||||
manual_clock::advance(100);
|
||||
meter.measure([] {
|
||||
manual_clock::advance(1);
|
||||
});
|
||||
old_runs = meter.runs();
|
||||
return meter.runs() + 17;
|
||||
});
|
||||
|
||||
REQUIRE(Timing.elapsed >= time);
|
||||
REQUIRE(Timing.result == Timing.iterations + 17);
|
||||
REQUIRE(Timing.iterations >= time.count());
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("measure", "[benchmark]") {
|
||||
auto r = Catch::Benchmark::Detail::measure<manual_clock>([](int x) -> int {
|
||||
CHECK(x == 17);
|
||||
manual_clock::advance(42);
|
||||
return 23;
|
||||
}, 17);
|
||||
auto s = Catch::Benchmark::Detail::measure<manual_clock>([](int x) -> int {
|
||||
CHECK(x == 23);
|
||||
manual_clock::advance(69);
|
||||
return 17;
|
||||
}, 23);
|
||||
|
||||
CHECK(r.elapsed.count() == 42);
|
||||
CHECK(r.result == 23);
|
||||
CHECK(r.iterations == 1);
|
||||
|
||||
CHECK(s.elapsed.count() == 69);
|
||||
CHECK(s.result == 17);
|
||||
CHECK(s.iterations == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("run benchmark", "[benchmark]") {
|
||||
counting_clock::set_rate(1000);
|
||||
auto start = counting_clock::now();
|
||||
|
||||
Catch::Benchmark::Benchmark bench{ "Test Benchmark", [](Catch::Benchmark::Chronometer meter) {
|
||||
counting_clock::set_rate(100000);
|
||||
meter.measure([] { return counting_clock::now(); });
|
||||
} };
|
||||
|
||||
bench.run<counting_clock>();
|
||||
auto end = counting_clock::now();
|
||||
|
||||
CHECK((end - start).count() == 2867251000);
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
206
tests/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
Normal file
206
tests/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Created by Phil on 1/10/2015.
|
||||
* Copyright 2015 Two Blue Cubes Ltd
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_test_case_tracker.h>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
using namespace Catch;
|
||||
|
||||
namespace {
|
||||
Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) {
|
||||
return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Tracker" ) {
|
||||
|
||||
TrackerContext ctx;
|
||||
ctx.startRun();
|
||||
ctx.startCycle();
|
||||
|
||||
|
||||
ITracker& testCase = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
||||
REQUIRE( testCase.isOpen() );
|
||||
|
||||
ITracker& s1 = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
||||
REQUIRE( s1.isOpen() );
|
||||
|
||||
SECTION( "successfully close one section" ) {
|
||||
s1.close();
|
||||
REQUIRE( s1.isSuccessfullyCompleted() );
|
||||
REQUIRE( testCase.isComplete() == false );
|
||||
|
||||
testCase.close();
|
||||
REQUIRE( ctx.completedCycle() );
|
||||
REQUIRE( testCase.isSuccessfullyCompleted() );
|
||||
}
|
||||
|
||||
SECTION( "fail one section" ) {
|
||||
s1.fail();
|
||||
REQUIRE( s1.isComplete() );
|
||||
REQUIRE( s1.isSuccessfullyCompleted() == false );
|
||||
REQUIRE( testCase.isComplete() == false );
|
||||
|
||||
testCase.close();
|
||||
REQUIRE( ctx.completedCycle() );
|
||||
REQUIRE( testCase.isSuccessfullyCompleted() == false );
|
||||
|
||||
SECTION( "re-enter after failed section" ) {
|
||||
ctx.startCycle();
|
||||
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
||||
REQUIRE( testCase2.isOpen() );
|
||||
|
||||
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
||||
REQUIRE( s1b.isOpen() == false );
|
||||
|
||||
testCase2.close();
|
||||
REQUIRE( ctx.completedCycle() );
|
||||
REQUIRE( testCase.isComplete() );
|
||||
REQUIRE( testCase.isSuccessfullyCompleted() );
|
||||
}
|
||||
SECTION( "re-enter after failed section and find next section" ) {
|
||||
ctx.startCycle();
|
||||
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
||||
REQUIRE( testCase2.isOpen() );
|
||||
|
||||
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
||||
REQUIRE( s1b.isOpen() == false );
|
||||
|
||||
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
||||
REQUIRE( s2.isOpen() );
|
||||
|
||||
s2.close();
|
||||
REQUIRE( ctx.completedCycle() );
|
||||
|
||||
testCase2.close();
|
||||
REQUIRE( testCase.isComplete() );
|
||||
REQUIRE( testCase.isSuccessfullyCompleted() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "successfully close one section, then find another" ) {
|
||||
s1.close();
|
||||
|
||||
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
||||
REQUIRE( s2.isOpen() == false );
|
||||
|
||||
testCase.close();
|
||||
REQUIRE( testCase.isComplete() == false );
|
||||
|
||||
SECTION( "Re-enter - skips S1 and enters S2" ) {
|
||||
ctx.startCycle();
|
||||
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
||||
REQUIRE( testCase2.isOpen() );
|
||||
|
||||
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
||||
REQUIRE( s1b.isOpen() == false );
|
||||
|
||||
ITracker& s2b = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
||||
REQUIRE( s2b.isOpen() );
|
||||
|
||||
REQUIRE( ctx.completedCycle() == false );
|
||||
|
||||
SECTION ("Successfully close S2") {
|
||||
s2b.close();
|
||||
REQUIRE( ctx.completedCycle() );
|
||||
|
||||
REQUIRE( s2b.isSuccessfullyCompleted() );
|
||||
REQUIRE( testCase2.isComplete() == false );
|
||||
|
||||
testCase2.close();
|
||||
REQUIRE( testCase2.isSuccessfullyCompleted() );
|
||||
}
|
||||
SECTION ("fail S2") {
|
||||
s2b.fail();
|
||||
REQUIRE( ctx.completedCycle() );
|
||||
|
||||
REQUIRE( s2b.isComplete() );
|
||||
REQUIRE( s2b.isSuccessfullyCompleted() == false );
|
||||
|
||||
testCase2.close();
|
||||
REQUIRE( testCase2.isSuccessfullyCompleted() == false );
|
||||
|
||||
// Need a final cycle
|
||||
ctx.startCycle();
|
||||
ITracker& testCase3 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
||||
REQUIRE( testCase3.isOpen() );
|
||||
|
||||
ITracker& s1c = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
||||
REQUIRE( s1c.isOpen() == false );
|
||||
|
||||
ITracker& s2c = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
||||
REQUIRE( s2c.isOpen() == false );
|
||||
|
||||
testCase3.close();
|
||||
REQUIRE( testCase3.isSuccessfullyCompleted() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "open a nested section" ) {
|
||||
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
||||
REQUIRE( s2.isOpen() );
|
||||
|
||||
s2.close();
|
||||
REQUIRE( s2.isComplete() );
|
||||
REQUIRE( s1.isComplete() == false );
|
||||
|
||||
s1.close();
|
||||
REQUIRE( s1.isComplete() );
|
||||
REQUIRE( testCase.isComplete() == false );
|
||||
|
||||
testCase.close();
|
||||
REQUIRE( testCase.isComplete() );
|
||||
}
|
||||
}
|
||||
|
||||
static bool previouslyRun = false;
|
||||
static bool previouslyRunNested = false;
|
||||
|
||||
TEST_CASE( "#1394", "[.][approvals][tracker]" ) {
|
||||
// -- Don't re-run after specified section is done
|
||||
REQUIRE(previouslyRun == false);
|
||||
|
||||
SECTION( "RunSection" ) {
|
||||
previouslyRun = true;
|
||||
}
|
||||
SECTION( "SkipSection" ) {
|
||||
// cause an error if this section is called because it shouldn't be
|
||||
REQUIRE(1 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "#1394 nested", "[.][approvals][tracker]" ) {
|
||||
REQUIRE(previouslyRunNested == false);
|
||||
|
||||
SECTION( "NestedRunSection" ) {
|
||||
SECTION( "s1" ) {
|
||||
previouslyRunNested = true;
|
||||
}
|
||||
}
|
||||
SECTION( "NestedSkipSection" ) {
|
||||
// cause an error if this section is called because it shouldn't be
|
||||
REQUIRE(1 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Selecting a "not last" section inside a test case via -c "section" would
|
||||
// previously only run the first subsection, instead of running all of them.
|
||||
// This allows us to check that `"#1670 regression check" -c A` leads to
|
||||
// 2 successful assertions.
|
||||
TEST_CASE("#1670 regression check", "[.approvals][tracker]") {
|
||||
SECTION("A") {
|
||||
SECTION("1") SUCCEED();
|
||||
SECTION("2") SUCCEED();
|
||||
}
|
||||
SECTION("B") {
|
||||
SECTION("1") SUCCEED();
|
||||
SECTION("2") SUCCEED();
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Created by Martin on 06/10/2019.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <catch2/catch_random_number_generator.h>
|
||||
|
||||
TEST_CASE("Our PCG implementation provides expected results for known seeds", "[rng]") {
|
||||
Catch::SimplePcg32 rng;
|
||||
SECTION("Default seeded") {
|
||||
REQUIRE(rng() == 0xfcdb943b);
|
||||
REQUIRE(rng() == 0x6f55b921);
|
||||
REQUIRE(rng() == 0x4c17a916);
|
||||
REQUIRE(rng() == 0x71eae25f);
|
||||
REQUIRE(rng() == 0x6ce7909c);
|
||||
}
|
||||
SECTION("Specific seed") {
|
||||
rng.seed(0xabcd1234);
|
||||
REQUIRE(rng() == 0x57c08495);
|
||||
REQUIRE(rng() == 0x33c956ac);
|
||||
REQUIRE(rng() == 0x2206fd76);
|
||||
REQUIRE(rng() == 0x3501a35b);
|
||||
REQUIRE(rng() == 0xfdffb30f);
|
||||
|
||||
// Also check repeated output after reseeding
|
||||
rng.seed(0xabcd1234);
|
||||
REQUIRE(rng() == 0x57c08495);
|
||||
REQUIRE(rng() == 0x33c956ac);
|
||||
REQUIRE(rng() == 0x2206fd76);
|
||||
REQUIRE(rng() == 0x3501a35b);
|
||||
REQUIRE(rng() == 0xfdffb30f);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Comparison ops", "[rng]") {
|
||||
using Catch::SimplePcg32;
|
||||
REQUIRE(SimplePcg32{} == SimplePcg32{});
|
||||
REQUIRE(SimplePcg32{ 0 } != SimplePcg32{});
|
||||
REQUIRE_FALSE(SimplePcg32{ 1 } == SimplePcg32{ 2 });
|
||||
REQUIRE_FALSE(SimplePcg32{ 1 } != SimplePcg32{ 1 });
|
||||
}
|
150
tests/SelfTest/IntrospectiveTests/String.tests.cpp
Normal file
150
tests/SelfTest/IntrospectiveTests/String.tests.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include <catch2/catch_stringref.h>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
|
||||
|
||||
using Catch::StringRef;
|
||||
|
||||
SECTION( "Empty string" ) {
|
||||
StringRef empty;
|
||||
REQUIRE( empty.empty() );
|
||||
REQUIRE( empty.size() == 0 );
|
||||
REQUIRE( empty.isNullTerminated() );
|
||||
REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 );
|
||||
}
|
||||
|
||||
SECTION( "From string literal" ) {
|
||||
StringRef s = "hello";
|
||||
REQUIRE( s.empty() == false );
|
||||
REQUIRE( s.size() == 5 );
|
||||
REQUIRE( s.isNullTerminated() );
|
||||
|
||||
auto rawChars = s.data();
|
||||
REQUIRE( std::strcmp( rawChars, "hello" ) == 0 );
|
||||
|
||||
REQUIRE_NOTHROW(s.c_str());
|
||||
REQUIRE(s.c_str() == rawChars);
|
||||
REQUIRE(s.data() == rawChars);
|
||||
}
|
||||
SECTION( "From sub-string" ) {
|
||||
StringRef original = StringRef( "original string" ).substr(0, 8);
|
||||
REQUIRE( original == "original" );
|
||||
|
||||
REQUIRE_FALSE(original.isNullTerminated());
|
||||
REQUIRE_THROWS(original.c_str());
|
||||
REQUIRE_NOTHROW(original.data());
|
||||
}
|
||||
|
||||
|
||||
SECTION( "Substrings" ) {
|
||||
StringRef s = "hello world!";
|
||||
StringRef ss = s.substr(0, 5);
|
||||
|
||||
SECTION( "zero-based substring" ) {
|
||||
REQUIRE( ss.empty() == false );
|
||||
REQUIRE( ss.size() == 5 );
|
||||
REQUIRE( std::strncmp( ss.data(), "hello", 5 ) == 0 );
|
||||
REQUIRE( ss == "hello" );
|
||||
}
|
||||
|
||||
SECTION( "non-zero-based substring") {
|
||||
ss = s.substr( 6, 6 );
|
||||
REQUIRE( ss.size() == 6 );
|
||||
REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 );
|
||||
}
|
||||
|
||||
SECTION( "Pointer values of full refs should match" ) {
|
||||
StringRef s2 = s;
|
||||
REQUIRE( s.data() == s2.data() );
|
||||
}
|
||||
|
||||
SECTION( "Pointer values of substring refs should also match" ) {
|
||||
REQUIRE( s.data() == ss.data() );
|
||||
}
|
||||
|
||||
SECTION("Past the end substring") {
|
||||
REQUIRE(s.substr(s.size() + 1, 123).empty());
|
||||
}
|
||||
|
||||
SECTION("Substring off the end are trimmed") {
|
||||
ss = s.substr(6, 123);
|
||||
REQUIRE(std::strcmp(ss.c_str(), "world!") == 0);
|
||||
}
|
||||
// TODO: substring into string + size is longer than end
|
||||
}
|
||||
|
||||
SECTION( "Comparisons are deep" ) {
|
||||
char buffer1[] = "Hello";
|
||||
char buffer2[] = "Hello";
|
||||
CHECK((char*)buffer1 != (char*)buffer2);
|
||||
|
||||
StringRef left(buffer1), right(buffer2);
|
||||
REQUIRE( left == right );
|
||||
REQUIRE(left != left.substr(0, 3));
|
||||
}
|
||||
|
||||
SECTION( "from std::string" ) {
|
||||
std::string stdStr = "a standard string";
|
||||
|
||||
SECTION( "implicitly constructed" ) {
|
||||
StringRef sr = stdStr;
|
||||
REQUIRE( sr == "a standard string" );
|
||||
REQUIRE( sr.size() == stdStr.size() );
|
||||
}
|
||||
SECTION( "explicitly constructed" ) {
|
||||
StringRef sr( stdStr );
|
||||
REQUIRE( sr == "a standard string" );
|
||||
REQUIRE( sr.size() == stdStr.size() );
|
||||
}
|
||||
SECTION( "assigned" ) {
|
||||
StringRef sr;
|
||||
sr = stdStr;
|
||||
REQUIRE( sr == "a standard string" );
|
||||
REQUIRE( sr.size() == stdStr.size() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "to std::string" ) {
|
||||
StringRef sr = "a stringref";
|
||||
|
||||
SECTION( "explicitly constructed" ) {
|
||||
std::string stdStr( sr );
|
||||
REQUIRE( stdStr == "a stringref" );
|
||||
REQUIRE( stdStr.size() == sr.size() );
|
||||
}
|
||||
SECTION( "assigned" ) {
|
||||
std::string stdStr;
|
||||
stdStr = static_cast<std::string>(sr);
|
||||
REQUIRE( stdStr == "a stringref" );
|
||||
REQUIRE( stdStr.size() == sr.size() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") {
|
||||
using Catch::StringRef;
|
||||
SECTION("Simple constructors") {
|
||||
STATIC_REQUIRE(StringRef{}.size() == 0);
|
||||
|
||||
STATIC_REQUIRE(StringRef{ "abc", 3 }.size() == 3);
|
||||
STATIC_REQUIRE(StringRef{ "abc", 3 }.isNullTerminated());
|
||||
|
||||
STATIC_REQUIRE(StringRef{ "abc", 2 }.size() == 2);
|
||||
STATIC_REQUIRE_FALSE(StringRef{ "abc", 2 }.isNullTerminated());
|
||||
}
|
||||
SECTION("UDL construction") {
|
||||
constexpr auto sr1 = "abc"_catch_sr;
|
||||
STATIC_REQUIRE_FALSE(sr1.empty());
|
||||
STATIC_REQUIRE(sr1.size() == 3);
|
||||
STATIC_REQUIRE(sr1.isNullTerminated());
|
||||
|
||||
using Catch::operator"" _sr;
|
||||
constexpr auto sr2 = ""_sr;
|
||||
STATIC_REQUIRE(sr2.empty());
|
||||
STATIC_REQUIRE(sr2.size() == 0);
|
||||
STATIC_REQUIRE(sr2.isNullTerminated());
|
||||
}
|
||||
}
|
67
tests/SelfTest/IntrospectiveTests/StringManip.tests.cpp
Normal file
67
tests/SelfTest/IntrospectiveTests/StringManip.tests.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <catch2/catch_string_manip.h>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
static const char * const no_whitespace = "There is no extra whitespace here";
|
||||
static const char * const leading_whitespace = " \r \t\n There is no extra whitespace here";
|
||||
static const char * const trailing_whitespace = "There is no extra whitespace here \t \n \r ";
|
||||
static const char * const whitespace_at_both_ends = " \r\n \t There is no extra whitespace here \t\t\t \n";
|
||||
|
||||
TEST_CASE("Trim strings", "[string-manip]") {
|
||||
using Catch::trim; using Catch::StringRef;
|
||||
static_assert(std::is_same<std::string, decltype(trim(std::string{}))>::value, "Trimming std::string should return std::string");
|
||||
static_assert(std::is_same<StringRef, decltype(trim(StringRef{}))>::value, "Trimming StringRef should return StringRef");
|
||||
|
||||
REQUIRE(trim(std::string(no_whitespace)) == no_whitespace);
|
||||
REQUIRE(trim(std::string(leading_whitespace)) == no_whitespace);
|
||||
REQUIRE(trim(std::string(trailing_whitespace)) == no_whitespace);
|
||||
REQUIRE(trim(std::string(whitespace_at_both_ends)) == no_whitespace);
|
||||
|
||||
REQUIRE(trim(StringRef(no_whitespace)) == StringRef(no_whitespace));
|
||||
REQUIRE(trim(StringRef(leading_whitespace)) == StringRef(no_whitespace));
|
||||
REQUIRE(trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace));
|
||||
REQUIRE(trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace));
|
||||
}
|
||||
|
||||
TEST_CASE("replaceInPlace", "[string-manip]") {
|
||||
std::string letters = "abcdefcg";
|
||||
SECTION("replace single char") {
|
||||
CHECK(Catch::replaceInPlace(letters, "b", "z"));
|
||||
CHECK(letters == "azcdefcg");
|
||||
}
|
||||
SECTION("replace two chars") {
|
||||
CHECK(Catch::replaceInPlace(letters, "c", "z"));
|
||||
CHECK(letters == "abzdefzg");
|
||||
}
|
||||
SECTION("replace first char") {
|
||||
CHECK(Catch::replaceInPlace(letters, "a", "z"));
|
||||
CHECK(letters == "zbcdefcg");
|
||||
}
|
||||
SECTION("replace last char") {
|
||||
CHECK(Catch::replaceInPlace(letters, "g", "z"));
|
||||
CHECK(letters == "abcdefcz");
|
||||
}
|
||||
SECTION("replace all chars") {
|
||||
CHECK(Catch::replaceInPlace(letters, letters, "replaced"));
|
||||
CHECK(letters == "replaced");
|
||||
}
|
||||
SECTION("replace no chars") {
|
||||
CHECK_FALSE(Catch::replaceInPlace(letters, "x", "z"));
|
||||
CHECK(letters == letters);
|
||||
}
|
||||
SECTION("escape '") {
|
||||
std::string s = "didn't";
|
||||
CHECK(Catch::replaceInPlace(s, "'", "|'"));
|
||||
CHECK(s == "didn|'t");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("splitString", "[string-manip]") {
|
||||
using namespace Catch::Matchers;
|
||||
using Catch::splitStringRef;
|
||||
using Catch::StringRef;
|
||||
|
||||
CHECK_THAT(splitStringRef("", ','), Equals(std::vector<StringRef>()));
|
||||
CHECK_THAT(splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}));
|
||||
CHECK_THAT(splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}));
|
||||
}
|
53
tests/SelfTest/IntrospectiveTests/Tag.tests.cpp
Normal file
53
tests/SelfTest/IntrospectiveTests/Tag.tests.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Created by Phil on 27/06/2014.
|
||||
* Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_tag_alias_registry.h>
|
||||
|
||||
TEST_CASE( "Tag alias can be registered against tag patterns" ) {
|
||||
|
||||
Catch::TagAliasRegistry registry;
|
||||
|
||||
registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) );
|
||||
|
||||
SECTION( "The same tag alias can only be registered once" ) {
|
||||
|
||||
try {
|
||||
registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 10 ) );
|
||||
FAIL( "expected exception" );
|
||||
}
|
||||
catch( std::exception& ex ) {
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
std::string what = ex.what();
|
||||
using namespace Catch::Matchers;
|
||||
CHECK_THAT( what, Contains( "[@zzz]" ) );
|
||||
CHECK_THAT( what, Contains( "file" ) );
|
||||
CHECK_THAT( what, Contains( "2" ) );
|
||||
CHECK_THAT( what, Contains( "10" ) );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Tag aliases must be of the form [@name]" ) {
|
||||
CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) );
|
||||
CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) );
|
||||
CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) );
|
||||
CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("shortened hide tags are split apart") {
|
||||
using Catch::StringRef;
|
||||
auto testcase = Catch::makeTestCaseInfo("", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO);
|
||||
// Transform ...
|
||||
std::vector<StringRef> tags;
|
||||
for (auto const& tag : testcase->tags) {
|
||||
tags.push_back(tag.original);
|
||||
}
|
||||
REQUIRE_THAT(tags, Catch::VectorContains("magic-tag"_catch_sr) && Catch::VectorContains("."_catch_sr));
|
||||
}
|
42
tests/SelfTest/IntrospectiveTests/ToString.tests.cpp
Normal file
42
tests/SelfTest/IntrospectiveTests/ToString.tests.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <catch2/catch_enum_values_registry.h>
|
||||
|
||||
enum class EnumClass3 { Value1, Value2, Value3, Value4 };
|
||||
|
||||
|
||||
TEST_CASE( "parseEnums", "[Strings][enums]" ) {
|
||||
using namespace Catch::Matchers;
|
||||
using Catch::Detail::parseEnums;
|
||||
|
||||
SECTION( "No enums" )
|
||||
CHECK_THAT( parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) );
|
||||
|
||||
SECTION( "One enum value" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ),
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "Value1" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
CHECK_THAT( parseEnums( "EnumName::Value1" ),
|
||||
Equals(std::vector<Catch::StringRef>{"Value1"} ) );
|
||||
}
|
||||
|
||||
SECTION( "Multiple enum values" ) {
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ),
|
||||
Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Directly creating an EnumInfo" ) {
|
||||
|
||||
using namespace Catch::Detail;
|
||||
std::unique_ptr<EnumInfo> enumInfo = makeEnumInfo( "EnumName", "EnumName::Value1, EnumName::Value2", {0, 1} );
|
||||
|
||||
CHECK( enumInfo->lookup(0) == "Value1" );
|
||||
CHECK( enumInfo->lookup(1) == "Value2" );
|
||||
CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" );
|
||||
}
|
114
tests/SelfTest/IntrospectiveTests/Xml.tests.cpp
Normal file
114
tests/SelfTest/IntrospectiveTests/Xml.tests.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <catch2/catch_xmlwriter.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) {
|
||||
std::ostringstream oss;
|
||||
oss << Catch::XmlEncode( str, forWhat );
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
TEST_CASE( "XmlEncode", "[XML]" ) {
|
||||
SECTION( "normal string" ) {
|
||||
REQUIRE( encode( "normal string" ) == "normal string" );
|
||||
}
|
||||
SECTION( "empty string" ) {
|
||||
REQUIRE( encode( "" ) == "" );
|
||||
}
|
||||
SECTION( "string with ampersand" ) {
|
||||
REQUIRE( encode( "smith & jones" ) == "smith & jones" );
|
||||
}
|
||||
SECTION( "string with less-than" ) {
|
||||
REQUIRE( encode( "smith < jones" ) == "smith < jones" );
|
||||
}
|
||||
SECTION( "string with greater-than" ) {
|
||||
REQUIRE( encode( "smith > jones" ) == "smith > jones" );
|
||||
REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" );
|
||||
}
|
||||
SECTION( "string with quotes" ) {
|
||||
std::string stringWithQuotes = "don't \"quote\" me on that";
|
||||
REQUIRE( encode( stringWithQuotes ) == stringWithQuotes );
|
||||
REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" );
|
||||
}
|
||||
SECTION( "string with control char (1)" ) {
|
||||
REQUIRE( encode( "[\x01]" ) == "[\\x01]" );
|
||||
}
|
||||
SECTION( "string with control char (x7F)" ) {
|
||||
REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" );
|
||||
}
|
||||
}
|
||||
|
||||
// Thanks to Peter Bindels (dascandy) for some of the tests
|
||||
TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8][approvals]") {
|
||||
#define ESC(lit) (char*)(lit)
|
||||
SECTION("Valid utf-8 strings") {
|
||||
CHECK(encode(ESC(u8"Here be 👾")) == ESC(u8"Here be 👾"));
|
||||
CHECK(encode(ESC(u8"šš")) == ESC(u8"šš"));
|
||||
|
||||
CHECK(encode("\xDF\xBF") == "\xDF\xBF"); // 0x7FF
|
||||
CHECK(encode("\xE0\xA0\x80") == "\xE0\xA0\x80"); // 0x800
|
||||
CHECK(encode("\xED\x9F\xBF") == "\xED\x9F\xBF"); // 0xD7FF
|
||||
CHECK(encode("\xEE\x80\x80") == "\xEE\x80\x80"); // 0xE000
|
||||
CHECK(encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF"); // 0xFFFF
|
||||
CHECK(encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80"); // 0x10000
|
||||
CHECK(encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF"); // 0x10FFFF
|
||||
}
|
||||
SECTION("Invalid utf-8 strings") {
|
||||
SECTION("Various broken strings") {
|
||||
CHECK(encode(ESC("Here \xFF be \xF0\x9F\x91\xBE")) == ESC(u8"Here \\xFF be 👾"));
|
||||
CHECK(encode("\xFF") == "\\xFF");
|
||||
CHECK(encode("\xC5\xC5\xA0") == ESC(u8"\\xC5Š"));
|
||||
CHECK(encode("\xF4\x90\x80\x80") == ESC(u8"\\xF4\\x90\\x80\\x80")); // 0x110000 -- out of unicode range
|
||||
}
|
||||
|
||||
SECTION("Overlong encodings") {
|
||||
CHECK(encode("\xC0\x80") == "\\xC0\\x80"); // \0
|
||||
CHECK(encode("\xF0\x80\x80\x80") == "\\xF0\\x80\\x80\\x80"); // Super-over-long \0
|
||||
CHECK(encode("\xC1\xBF") == "\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
|
||||
CHECK(encode("\xE0\x9F\xBF") == "\\xE0\\x9F\\xBF"); // 0x7FF
|
||||
CHECK(encode("\xF0\x8F\xBF\xBF") == "\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
|
||||
}
|
||||
|
||||
// Note that we actually don't modify surrogate pairs, as we do not do strict checking
|
||||
SECTION("Surrogate pairs") {
|
||||
CHECK(encode("\xED\xA0\x80") == "\xED\xA0\x80"); // Invalid surrogate half 0xD800
|
||||
CHECK(encode("\xED\xAF\xBF") == "\xED\xAF\xBF"); // Invalid surrogate half 0xDBFF
|
||||
CHECK(encode("\xED\xB0\x80") == "\xED\xB0\x80"); // Invalid surrogate half 0xDC00
|
||||
CHECK(encode("\xED\xBF\xBF") == "\xED\xBF\xBF"); // Invalid surrogate half 0xDFFF
|
||||
}
|
||||
|
||||
SECTION("Invalid start byte") {
|
||||
CHECK(encode("\x80") == "\\x80");
|
||||
CHECK(encode("\x81") == "\\x81");
|
||||
CHECK(encode("\xBC") == "\\xBC");
|
||||
CHECK(encode("\xBF") == "\\xBF");
|
||||
// Out of range
|
||||
CHECK(encode("\xF5\x80\x80\x80") == "\\xF5\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF6\x80\x80\x80") == "\\xF6\\x80\\x80\\x80");
|
||||
CHECK(encode("\xF7\x80\x80\x80") == "\\xF7\\x80\\x80\\x80");
|
||||
}
|
||||
|
||||
SECTION("Missing continuation byte(s)") {
|
||||
// Missing first continuation byte
|
||||
CHECK(encode("\xDE") == "\\xDE");
|
||||
CHECK(encode("\xDF") == "\\xDF");
|
||||
CHECK(encode("\xE0") == "\\xE0");
|
||||
CHECK(encode("\xEF") == "\\xEF");
|
||||
CHECK(encode("\xF0") == "\\xF0");
|
||||
CHECK(encode("\xF4") == "\\xF4");
|
||||
|
||||
// Missing second continuation byte
|
||||
CHECK(encode("\xE0\x80") == "\\xE0\\x80");
|
||||
CHECK(encode("\xE0\xBF") == "\\xE0\\xBF");
|
||||
CHECK(encode("\xE1\x80") == "\\xE1\\x80");
|
||||
CHECK(encode("\xF0\x80") == "\\xF0\\x80");
|
||||
CHECK(encode("\xF4\x80") == "\\xF4\\x80");
|
||||
|
||||
// Missing third continuation byte
|
||||
CHECK(encode("\xF0\x80\x80") == "\\xF0\\x80\\x80");
|
||||
CHECK(encode("\xF4\x80\x80") == "\\xF4\\x80\\x80");
|
||||
}
|
||||
}
|
||||
#undef ESC
|
||||
}
|
1
tests/SelfTest/Misc/invalid-test-names.input
Normal file
1
tests/SelfTest/Misc/invalid-test-names.input
Normal file
@@ -0,0 +1 @@
|
||||
Test with special, characters in \" name
|
2
tests/SelfTest/Misc/plain-old-tests.input
Normal file
2
tests/SelfTest/Misc/plain-old-tests.input
Normal file
@@ -0,0 +1,2 @@
|
||||
random SECTION tests
|
||||
nested SECTION tests
|
1
tests/SelfTest/Misc/special-characters-in-file.input
Normal file
1
tests/SelfTest/Misc/special-characters-in-file.input
Normal file
@@ -0,0 +1 @@
|
||||
Test with special\, characters \"in name
|
3
tests/SelfTest/SurrogateCpps/catch_console_colour.cpp
Normal file
3
tests/SelfTest/SurrogateCpps/catch_console_colour.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_console_colour.h>
|
2
tests/SelfTest/SurrogateCpps/catch_debugger.cpp
Normal file
2
tests/SelfTest/SurrogateCpps/catch_debugger.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_debugger.h>
|
@@ -0,0 +1,2 @@
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_interfaces_reporter.h>
|
3
tests/SelfTest/SurrogateCpps/catch_option.cpp
Normal file
3
tests/SelfTest/SurrogateCpps/catch_option.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_option.hpp>
|
3
tests/SelfTest/SurrogateCpps/catch_stream.cpp
Normal file
3
tests/SelfTest/SurrogateCpps/catch_stream.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_stream.h>
|
2
tests/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp
Normal file
2
tests/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_test_case_tracker.h>
|
3
tests/SelfTest/SurrogateCpps/catch_test_spec.cpp
Normal file
3
tests/SelfTest/SurrogateCpps/catch_test_spec.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_test_spec.h>
|
4
tests/SelfTest/SurrogateCpps/catch_xmlwriter.cpp
Normal file
4
tests/SelfTest/SurrogateCpps/catch_xmlwriter.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// This file is only here to verify (to the extent possible) the self sufficiency of the header
|
||||
#include <catch2/catch_suppress_warnings.h>
|
||||
#include <catch2/catch_xmlwriter.h>
|
||||
#include <catch2/catch_reenable_warnings.h>
|
34
tests/SelfTest/TestMain.cpp
Normal file
34
tests/SelfTest/TestMain.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Created by Phil on 22/10/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
// These reporters are not included in the single include, so must be included separately in the main file
|
||||
#include <catch2/reporters/catch_reporter_teamcity.hpp>
|
||||
#include <catch2/reporters/catch_reporter_tap.hpp>
|
||||
#include <catch2/reporters/catch_reporter_automake.hpp>
|
||||
#include <catch2/reporters/catch_reporter_sonarqube.hpp>
|
||||
|
||||
|
||||
// Some example tag aliases
|
||||
CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
|
||||
CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" )
|
||||
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic ignored "-Wpadded"
|
||||
# pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
|
||||
struct TestListener : Catch::TestEventListenerBase {
|
||||
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
|
||||
};
|
||||
CATCH_REGISTER_LISTENER( TestListener )
|
||||
|
215
tests/SelfTest/UsageTests/Approx.tests.cpp
Normal file
215
tests/SelfTest/UsageTests/Approx.tests.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Created by Phil on 28/04/2011.
|
||||
* Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace { namespace ApproxTests {
|
||||
|
||||
#ifndef APPROX_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define APPROX_TEST_HELPERS_INCLUDED
|
||||
|
||||
inline double divide( double a, double b ) {
|
||||
return a/b;
|
||||
}
|
||||
|
||||
class StrongDoubleTypedef {
|
||||
double d_ = 0.0;
|
||||
|
||||
public:
|
||||
explicit StrongDoubleTypedef(double d) : d_(d) {}
|
||||
explicit operator double() const { return d_; }
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<( std::ostream& os, StrongDoubleTypedef td ) {
|
||||
return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
using namespace Catch::literals;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "A comparison that uses literals instead of the normal constructor", "[Approx]" ) {
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d == 1.23_a );
|
||||
REQUIRE( d != 1.22_a );
|
||||
REQUIRE( -d == -1.23_a );
|
||||
|
||||
REQUIRE( d == 1.2_a .epsilon(.1) );
|
||||
REQUIRE( d != 1.2_a .epsilon(.001) );
|
||||
REQUIRE( d == 1_a .epsilon(.3) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Some simple comparisons between doubles", "[Approx]" ) {
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d == Approx( 1.23 ) );
|
||||
REQUIRE( d != Approx( 1.22 ) );
|
||||
REQUIRE( d != Approx( 1.24 ) );
|
||||
|
||||
REQUIRE( d == 1.23_a );
|
||||
REQUIRE( d != 1.22_a );
|
||||
|
||||
REQUIRE( Approx( d ) == 1.23 );
|
||||
REQUIRE( Approx( d ) != 1.22 );
|
||||
REQUIRE( Approx( d ) != 1.24 );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Approximate comparisons with different epsilons", "[Approx]" ) {
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d != Approx( 1.231 ) );
|
||||
REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Less-than inequalities with different epsilons", "[Approx]" ) {
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d <= Approx( 1.24 ) );
|
||||
REQUIRE( d <= Approx( 1.23 ) );
|
||||
REQUIRE_FALSE( d <= Approx( 1.22 ) );
|
||||
REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Greater-than inequalities with different epsilons", "[Approx]" ) {
|
||||
double d = 1.23;
|
||||
|
||||
REQUIRE( d >= Approx( 1.22 ) );
|
||||
REQUIRE( d >= Approx( 1.23 ) );
|
||||
REQUIRE_FALSE( d >= Approx( 1.24 ) );
|
||||
REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Approximate comparisons with floats", "[Approx]" ) {
|
||||
REQUIRE( 1.23f == Approx( 1.23f ) );
|
||||
REQUIRE( 0.0f == Approx( 0.0f ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Approximate comparisons with ints", "[Approx]" ) {
|
||||
REQUIRE( 1 == Approx( 1 ) );
|
||||
REQUIRE( 0 == Approx( 0 ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Approximate comparisons with mixed numeric types", "[Approx]" ) {
|
||||
const double dZero = 0;
|
||||
const double dSmall = 0.00001;
|
||||
const double dMedium = 1.234;
|
||||
|
||||
REQUIRE( 1.0f == Approx( 1 ) );
|
||||
REQUIRE( 0 == Approx( dZero) );
|
||||
REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) );
|
||||
REQUIRE( 1.234f == Approx( dMedium ) );
|
||||
REQUIRE( dMedium == Approx( 1.234f ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE( "Use a custom approx", "[Approx][custom]" ) {
|
||||
double d = 1.23;
|
||||
|
||||
Approx approx = Approx::custom().epsilon( 0.01 );
|
||||
|
||||
REQUIRE( d == approx( 1.23 ) );
|
||||
REQUIRE( d == approx( 1.22 ) );
|
||||
REQUIRE( d == approx( 1.24 ) );
|
||||
REQUIRE( d != approx( 1.25 ) );
|
||||
|
||||
REQUIRE( approx( d ) == 1.23 );
|
||||
REQUIRE( approx( d ) == 1.22 );
|
||||
REQUIRE( approx( d ) == 1.24 );
|
||||
REQUIRE( approx( d ) != 1.25 );
|
||||
}
|
||||
|
||||
TEST_CASE( "Approximate PI", "[Approx][PI]" ) {
|
||||
REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) );
|
||||
REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST_CASE( "Absolute margin", "[Approx]" ) {
|
||||
REQUIRE( 104.0 != Approx(100.0) );
|
||||
REQUIRE( 104.0 == Approx(100.0).margin(5) );
|
||||
REQUIRE( 104.0 == Approx(100.0).margin(4) );
|
||||
REQUIRE( 104.0 != Approx(100.0).margin(3) );
|
||||
REQUIRE( 100.3 != Approx(100.0) );
|
||||
REQUIRE( 100.3 == Approx(100.0).margin(0.5) );
|
||||
}
|
||||
|
||||
TEST_CASE("Approx with exactly-representable margin", "[Approx]") {
|
||||
CHECK( 0.25f == Approx(0.0f).margin(0.25f) );
|
||||
|
||||
CHECK( 0.0f == Approx(0.25f).margin(0.25f) );
|
||||
CHECK( 0.5f == Approx(0.25f).margin(0.25f) );
|
||||
|
||||
CHECK( 245.0f == Approx(245.25f).margin(0.25f) );
|
||||
CHECK( 245.5f == Approx(245.25f).margin(0.25f) );
|
||||
}
|
||||
|
||||
TEST_CASE("Approx setters validate their arguments", "[Approx]") {
|
||||
REQUIRE_NOTHROW(Approx(0).margin(0));
|
||||
REQUIRE_NOTHROW(Approx(0).margin(1234656));
|
||||
|
||||
REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(Approx(0).epsilon(0));
|
||||
REQUIRE_NOTHROW(Approx(0).epsilon(1));
|
||||
|
||||
REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error);
|
||||
REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error);
|
||||
}
|
||||
|
||||
TEST_CASE("Default scale is invisible to comparison", "[Approx]") {
|
||||
REQUIRE(101.000001 != Approx(100).epsilon(0.01));
|
||||
REQUIRE(std::pow(10, -5) != Approx(std::pow(10, -7)));
|
||||
}
|
||||
|
||||
TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") {
|
||||
REQUIRE(101.01 != Approx(100).epsilon(0.01));
|
||||
}
|
||||
|
||||
TEST_CASE("Assorted miscellaneous tests", "[Approx][approvals]") {
|
||||
REQUIRE(INFINITY == Approx(INFINITY));
|
||||
REQUIRE(-INFINITY != Approx(INFINITY));
|
||||
REQUIRE(1 != Approx(INFINITY));
|
||||
REQUIRE(INFINITY != Approx(1));
|
||||
REQUIRE(NAN != Approx(NAN));
|
||||
REQUIRE_FALSE(NAN == Approx(NAN));
|
||||
}
|
||||
|
||||
TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" )
|
||||
{
|
||||
StrongDoubleTypedef td(10.0);
|
||||
|
||||
REQUIRE(td == Approx(10.0));
|
||||
REQUIRE(Approx(10.0) == td);
|
||||
|
||||
REQUIRE(td != Approx(11.0));
|
||||
REQUIRE(Approx(11.0) != td);
|
||||
|
||||
REQUIRE(td <= Approx(10.0));
|
||||
REQUIRE(td <= Approx(11.0));
|
||||
REQUIRE(Approx(10.0) <= td);
|
||||
REQUIRE(Approx(9.0) <= td);
|
||||
|
||||
REQUIRE(td >= Approx(9.0));
|
||||
REQUIRE(td >= Approx(td));
|
||||
REQUIRE(Approx(td) >= td);
|
||||
REQUIRE(Approx(11.0) >= td);
|
||||
|
||||
}
|
||||
|
||||
}} // namespace ApproxTests
|
110
tests/SelfTest/UsageTests/BDD.tests.cpp
Normal file
110
tests/SelfTest/UsageTests/BDD.tests.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Created by Phil on 29/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace { namespace BDDTests {
|
||||
|
||||
#ifndef BDD_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define BDD_TEST_HELPERS_INCLUDED
|
||||
|
||||
inline bool itDoesThis() { return true; }
|
||||
|
||||
inline bool itDoesThat() { return true; }
|
||||
|
||||
namespace {
|
||||
|
||||
// a trivial fixture example to support SCENARIO_METHOD tests
|
||||
struct Fixture {
|
||||
Fixture()
|
||||
: d_counter(0) {
|
||||
}
|
||||
|
||||
int counter() {
|
||||
return d_counter++;
|
||||
}
|
||||
|
||||
int d_counter;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
SCENARIO("Do that thing with the thing", "[Tags]") {
|
||||
GIVEN("This stuff exists") {
|
||||
// make stuff exist
|
||||
AND_GIVEN("And some assumption") {
|
||||
// Validate assumption
|
||||
WHEN("I do this") {
|
||||
// do this
|
||||
THEN("it should do this") {
|
||||
REQUIRE(itDoesThis());
|
||||
AND_THEN("do that")REQUIRE(itDoesThat());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Vector resizing affects size and capacity", "[vector][bdd][size][capacity]") {
|
||||
GIVEN("an empty vector") {
|
||||
std::vector<int> v;
|
||||
REQUIRE(v.size() == 0);
|
||||
|
||||
WHEN("it is made larger") {
|
||||
v.resize(10);
|
||||
THEN("the size and capacity go up") {
|
||||
REQUIRE(v.size() == 10);
|
||||
REQUIRE(v.capacity() >= 10);
|
||||
|
||||
AND_WHEN("it is made smaller again") {
|
||||
v.resize(5);
|
||||
THEN("the size goes down but the capacity stays the same") {
|
||||
REQUIRE(v.size() == 5);
|
||||
REQUIRE(v.capacity() >= 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("we reserve more space") {
|
||||
v.reserve(10);
|
||||
THEN("The capacity is increased but the size remains the same") {
|
||||
REQUIRE(v.capacity() >= 10);
|
||||
REQUIRE(v.size() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("This is a really long scenario name to see how the list command deals with wrapping",
|
||||
"[very long tags][lots][long][tags][verbose]"
|
||||
"[one very long tag name that should cause line wrapping writing out using the list command]"
|
||||
"[anotherReallyLongTagNameButThisOneHasNoObviousWrapPointsSoShouldSplitWithinAWordUsingADashCharacter]") {
|
||||
GIVEN("A section name that is so long that it cannot fit in a single console width")WHEN(
|
||||
"The test headers are printed as part of the normal running of the scenario")THEN(
|
||||
"The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent")SUCCEED(
|
||||
"boo!");
|
||||
}
|
||||
|
||||
SCENARIO_METHOD(Fixture,
|
||||
"BDD tests requiring Fixtures to provide commonly-accessed data or methods",
|
||||
"[bdd][fixtures]") {
|
||||
const int before(counter());
|
||||
GIVEN("No operations precede me") {
|
||||
REQUIRE(before == 0);
|
||||
WHEN("We get the count") {
|
||||
const int after(counter());
|
||||
THEN("Subsequently values are higher") {
|
||||
REQUIRE(after > before);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace BDDtests
|
130
tests/SelfTest/UsageTests/Benchmark.tests.cpp
Normal file
130
tests/SelfTest/UsageTests/Benchmark.tests.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
|
||||
namespace {
|
||||
std::uint64_t Fibonacci(std::uint64_t number) {
|
||||
return number < 2 ? 1 : Fibonacci(number - 1) + Fibonacci(number - 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Benchmark Fibonacci", "[!benchmark]") {
|
||||
CHECK(Fibonacci(0) == 1);
|
||||
// some more asserts..
|
||||
CHECK(Fibonacci(5) == 8);
|
||||
// some more asserts..
|
||||
|
||||
BENCHMARK("Fibonacci 20") {
|
||||
return Fibonacci(20);
|
||||
};
|
||||
|
||||
BENCHMARK("Fibonacci 25") {
|
||||
return Fibonacci(25);
|
||||
};
|
||||
|
||||
BENCHMARK("Fibonacci 30") {
|
||||
return Fibonacci(30);
|
||||
};
|
||||
|
||||
BENCHMARK("Fibonacci 35") {
|
||||
return Fibonacci(35);
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Benchmark containers", "[!benchmark]") {
|
||||
static const int size = 100;
|
||||
|
||||
std::vector<int> v;
|
||||
std::map<int, int> m;
|
||||
|
||||
SECTION("without generator") {
|
||||
BENCHMARK("Load up a vector") {
|
||||
v = std::vector<int>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
v.push_back(i);
|
||||
};
|
||||
REQUIRE(v.size() == size);
|
||||
|
||||
// test optimizer control
|
||||
BENCHMARK("Add up a vector's content") {
|
||||
uint64_t add = 0;
|
||||
for (int i = 0; i < size; ++i)
|
||||
add += v[i];
|
||||
return add;
|
||||
};
|
||||
|
||||
BENCHMARK("Load up a map") {
|
||||
m = std::map<int, int>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
m.insert({ i, i + 1 });
|
||||
};
|
||||
REQUIRE(m.size() == size);
|
||||
|
||||
BENCHMARK("Reserved vector") {
|
||||
v = std::vector<int>();
|
||||
v.reserve(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v.push_back(i);
|
||||
};
|
||||
REQUIRE(v.size() == size);
|
||||
|
||||
BENCHMARK("Resized vector") {
|
||||
v = std::vector<int>();
|
||||
v.resize(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i] = i;
|
||||
};
|
||||
REQUIRE(v.size() == size);
|
||||
|
||||
int array[size];
|
||||
BENCHMARK("A fixed size array that should require no allocations") {
|
||||
for (int i = 0; i < size; ++i)
|
||||
array[i] = i;
|
||||
};
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; ++i)
|
||||
sum += array[i];
|
||||
REQUIRE(sum > size);
|
||||
|
||||
SECTION("XYZ") {
|
||||
|
||||
BENCHMARK_ADVANCED("Load up vector with chronometer")(Catch::Benchmark::Chronometer meter) {
|
||||
std::vector<int> k;
|
||||
meter.measure([&](int idx) {
|
||||
k = std::vector<int>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
k.push_back(idx);
|
||||
});
|
||||
REQUIRE(k.size() == size);
|
||||
};
|
||||
|
||||
int runs = 0;
|
||||
BENCHMARK("Fill vector indexed", benchmarkIndex) {
|
||||
v = std::vector<int>();
|
||||
v.resize(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i] = benchmarkIndex;
|
||||
runs = benchmarkIndex;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
REQUIRE(v[i] == runs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("with generator") {
|
||||
auto generated = GENERATE(range(0, 10));
|
||||
BENCHMARK("Fill vector generated") {
|
||||
v = std::vector<int>();
|
||||
v.resize(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
v[i] = generated;
|
||||
};
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
REQUIRE(v[i] == generated);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
137
tests/SelfTest/UsageTests/Class.tests.cpp
Normal file
137
tests/SelfTest/UsageTests/Class.tests.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Created by Phil on 09/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace{ namespace ClassTests {
|
||||
|
||||
#ifndef CLASS_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define CLASS_TEST_HELPERS_INCLUDED
|
||||
|
||||
class TestClass
|
||||
{
|
||||
std::string s;
|
||||
|
||||
public:
|
||||
TestClass()
|
||||
: s( "hello" )
|
||||
{}
|
||||
|
||||
void succeedingCase()
|
||||
{
|
||||
REQUIRE( s == "hello" );
|
||||
}
|
||||
void failingCase()
|
||||
{
|
||||
REQUIRE( s == "world" );
|
||||
}
|
||||
};
|
||||
|
||||
struct Fixture
|
||||
{
|
||||
Fixture() : m_a( 1 ) {}
|
||||
|
||||
int m_a;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct Template_Fixture {
|
||||
Template_Fixture(): m_a(1) {}
|
||||
|
||||
T m_a;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Template_Fixture_2 {
|
||||
Template_Fixture_2() {}
|
||||
|
||||
T m_a;
|
||||
};
|
||||
|
||||
template< typename T>
|
||||
struct Template_Foo {
|
||||
size_t size() { return 0; }
|
||||
};
|
||||
|
||||
template< typename T, size_t V>
|
||||
struct Template_Foo_2 {
|
||||
size_t size() { return V; }
|
||||
};
|
||||
|
||||
template <int V>
|
||||
struct Nttp_Fixture{
|
||||
int value = V;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
METHOD_AS_TEST_CASE( TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" )
|
||||
METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" )
|
||||
|
||||
TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[class]" )
|
||||
{
|
||||
REQUIRE( m_a == 1 );
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE_METHOD(Template_Fixture, "A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
|
||||
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE_METHOD_SIG(Nttp_Fixture, "A TEMPLATE_TEST_CASE_METHOD_SIG based test run that succeeds", "[class][template][nttp]",((int V), V), 1, 3, 6) {
|
||||
REQUIRE(Nttp_Fixture<V>::value > 0);
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds","[class][template][product]",(std::vector,Template_Foo),(int,float))
|
||||
{
|
||||
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 );
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG based test run that succeeds", "[class][template][product][nttp]", ((typename T, size_t S), T, S),(std::array, Template_Foo_2), ((int,2), (float,6)))
|
||||
{
|
||||
REQUIRE(Template_Fixture_2<TestType>{}.m_a.size() >= 2);
|
||||
}
|
||||
|
||||
using MyTypes = std::tuple<int, char, double>;
|
||||
TEMPLATE_LIST_TEST_CASE_METHOD(Template_Fixture, "Template test case method with test types specified inside std::tuple", "[class][template][list]", MyTypes)
|
||||
{
|
||||
REQUIRE( Template_Fixture<TestType>::m_a == 1 );
|
||||
}
|
||||
|
||||
// We should be able to write our tests within a different namespace
|
||||
namespace Inner
|
||||
{
|
||||
TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that fails", "[.][class][failing]" )
|
||||
{
|
||||
REQUIRE( m_a == 2 );
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that fails", "[.][class][template][failing]", int, float, double)
|
||||
{
|
||||
REQUIRE( Template_Fixture<TestType>::m_a == 2 );
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE_METHOD_SIG(Nttp_Fixture, "A TEMPLATE_TEST_CASE_METHOD_SIG based test run that fails", "[.][class][template][nttp][failing]", ((int V), V), 1, 3, 6) {
|
||||
REQUIRE(Nttp_Fixture<V>::value == 0);
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails","[.][class][template][product][failing]",(std::vector,Template_Foo),(int,float))
|
||||
{
|
||||
REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 );
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG based test run that fails", "[.][class][template][product][nttp][failing]", ((typename T, size_t S), T, S), (std::array, Template_Foo_2), ((int, 2), (float, 6)))
|
||||
{
|
||||
REQUIRE(Template_Fixture_2<TestType>{}.m_a.size() < 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace ClassTests
|
230
tests/SelfTest/UsageTests/Compilation.tests.cpp
Normal file
230
tests/SelfTest/UsageTests/Compilation.tests.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Created by Martin on 17/02/2017.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
// Setup for #1403 -- look for global overloads of operator << for classes
|
||||
// in a different namespace.
|
||||
#include <ostream>
|
||||
|
||||
namespace foo {
|
||||
struct helper_1403 {
|
||||
bool operator==(helper_1403) const { return true; }
|
||||
};
|
||||
}
|
||||
|
||||
namespace bar {
|
||||
template <typename... Ts>
|
||||
struct TypeList {};
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
#endif
|
||||
std::ostream& operator<<(std::ostream& out, foo::helper_1403 const&) {
|
||||
return out << "[1403 helper]";
|
||||
}
|
||||
///////////////////////////////
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace { namespace CompilationTests {
|
||||
|
||||
#ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define COMPILATION_TEST_HELPERS_INCLUDED
|
||||
|
||||
// Comparison operators can return non-booleans.
|
||||
// This is unusual, but should be supported.
|
||||
struct logic_t {
|
||||
logic_t operator< (logic_t) const { return {}; }
|
||||
logic_t operator<=(logic_t) const { return {}; }
|
||||
logic_t operator> (logic_t) const { return {}; }
|
||||
logic_t operator>=(logic_t) const { return {}; }
|
||||
logic_t operator==(logic_t) const { return {}; }
|
||||
logic_t operator!=(logic_t) const { return {}; }
|
||||
explicit operator bool() const { return true; }
|
||||
};
|
||||
|
||||
|
||||
// This is a minimal example for an issue we have found in 1.7.0
|
||||
struct foo {
|
||||
int i;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool operator==(const T &val, foo f) {
|
||||
return val == f.i;
|
||||
}
|
||||
|
||||
struct Y {
|
||||
uint32_t v : 1;
|
||||
};
|
||||
|
||||
void throws_int(bool b) {
|
||||
if (b) {
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool templated_tests(T t) {
|
||||
int a = 3;
|
||||
REQUIRE(a == t);
|
||||
CHECK(a == t);
|
||||
REQUIRE_THROWS(throws_int(true));
|
||||
CHECK_THROWS_AS(throws_int(true), int);
|
||||
REQUIRE_NOTHROW(throws_int(false));
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
REQUIRE_THAT("aaa", Catch::EndsWith("aaa"));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
struct A {
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const A &) { return o << 0; }
|
||||
|
||||
struct B : private A {
|
||||
bool operator==(int) const { return true; }
|
||||
};
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
// Note that because -~GCC~-, this warning cannot be silenced temporarily, by pushing diagnostic stack...
|
||||
// Luckily it is firing in test files and thus can be silenced for the whole file, without losing much.
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
B f();
|
||||
|
||||
std::ostream g();
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
template <typename, typename>
|
||||
struct Fixture_1245 {};
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE("#809") {
|
||||
foo f;
|
||||
f.i = 42;
|
||||
REQUIRE(42 == f);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Changes to REQUIRE_THROWS_AS made it stop working in a template in
|
||||
// an unfixable way (as long as C++03 compatibility is being kept).
|
||||
// To prevent these from happening in the future, this needs to compile
|
||||
|
||||
TEST_CASE("#833") {
|
||||
REQUIRE(templated_tests<int>(3));
|
||||
}
|
||||
|
||||
|
||||
// Test containing example where original stream insertable check breaks compilation
|
||||
|
||||
|
||||
TEST_CASE("#872") {
|
||||
A dummy;
|
||||
CAPTURE(dummy);
|
||||
B x;
|
||||
REQUIRE (x == 4);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("#1027") {
|
||||
Y y{0};
|
||||
REQUIRE(y.v == 0);
|
||||
REQUIRE(0 == y.v);
|
||||
}
|
||||
|
||||
// Comparison operators can return non-booleans.
|
||||
// This is unusual, but should be supported.
|
||||
TEST_CASE("#1147") {
|
||||
logic_t t1, t2;
|
||||
REQUIRE(t1 == t2);
|
||||
REQUIRE(t1 != t2);
|
||||
REQUIRE(t1 < t2);
|
||||
REQUIRE(t1 > t2);
|
||||
REQUIRE(t1 <= t2);
|
||||
REQUIRE(t1 >= t2);
|
||||
}
|
||||
|
||||
// unsigned array
|
||||
TEST_CASE("#1238") {
|
||||
unsigned char uarr[] = "123";
|
||||
CAPTURE(uarr);
|
||||
signed char sarr[] = "456";
|
||||
CAPTURE(sarr);
|
||||
|
||||
REQUIRE(std::memcmp(uarr, "123", sizeof(uarr)) == 0);
|
||||
REQUIRE(std::memcmp(sarr, "456", sizeof(sarr)) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD((Fixture_1245<int, int>), "#1245", "[compilation]") {
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST_CASE("#1403", "[compilation]") {
|
||||
::foo::helper_1403 h1, h2;
|
||||
REQUIRE(h1 == h2);
|
||||
}
|
||||
|
||||
TEST_CASE("Optionally static assertions", "[compilation]") {
|
||||
STATIC_REQUIRE( std::is_void<void>::value );
|
||||
STATIC_REQUIRE_FALSE( std::is_void<int>::value );
|
||||
}
|
||||
|
||||
TEST_CASE("#1548", "[compilation]") {
|
||||
using namespace bar;
|
||||
REQUIRE(std::is_same<TypeList<int>, TypeList<int>>::value);
|
||||
}
|
||||
|
||||
// #925
|
||||
using signal_t = void (*) (void*);
|
||||
|
||||
struct TestClass {
|
||||
signal_t testMethod_uponComplete_arg = nullptr;
|
||||
};
|
||||
|
||||
namespace utility {
|
||||
inline static void synchronizing_callback( void * ) { }
|
||||
}
|
||||
|
||||
TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) {
|
||||
TestClass test;
|
||||
REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg);
|
||||
}
|
||||
|
||||
TEST_CASE( "#1027: Bitfields can be captured" ) {
|
||||
struct Y {
|
||||
uint32_t v : 1;
|
||||
};
|
||||
Y y{ 0 };
|
||||
REQUIRE( y.v == 0 );
|
||||
REQUIRE( 0 == y.v );
|
||||
}
|
||||
|
||||
TEST_CASE("#1319: Sections can have description (even if it is not saved", "[compilation]") {
|
||||
SECTION("SectionName", "This is a long form section description") {
|
||||
SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace CompilationTests
|
||||
|
334
tests/SelfTest/UsageTests/Condition.tests.cpp
Normal file
334
tests/SelfTest/UsageTests/Condition.tests.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Created by Phil on 08/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wpadded"
|
||||
// Wdouble-promotion is not supported until 3.8
|
||||
# if (__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ > 7)
|
||||
# pragma clang diagnostic ignored "-Wdouble-promotion"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
|
||||
namespace { namespace ConditionTests {
|
||||
|
||||
#ifndef CONDITION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define CONDITION_TEST_HELPERS_INCLUDED
|
||||
|
||||
struct TestData {
|
||||
int int_seven = 7;
|
||||
std::string str_hello = "hello";
|
||||
float float_nine_point_one = 9.1f;
|
||||
double double_pi = 3.1415926535;
|
||||
};
|
||||
|
||||
struct TestDef {
|
||||
TestDef& operator + ( const std::string& ) {
|
||||
return *this;
|
||||
}
|
||||
TestDef& operator[]( const std::string& ) {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
inline const char* returnsConstNull(){ return nullptr; }
|
||||
inline char* returnsNull(){ return nullptr; }
|
||||
|
||||
#endif
|
||||
|
||||
// The "failing" tests all use the CHECK macro, which continues if the specific test fails.
|
||||
// This allows us to see all results, even if an earlier check fails
|
||||
|
||||
// Equality tests
|
||||
TEST_CASE( "Equality checks that should succeed" )
|
||||
{
|
||||
TestDef td;
|
||||
td + "hello" + "hello";
|
||||
|
||||
TestData data;
|
||||
|
||||
REQUIRE( data.int_seven == 7 );
|
||||
REQUIRE( data.float_nine_point_one == Approx( 9.1f ) );
|
||||
REQUIRE( data.double_pi == Approx( 3.1415926535 ) );
|
||||
REQUIRE( data.str_hello == "hello" );
|
||||
REQUIRE( "hello" == data.str_hello );
|
||||
REQUIRE( data.str_hello.size() == 5 );
|
||||
|
||||
double x = 1.1 + 0.1 + 0.1;
|
||||
REQUIRE( x == Approx( 1.3 ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" )
|
||||
{
|
||||
TestData data;
|
||||
|
||||
CHECK( data.int_seven == 6 );
|
||||
CHECK( data.int_seven == 8 );
|
||||
CHECK( data.int_seven == 0 );
|
||||
CHECK( data.float_nine_point_one == Approx( 9.11f ) );
|
||||
CHECK( data.float_nine_point_one == Approx( 9.0f ) );
|
||||
CHECK( data.float_nine_point_one == Approx( 1 ) );
|
||||
CHECK( data.float_nine_point_one == Approx( 0 ) );
|
||||
CHECK( data.double_pi == Approx( 3.1415 ) );
|
||||
CHECK( data.str_hello == "goodbye" );
|
||||
CHECK( data.str_hello == "hell" );
|
||||
CHECK( data.str_hello == "hello1" );
|
||||
CHECK( data.str_hello.size() == 6 );
|
||||
|
||||
double x = 1.1 + 0.1 + 0.1;
|
||||
CHECK( x == Approx( 1.301 ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "Inequality checks that should succeed" )
|
||||
{
|
||||
TestData data;
|
||||
|
||||
REQUIRE( data.int_seven != 6 );
|
||||
REQUIRE( data.int_seven != 8 );
|
||||
REQUIRE( data.float_nine_point_one != Approx( 9.11f ) );
|
||||
REQUIRE( data.float_nine_point_one != Approx( 9.0f ) );
|
||||
REQUIRE( data.float_nine_point_one != Approx( 1 ) );
|
||||
REQUIRE( data.float_nine_point_one != Approx( 0 ) );
|
||||
REQUIRE( data.double_pi != Approx( 3.1415 ) );
|
||||
REQUIRE( data.str_hello != "goodbye" );
|
||||
REQUIRE( data.str_hello != "hell" );
|
||||
REQUIRE( data.str_hello != "hello1" );
|
||||
REQUIRE( data.str_hello.size() != 6 );
|
||||
}
|
||||
|
||||
TEST_CASE( "Inequality checks that should fail", "[.][failing][!shouldfail]" )
|
||||
{
|
||||
TestData data;
|
||||
|
||||
CHECK( data.int_seven != 7 );
|
||||
CHECK( data.float_nine_point_one != Approx( 9.1f ) );
|
||||
CHECK( data.double_pi != Approx( 3.1415926535 ) );
|
||||
CHECK( data.str_hello != "hello" );
|
||||
CHECK( data.str_hello.size() != 5 );
|
||||
}
|
||||
|
||||
// Ordering comparison tests
|
||||
TEST_CASE( "Ordering comparison checks that should succeed" )
|
||||
{
|
||||
TestData data;
|
||||
|
||||
REQUIRE( data.int_seven < 8 );
|
||||
REQUIRE( data.int_seven > 6 );
|
||||
REQUIRE( data.int_seven > 0 );
|
||||
REQUIRE( data.int_seven > -1 );
|
||||
|
||||
REQUIRE( data.int_seven >= 7 );
|
||||
REQUIRE( data.int_seven >= 6 );
|
||||
REQUIRE( data.int_seven <= 7 );
|
||||
REQUIRE( data.int_seven <= 8 );
|
||||
|
||||
REQUIRE( data.float_nine_point_one > 9 );
|
||||
REQUIRE( data.float_nine_point_one < 10 );
|
||||
REQUIRE( data.float_nine_point_one < 9.2 );
|
||||
|
||||
REQUIRE( data.str_hello <= "hello" );
|
||||
REQUIRE( data.str_hello >= "hello" );
|
||||
|
||||
REQUIRE( data.str_hello < "hellp" );
|
||||
REQUIRE( data.str_hello < "zebra" );
|
||||
REQUIRE( data.str_hello > "hellm" );
|
||||
REQUIRE( data.str_hello > "a" );
|
||||
}
|
||||
|
||||
TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" )
|
||||
{
|
||||
TestData data;
|
||||
|
||||
CHECK( data.int_seven > 7 );
|
||||
CHECK( data.int_seven < 7 );
|
||||
CHECK( data.int_seven > 8 );
|
||||
CHECK( data.int_seven < 6 );
|
||||
CHECK( data.int_seven < 0 );
|
||||
CHECK( data.int_seven < -1 );
|
||||
|
||||
CHECK( data.int_seven >= 8 );
|
||||
CHECK( data.int_seven <= 6 );
|
||||
|
||||
CHECK( data.float_nine_point_one < 9 );
|
||||
CHECK( data.float_nine_point_one > 10 );
|
||||
CHECK( data.float_nine_point_one > 9.2 );
|
||||
|
||||
CHECK( data.str_hello > "hello" );
|
||||
CHECK( data.str_hello < "hello" );
|
||||
CHECK( data.str_hello > "hellp" );
|
||||
CHECK( data.str_hello > "z" );
|
||||
CHECK( data.str_hello < "hellm" );
|
||||
CHECK( data.str_hello < "a" );
|
||||
|
||||
CHECK( data.str_hello >= "z" );
|
||||
CHECK( data.str_hello <= "a" );
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
// Comparisons with int literals
|
||||
TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned" )
|
||||
{
|
||||
int i = 1;
|
||||
unsigned int ui = 2;
|
||||
long l = 3;
|
||||
unsigned long ul = 4;
|
||||
char c = 5;
|
||||
unsigned char uc = 6;
|
||||
|
||||
REQUIRE( i == 1 );
|
||||
REQUIRE( ui == 2 );
|
||||
REQUIRE( l == 3 );
|
||||
REQUIRE( ul == 4 );
|
||||
REQUIRE( c == 5 );
|
||||
REQUIRE( uc == 6 );
|
||||
|
||||
REQUIRE( 1 == i );
|
||||
REQUIRE( 2 == ui );
|
||||
REQUIRE( 3 == l );
|
||||
REQUIRE( 4 == ul );
|
||||
REQUIRE( 5 == c );
|
||||
REQUIRE( 6 == uc );
|
||||
|
||||
REQUIRE( (std::numeric_limits<uint32_t>::max)() > ul );
|
||||
}
|
||||
|
||||
// Disable warnings about sign conversions for the next two tests
|
||||
// (as we are deliberately invoking them)
|
||||
// - Currently only disabled for GCC/ LLVM. Should add VC++ too
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
TEST_CASE( "comparisons between int variables" )
|
||||
{
|
||||
long long_var = 1L;
|
||||
unsigned char unsigned_char_var = 1;
|
||||
unsigned short unsigned_short_var = 1;
|
||||
unsigned int unsigned_int_var = 1;
|
||||
unsigned long unsigned_long_var = 1L;
|
||||
|
||||
REQUIRE( long_var == unsigned_char_var );
|
||||
REQUIRE( long_var == unsigned_short_var );
|
||||
REQUIRE( long_var == unsigned_int_var );
|
||||
REQUIRE( long_var == unsigned_long_var );
|
||||
}
|
||||
|
||||
TEST_CASE( "comparisons between const int variables" )
|
||||
{
|
||||
const unsigned char unsigned_char_var = 1;
|
||||
const unsigned short unsigned_short_var = 1;
|
||||
const unsigned int unsigned_int_var = 1;
|
||||
const unsigned long unsigned_long_var = 1L;
|
||||
|
||||
REQUIRE( unsigned_char_var == 1 );
|
||||
REQUIRE( unsigned_short_var == 1 );
|
||||
REQUIRE( unsigned_int_var == 1 );
|
||||
REQUIRE( unsigned_long_var == 1 );
|
||||
}
|
||||
|
||||
TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" )
|
||||
{
|
||||
CHECK( ( -1 > 2u ) );
|
||||
CHECK( -1 > 2u );
|
||||
|
||||
CHECK( ( 2u < -1 ) );
|
||||
CHECK( 2u < -1 );
|
||||
|
||||
const int minInt = (std::numeric_limits<int>::min)();
|
||||
CHECK( ( minInt > 2u ) );
|
||||
CHECK( minInt > 2u );
|
||||
}
|
||||
|
||||
TEST_CASE( "Comparisons between ints where one side is computed" )
|
||||
{
|
||||
CHECK( 54 == 6*9 );
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
TEST_CASE( "Pointers can be compared to null" )
|
||||
{
|
||||
TestData* p = nullptr;
|
||||
TestData* pNULL = nullptr;
|
||||
|
||||
REQUIRE( p == nullptr );
|
||||
REQUIRE( p == pNULL );
|
||||
|
||||
TestData data;
|
||||
p = &data;
|
||||
|
||||
REQUIRE( p != nullptr );
|
||||
|
||||
const TestData* cp = p;
|
||||
REQUIRE( cp != nullptr );
|
||||
|
||||
const TestData* const cpc = p;
|
||||
REQUIRE( cpc != nullptr );
|
||||
|
||||
REQUIRE( returnsNull() == nullptr );
|
||||
REQUIRE( returnsConstNull() == nullptr );
|
||||
|
||||
REQUIRE( nullptr != p );
|
||||
}
|
||||
|
||||
// Not (!) tests
|
||||
// The problem with the ! operator is that it has right-to-left associativity.
|
||||
// This means we can't isolate it when we decompose. The simple REQUIRE( !false ) form, therefore,
|
||||
// cannot have the operand value extracted. The test will work correctly, and the situation
|
||||
// is detected and a warning issued.
|
||||
// An alternative form of the macros (CHECK_FALSE and REQUIRE_FALSE) can be used instead to capture
|
||||
// the operand value.
|
||||
TEST_CASE( "'Not' checks that should succeed" )
|
||||
{
|
||||
bool falseValue = false;
|
||||
|
||||
REQUIRE( false == false );
|
||||
REQUIRE( true == true );
|
||||
REQUIRE( !false );
|
||||
REQUIRE_FALSE( false );
|
||||
|
||||
REQUIRE( !falseValue );
|
||||
REQUIRE_FALSE( falseValue );
|
||||
|
||||
REQUIRE( !(1 == 2) );
|
||||
REQUIRE_FALSE( 1 == 2 );
|
||||
}
|
||||
|
||||
TEST_CASE( "'Not' checks that should fail", "[.][failing]" )
|
||||
{
|
||||
bool trueValue = true;
|
||||
|
||||
CHECK( false != false );
|
||||
CHECK( true != true );
|
||||
CHECK( !true );
|
||||
CHECK_FALSE( true );
|
||||
|
||||
CHECK( !trueValue );
|
||||
CHECK_FALSE( trueValue );
|
||||
|
||||
CHECK( !(1 == 1) );
|
||||
CHECK_FALSE( 1 == 1 );
|
||||
}
|
||||
|
||||
}} // namespace ConditionTests
|
39
tests/SelfTest/UsageTests/Decomposition.tests.cpp
Normal file
39
tests/SelfTest/UsageTests/Decomposition.tests.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Created by Martin on 27/5/2017.
|
||||
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
|
||||
namespace {
|
||||
|
||||
struct truthy {
|
||||
truthy(bool b):m_value(b){}
|
||||
operator bool() const {
|
||||
return false;
|
||||
}
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, truthy) {
|
||||
o << "Hey, its truthy!";
|
||||
return o;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE( "Reconstruction should be based on stringification: #914" , "[Decomposition][failing][.]") {
|
||||
CHECK(truthy(false));
|
||||
}
|
||||
|
||||
TEST_CASE("#1005: Comparing pointer to int and long (NULL can be either on various systems)", "[Decomposition]") {
|
||||
FILE* fptr = nullptr;
|
||||
REQUIRE(fptr == 0);
|
||||
REQUIRE(fptr == 0l);
|
||||
}
|
99
tests/SelfTest/UsageTests/EnumToString.tests.cpp
Normal file
99
tests/SelfTest/UsageTests/EnumToString.tests.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
// Enum without user-provided stream operator
|
||||
enum Enum1 { Enum1Value0, Enum1Value1 };
|
||||
|
||||
// Enum with user-provided stream operator
|
||||
enum Enum2 { Enum2Value0, Enum2Value1 };
|
||||
|
||||
std::ostream& operator<<( std::ostream& os, Enum2 v ) {
|
||||
return os << "E2{" << static_cast<int>(v) << "}";
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
TEST_CASE( "toString(enum)", "[toString][enum]" ) {
|
||||
Enum1 e0 = Enum1Value0;
|
||||
CHECK( ::Catch::Detail::stringify(e0) == "0" );
|
||||
Enum1 e1 = Enum1Value1;
|
||||
CHECK( ::Catch::Detail::stringify(e1) == "1" );
|
||||
}
|
||||
|
||||
TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) {
|
||||
Enum2 e0 = Enum2Value0;
|
||||
CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" );
|
||||
Enum2 e1 = Enum2Value1;
|
||||
CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" );
|
||||
}
|
||||
|
||||
// Enum class without user-provided stream operator
|
||||
namespace {
|
||||
enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 };
|
||||
|
||||
// Enum class with user-provided stream operator
|
||||
enum class EnumClass2 { EnumClass2Value0, EnumClass2Value1 };
|
||||
|
||||
std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
|
||||
switch( static_cast<int>( e2 ) ) {
|
||||
case static_cast<int>( EnumClass2::EnumClass2Value0 ):
|
||||
return os << "E2/V0";
|
||||
case static_cast<int>( EnumClass2::EnumClass2Value1 ):
|
||||
return os << "E2/V1";
|
||||
default:
|
||||
return os << "Unknown enum value " << static_cast<int>( e2 );
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) {
|
||||
EnumClass1 e0 = EnumClass1::EnumClass1Value0;
|
||||
CHECK( ::Catch::Detail::stringify(e0) == "0" );
|
||||
EnumClass1 e1 = EnumClass1::EnumClass1Value1;
|
||||
CHECK( ::Catch::Detail::stringify(e1) == "1" );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) {
|
||||
EnumClass2 e0 = EnumClass2::EnumClass2Value0;
|
||||
CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" );
|
||||
EnumClass2 e1 = EnumClass2::EnumClass2Value1;
|
||||
CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" );
|
||||
|
||||
auto e3 = static_cast<EnumClass2>(10);
|
||||
CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" );
|
||||
}
|
||||
|
||||
enum class EnumClass3 { Value1, Value2, Value3, Value4 };
|
||||
|
||||
CATCH_REGISTER_ENUM( EnumClass3, EnumClass3::Value1, EnumClass3::Value2, EnumClass3::Value3 )
|
||||
|
||||
|
||||
TEST_CASE( "Enums can quickly have stringification enabled using REGISTER_ENUM" ) {
|
||||
using Catch::Detail::stringify;
|
||||
REQUIRE( stringify( EnumClass3::Value1 ) == "Value1" );
|
||||
REQUIRE( stringify( EnumClass3::Value2 ) == "Value2" );
|
||||
REQUIRE( stringify( EnumClass3::Value3 ) == "Value3" );
|
||||
REQUIRE( stringify( EnumClass3::Value4 ) == "{** unexpected enum value **}" );
|
||||
|
||||
EnumClass3 ec3 = EnumClass3 ::Value2;
|
||||
REQUIRE( stringify( ec3 ) == "Value2" );
|
||||
}
|
||||
|
||||
namespace Bikeshed {
|
||||
enum class Colours { Red, Green, Blue };
|
||||
}
|
||||
|
||||
// Important!: This macro must appear at top level scope - not inside a namespace
|
||||
// You can fully qualify the names, or use a using if you prefer
|
||||
CATCH_REGISTER_ENUM( Bikeshed::Colours,
|
||||
Bikeshed::Colours::Red,
|
||||
Bikeshed::Colours::Green,
|
||||
Bikeshed::Colours::Blue )
|
||||
|
||||
TEST_CASE( "Enums in namespaces can quickly have stringification enabled using REGISTER_ENUM" ) {
|
||||
using Catch::Detail::stringify;
|
||||
REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" );
|
||||
REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" );
|
||||
}
|
210
tests/SelfTest/UsageTests/Exception.tests.cpp
Normal file
210
tests/SelfTest/UsageTests/Exception.tests.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Created by Phil on 09/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4702) // Unreachable code -- unconditional throws and so on
|
||||
#endif
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
||||
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
|
||||
namespace { namespace ExceptionTests {
|
||||
|
||||
#ifndef EXCEPTION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define EXCEPTION_TEST_HELPERS_INCLUDED
|
||||
|
||||
int thisThrows() {
|
||||
throw std::domain_error( "expected exception" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int thisDoesntThrow() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
class CustomException {
|
||||
public:
|
||||
explicit CustomException( const std::string& msg )
|
||||
: m_msg( msg )
|
||||
{}
|
||||
|
||||
std::string getMessage() const {
|
||||
return m_msg;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
class CustomStdException : public std::exception {
|
||||
public:
|
||||
explicit CustomStdException( const std::string& msg )
|
||||
: m_msg( msg )
|
||||
{}
|
||||
~CustomStdException() noexcept override {}
|
||||
|
||||
std::string getMessage() const {
|
||||
return m_msg;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
[[noreturn]] void throwCustom() {
|
||||
throw CustomException( "custom exception - not std" );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE( "When checked exceptions are thrown they can be expected or unexpected", "[!throws]" ) {
|
||||
REQUIRE_THROWS_AS( thisThrows(), std::domain_error );
|
||||
REQUIRE_NOTHROW( thisDoesntThrow() );
|
||||
REQUIRE_THROWS( thisThrows() );
|
||||
}
|
||||
|
||||
TEST_CASE( "Expected exceptions that don't throw or unexpected exceptions fail the test", "[.][failing][!throws]" ) {
|
||||
CHECK_THROWS_AS( thisThrows(), std::string );
|
||||
CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error );
|
||||
CHECK_NOTHROW( thisThrows() );
|
||||
}
|
||||
|
||||
TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing][!throws]" ) {
|
||||
throw std::domain_error( "unexpected exception" );
|
||||
}
|
||||
|
||||
TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing][!throws]" ) {
|
||||
CHECK( 1 == 1 );
|
||||
throw std::domain_error( "unexpected exception" );
|
||||
}
|
||||
|
||||
TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing][!throws]" ) {
|
||||
SECTION( "section name" ) {
|
||||
throw std::domain_error("unexpected exception");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "When unchecked exceptions are thrown from functions they are always failures", "[.][failing][!throws]" ) {
|
||||
CHECK( thisThrows() == 0 );
|
||||
}
|
||||
|
||||
TEST_CASE( "When unchecked exceptions are thrown during a REQUIRE the test should abort fail", "[.][failing][!throws]" ) {
|
||||
REQUIRE( thisThrows() == 0 );
|
||||
FAIL( "This should never happen" );
|
||||
}
|
||||
|
||||
TEST_CASE( "When unchecked exceptions are thrown during a CHECK the test should continue", "[.][failing][!throws]" ) {
|
||||
try {
|
||||
CHECK(thisThrows() == 0);
|
||||
}
|
||||
catch(...) {
|
||||
FAIL( "This should never happen" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "When unchecked exceptions are thrown, but caught, they do not affect the test", "[!throws]" ) {
|
||||
try {
|
||||
throw std::domain_error( "unexpected exception" );
|
||||
}
|
||||
catch(...) {}
|
||||
}
|
||||
|
||||
|
||||
CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) {
|
||||
return ex.getMessage();
|
||||
}
|
||||
|
||||
CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) {
|
||||
return ex.getMessage();
|
||||
}
|
||||
|
||||
CATCH_TRANSLATE_EXCEPTION( double& ex ) {
|
||||
return Catch::Detail::stringify( ex );
|
||||
}
|
||||
|
||||
TEST_CASE("Non-std exceptions can be translated", "[.][failing][!throws]" ) {
|
||||
throw CustomException( "custom exception" );
|
||||
}
|
||||
|
||||
TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing][!throws]" ) {
|
||||
throw CustomException( "custom std exception" );
|
||||
}
|
||||
|
||||
TEST_CASE( "Custom exceptions can be translated when testing for nothrow", "[.][failing][!throws]" ) {
|
||||
REQUIRE_NOTHROW( throwCustom() );
|
||||
}
|
||||
|
||||
TEST_CASE( "Custom exceptions can be translated when testing for throwing as something else", "[.][failing][!throws]" ) {
|
||||
REQUIRE_THROWS_AS( throwCustom(), std::exception );
|
||||
}
|
||||
|
||||
TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]" ) {
|
||||
throw double( 3.14 );
|
||||
}
|
||||
|
||||
TEST_CASE("Thrown string literals are translated", "[.][failing][!throws]") {
|
||||
throw "For some reason someone is throwing a string literal!";
|
||||
}
|
||||
|
||||
TEST_CASE("thrown std::strings are translated", "[.][failing][!throws]") {
|
||||
throw std::string{ "Why would you throw a std::string?" };
|
||||
}
|
||||
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
|
||||
TEST_CASE( "Exception messages can be tested for", "[!throws]" ) {
|
||||
using namespace Catch::Matchers;
|
||||
SECTION( "exact match" )
|
||||
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
|
||||
SECTION( "different case" )
|
||||
REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) );
|
||||
SECTION( "wildcarded" ) {
|
||||
REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) );
|
||||
REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) );
|
||||
REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) );
|
||||
REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!throws]" ) {
|
||||
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
|
||||
REQUIRE_THROWS_WITH( thisThrows(), "should fail" );
|
||||
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
|
||||
}
|
||||
|
||||
TEST_CASE( "#748 - captures with unexpected exceptions", "[.][failing][!throws][!shouldfail]" ) {
|
||||
int answer = 42;
|
||||
CAPTURE( answer );
|
||||
// the message should be printed on the first two sections but not on the third
|
||||
SECTION( "outside assertions" ) {
|
||||
thisThrows();
|
||||
}
|
||||
SECTION( "inside REQUIRE_NOTHROW" ) {
|
||||
REQUIRE_NOTHROW( thisThrows() );
|
||||
}
|
||||
SECTION( "inside REQUIRE_THROWS" ) {
|
||||
REQUIRE_THROWS( thisThrows() );
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace ExceptionTests
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
256
tests/SelfTest/UsageTests/Generators.tests.cpp
Normal file
256
tests/SelfTest/UsageTests/Generators.tests.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
// Generators and sections can be nested freely
|
||||
TEST_CASE("Generators -- simple", "[generators]") {
|
||||
auto i = GENERATE(1, 2, 3);
|
||||
SECTION("one") {
|
||||
auto j = GENERATE(values({ -3, -2, -1 }));
|
||||
REQUIRE(j < i);
|
||||
}
|
||||
|
||||
SECTION("two") {
|
||||
// You can also explicitly set type for generators via Catch::Generators::as
|
||||
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
|
||||
REQUIRE(4u * i > str.size());
|
||||
}
|
||||
}
|
||||
|
||||
// You can create a cartesian-product of generators by creating multiple ones
|
||||
TEST_CASE("3x3x3 ints", "[generators]") {
|
||||
auto x = GENERATE(1, 2, 3);
|
||||
auto y = GENERATE(4, 5, 6);
|
||||
auto z = GENERATE(7, 8, 9);
|
||||
// These assertions will be run 27 times (3x3x3)
|
||||
CHECK(x < y);
|
||||
CHECK(y < z);
|
||||
REQUIRE(x < z);
|
||||
}
|
||||
|
||||
// You can also create data tuples
|
||||
TEST_CASE("tables", "[generators]") {
|
||||
// Note that this will not compile with libstdc++ older than libstdc++6
|
||||
// See https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
|
||||
// for possible workarounds
|
||||
// auto data = GENERATE(table<char const*, int>({
|
||||
// {"first", 5},
|
||||
// {"second", 6},
|
||||
// {"third", 5},
|
||||
// {"etc...", 6}
|
||||
// }));
|
||||
|
||||
// Workaround for the libstdc++ bug mentioned above
|
||||
using tuple_type = std::tuple<char const*, int>;
|
||||
auto data = GENERATE(table<char const*, int>({
|
||||
tuple_type{"first", 5},
|
||||
tuple_type{"second", 6},
|
||||
tuple_type{"third", 5},
|
||||
tuple_type{"etc...", 6}
|
||||
}));
|
||||
|
||||
REQUIRE(strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)));
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cpp_structured_bindings
|
||||
|
||||
// Structured bindings make the table utility much nicer to use
|
||||
TEST_CASE( "strlen2", "[approvals][generators]" ) {
|
||||
auto [test_input, expected] = GENERATE( table<std::string, size_t>({
|
||||
{"one", 3},
|
||||
{"two", 3},
|
||||
{"three", 5},
|
||||
{"four", 4}
|
||||
}));
|
||||
|
||||
REQUIRE( test_input.size() == expected );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// An alternate way of doing data tables without structured bindings
|
||||
struct Data { std::string str; size_t len; };
|
||||
|
||||
TEST_CASE( "strlen3", "[generators]" ) {
|
||||
auto data = GENERATE( values<Data>({
|
||||
{"one", 3},
|
||||
{"two", 3},
|
||||
{"three", 5},
|
||||
{"four", 4}
|
||||
}));
|
||||
|
||||
REQUIRE( data.str.size() == data.len );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cpp_structured_bindings
|
||||
|
||||
// Based on example from https://docs.cucumber.io/gherkin/reference/#scenario-outline
|
||||
// (thanks to https://github.com/catchorg/Catch2/issues/850#issuecomment-399504851)
|
||||
|
||||
// Note that GIVEN, WHEN, and THEN now forward onto DYNAMIC_SECTION instead of SECTION.
|
||||
// DYNAMIC_SECTION takes its name as a stringstream-style expression, so can be formatted using
|
||||
// variables in scope - such as the generated variables here. This reads quite nicely in the
|
||||
// test name output (the full scenario description).
|
||||
|
||||
static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
|
||||
|
||||
SCENARIO("Eating cucumbers", "[generators][approvals]") {
|
||||
|
||||
auto [start, eat, left] = GENERATE( table<int,int,int> ({
|
||||
{ 12, 5, 7 },
|
||||
{ 20, 5, 15 }
|
||||
}));
|
||||
|
||||
GIVEN( "there are " << start << " cucumbers" )
|
||||
WHEN( "I eat " << eat << " cucumbers" )
|
||||
THEN( "I should have " << left << " cucumbers" ) {
|
||||
REQUIRE( eatCucumbers( start, eat ) == left );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// There are also some generic generator manipulators
|
||||
TEST_CASE("Generators -- adapters", "[generators][generic]") {
|
||||
// TODO: This won't work yet, introduce GENERATE_VAR?
|
||||
//auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 });
|
||||
SECTION("Filtering by predicate") {
|
||||
SECTION("Basic usage") {
|
||||
// This filters out all odd (false) numbers, giving [2, 4, 6]
|
||||
auto i = GENERATE(filter([] (int val) { return val % 2 == 0; }, values({ 1, 2, 3, 4, 5, 6 })));
|
||||
REQUIRE(i % 2 == 0);
|
||||
}
|
||||
SECTION("Throws if there are no matching values") {
|
||||
using namespace Catch::Generators;
|
||||
REQUIRE_THROWS_AS(filter([] (int) {return false; }, value(1)), Catch::GeneratorException);
|
||||
}
|
||||
}
|
||||
SECTION("Shortening a range") {
|
||||
// This takes the first 3 elements from the values, giving back [1, 2, 3]
|
||||
auto i = GENERATE(take(3, values({ 1, 2, 3, 4, 5, 6 })));
|
||||
REQUIRE(i < 4);
|
||||
}
|
||||
SECTION("Transforming elements") {
|
||||
SECTION("Same type") {
|
||||
// This doubles values [1, 2, 3] into [2, 4, 6]
|
||||
auto i = GENERATE(map([] (int val) { return val * 2; }, values({ 1, 2, 3 })));
|
||||
REQUIRE(i % 2 == 0);
|
||||
}
|
||||
SECTION("Different type") {
|
||||
// This takes a generator that returns ints and maps them into strings
|
||||
auto i = GENERATE(map<std::string>([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
|
||||
REQUIRE(i.size() == 1);
|
||||
}
|
||||
SECTION("Different deduced type") {
|
||||
// This takes a generator that returns ints and maps them into strings
|
||||
auto i = GENERATE(map([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
|
||||
REQUIRE(i.size() == 1);
|
||||
}
|
||||
}
|
||||
SECTION("Repeating a generator") {
|
||||
// This will return values [1, 2, 3, 1, 2, 3]
|
||||
auto j = GENERATE(repeat(2, values({ 1, 2, 3 })));
|
||||
REQUIRE(j > 0);
|
||||
}
|
||||
SECTION("Chunking a generator into sized pieces") {
|
||||
SECTION("Number of elements in source is divisible by chunk size") {
|
||||
auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3, 3 })));
|
||||
REQUIRE(chunk2.size() == 2);
|
||||
REQUIRE(chunk2.front() == chunk2.back());
|
||||
}
|
||||
SECTION("Number of elements in source is not divisible by chunk size") {
|
||||
auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3 })));
|
||||
REQUIRE(chunk2.size() == 2);
|
||||
REQUIRE(chunk2.front() == chunk2.back());
|
||||
REQUIRE(chunk2.front() < 3);
|
||||
}
|
||||
SECTION("Chunk size of zero") {
|
||||
auto chunk2 = GENERATE(take(3, chunk(0, value(1))));
|
||||
REQUIRE(chunk2.size() == 0);
|
||||
}
|
||||
SECTION("Throws on too small generators") {
|
||||
using namespace Catch::Generators;
|
||||
REQUIRE_THROWS_AS(chunk(2, value(1)), Catch::GeneratorException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that because of the non-reproducibility of distributions,
|
||||
// anything involving the random generators cannot be part of approvals
|
||||
TEST_CASE("Random generator", "[generators][approvals]") {
|
||||
SECTION("Infer int from integral arguments") {
|
||||
auto val = GENERATE(take(4, random(0, 1)));
|
||||
STATIC_REQUIRE(std::is_same<decltype(val), int>::value);
|
||||
REQUIRE(0 <= val);
|
||||
REQUIRE(val <= 1);
|
||||
}
|
||||
SECTION("Infer double from double arguments") {
|
||||
auto val = GENERATE(take(4, random(0., 1.)));
|
||||
STATIC_REQUIRE(std::is_same<decltype(val), double>::value);
|
||||
REQUIRE(0. <= val);
|
||||
REQUIRE(val < 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Nested generators and captured variables", "[generators]") {
|
||||
// Workaround for old libstdc++
|
||||
using record = std::tuple<int, int>;
|
||||
// Set up 3 ranges to generate numbers from
|
||||
auto extent = GENERATE(table<int, int>({
|
||||
record{3, 7},
|
||||
record{-5, -3},
|
||||
record{90, 100}
|
||||
}));
|
||||
|
||||
auto from = std::get<0>(extent);
|
||||
auto to = std::get<1>(extent);
|
||||
|
||||
auto values = GENERATE_COPY(range(from, to));
|
||||
REQUIRE(values > -6);
|
||||
}
|
||||
|
||||
namespace {
|
||||
size_t call_count = 0;
|
||||
size_t test_count = 0;
|
||||
std::vector<int> make_data() {
|
||||
return { 1, 3, 5, 7, 9, 11 };
|
||||
}
|
||||
std::vector<int> make_data_counted() {
|
||||
++call_count;
|
||||
return make_data();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||
#endif
|
||||
|
||||
TEST_CASE("Copy and then generate a range", "[generators]") {
|
||||
SECTION("from var and iterators") {
|
||||
static auto data = make_data();
|
||||
|
||||
// It is important to notice that a generator is only initialized
|
||||
// **once** per run. What this means is that modifying data will not
|
||||
// modify the underlying generator.
|
||||
auto elem = GENERATE_REF(from_range(data.begin(), data.end()));
|
||||
REQUIRE(elem % 2 == 1);
|
||||
}
|
||||
SECTION("From a temporary container") {
|
||||
auto elem = GENERATE(from_range(make_data_counted()));
|
||||
++test_count;
|
||||
REQUIRE(elem % 2 == 1);
|
||||
}
|
||||
SECTION("Final validation") {
|
||||
REQUIRE(call_count == 1);
|
||||
REQUIRE(make_data().size() == test_count);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
562
tests/SelfTest/UsageTests/Matchers.tests.cpp
Normal file
562
tests/SelfTest/UsageTests/Matchers.tests.cpp
Normal file
@@ -0,0 +1,562 @@
|
||||
/*
|
||||
* Created by Phil on 21/02/2017.
|
||||
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
|
||||
namespace { namespace MatchersTests {
|
||||
|
||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||
|
||||
#ifndef MATCHERS_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define MATCHERS_TEST_HELPERS_INCLUDED
|
||||
|
||||
inline const char *testStringForMatching() {
|
||||
return "this string contains 'abc' as a substring";
|
||||
}
|
||||
|
||||
inline const char *testStringForMatching2() {
|
||||
return "some completely different text that contains one common word";
|
||||
}
|
||||
|
||||
inline bool alwaysTrue(int) { return true; }
|
||||
inline bool alwaysFalse(int) { return false; }
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
|
||||
#endif
|
||||
|
||||
#include <exception>
|
||||
|
||||
struct SpecialException : std::exception {
|
||||
SpecialException(int i_) : i(i_) {}
|
||||
|
||||
char const* what() const noexcept override {
|
||||
return "SpecialException::what";
|
||||
}
|
||||
|
||||
int i;
|
||||
};
|
||||
|
||||
struct DerivedException : std::exception {
|
||||
char const* what() const noexcept override {
|
||||
return "DerivedException::what";
|
||||
}
|
||||
};
|
||||
|
||||
void doesNotThrow() {}
|
||||
|
||||
[[noreturn]]
|
||||
void throwsSpecialException(int i) {
|
||||
throw SpecialException{i};
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void throwsAsInt(int i) {
|
||||
throw i;
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void throwsDerivedException() {
|
||||
throw DerivedException{};
|
||||
}
|
||||
|
||||
class ExceptionMatcher : public Catch::MatcherBase<SpecialException> {
|
||||
int m_expected;
|
||||
public:
|
||||
ExceptionMatcher(int i) : m_expected(i) {}
|
||||
|
||||
bool match(SpecialException const &se) const override {
|
||||
return se.i == m_expected;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
std::ostringstream ss;
|
||||
ss << "special exception has value of " << m_expected;
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
#ifdef __DJGPP__
|
||||
float nextafter(float from, float to)
|
||||
{
|
||||
return ::nextafterf(from, to);
|
||||
}
|
||||
|
||||
double nextafter(double from, double to)
|
||||
{
|
||||
return ::nextafter(from, to);
|
||||
}
|
||||
#else
|
||||
using std::nextafter;
|
||||
#endif
|
||||
|
||||
TEST_CASE("String matchers", "[matchers]") {
|
||||
REQUIRE_THAT(testStringForMatching(), Contains("string"));
|
||||
REQUIRE_THAT(testStringForMatching(), Contains("string", Catch::CaseSensitive::No));
|
||||
CHECK_THAT(testStringForMatching(), Contains("abc"));
|
||||
CHECK_THAT(testStringForMatching(), Contains("aBC", Catch::CaseSensitive::No));
|
||||
|
||||
CHECK_THAT(testStringForMatching(), StartsWith("this"));
|
||||
CHECK_THAT(testStringForMatching(), StartsWith("THIS", Catch::CaseSensitive::No));
|
||||
CHECK_THAT(testStringForMatching(), EndsWith("substring"));
|
||||
CHECK_THAT(testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No));
|
||||
}
|
||||
|
||||
TEST_CASE("Contains string matcher", "[.][failing][matchers]") {
|
||||
CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No));
|
||||
CHECK_THAT(testStringForMatching(), Contains("STRING"));
|
||||
}
|
||||
|
||||
TEST_CASE("StartsWith string matcher", "[.][failing][matchers]") {
|
||||
CHECK_THAT(testStringForMatching(), StartsWith("This String"));
|
||||
CHECK_THAT(testStringForMatching(), StartsWith("string", Catch::CaseSensitive::No));
|
||||
}
|
||||
|
||||
TEST_CASE("EndsWith string matcher", "[.][failing][matchers]") {
|
||||
CHECK_THAT(testStringForMatching(), EndsWith("Substring"));
|
||||
CHECK_THAT(testStringForMatching(), EndsWith("this", Catch::CaseSensitive::No));
|
||||
}
|
||||
|
||||
TEST_CASE("Equals string matcher", "[.][failing][matchers]") {
|
||||
CHECK_THAT(testStringForMatching(), Equals("this string contains 'ABC' as a substring"));
|
||||
CHECK_THAT(testStringForMatching(), Equals("something else", Catch::CaseSensitive::No));
|
||||
}
|
||||
|
||||
TEST_CASE("Equals", "[matchers]") {
|
||||
CHECK_THAT(testStringForMatching(), Equals("this string contains 'abc' as a substring"));
|
||||
CHECK_THAT(testStringForMatching(),
|
||||
Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No));
|
||||
}
|
||||
|
||||
// <regex> does not work in libstdc++ 4.8, so we have to enable these tests only when they
|
||||
// are expected to pass and cannot have them in baselines
|
||||
TEST_CASE("Regex string matcher -- libstdc++-4.8 workaround", "[matchers][approvals]") {
|
||||
|
||||
// This is fiiiine
|
||||
// Taken from an answer at
|
||||
// https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
|
||||
#if (!defined(__GNUC__)) || \
|
||||
(__cplusplus >= 201103L && \
|
||||
(!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
|
||||
(defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
|
||||
defined(_GLIBCXX_REGEX_STATE_LIMIT) || \
|
||||
(defined(_GLIBCXX_RELEASE) && \
|
||||
_GLIBCXX_RELEASE > 4))))
|
||||
|
||||
// DJGPP meets the above condition but <regex> does not work properly anyway
|
||||
#ifndef __DJGPP__
|
||||
REQUIRE_THAT(testStringForMatching(), Matches("this string contains 'abc' as a substring"));
|
||||
REQUIRE_THAT(testStringForMatching(),
|
||||
Matches("this string CONTAINS 'abc' as a substring", Catch::CaseSensitive::No));
|
||||
REQUIRE_THAT(testStringForMatching(), Matches("^this string contains 'abc' as a substring$"));
|
||||
REQUIRE_THAT(testStringForMatching(), Matches("^.* 'abc' .*$"));
|
||||
REQUIRE_THAT(testStringForMatching(), Matches("^.* 'ABC' .*$", Catch::CaseSensitive::No));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
REQUIRE_THAT(testStringForMatching2(), !Matches("this string contains 'abc' as a substring"));
|
||||
}
|
||||
|
||||
TEST_CASE("Regex string matcher", "[matchers][.failing]") {
|
||||
CHECK_THAT(testStringForMatching(), Matches("this STRING contains 'abc' as a substring"));
|
||||
CHECK_THAT(testStringForMatching(), Matches("contains 'abc' as a substring"));
|
||||
CHECK_THAT(testStringForMatching(), Matches("this string contains 'abc' as a"));
|
||||
}
|
||||
|
||||
TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") {
|
||||
CHECK_THAT(testStringForMatching(),
|
||||
Contains("string") &&
|
||||
Contains("abc") &&
|
||||
Contains("substring") &&
|
||||
Contains("contains"));
|
||||
}
|
||||
|
||||
TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") {
|
||||
CHECK_THAT(testStringForMatching(), Contains("string") || Contains("different") || Contains("random"));
|
||||
CHECK_THAT(testStringForMatching2(), Contains("string") || Contains("different") || Contains("random"));
|
||||
}
|
||||
|
||||
TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") {
|
||||
CHECK_THAT(testStringForMatching(), (Contains("string") || Contains("different")) && Contains("substring"));
|
||||
}
|
||||
|
||||
TEST_CASE("Matchers can be composed with both && and || - failing",
|
||||
"[matchers][operators][operator||][operator&&][.failing]") {
|
||||
CHECK_THAT(testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random"));
|
||||
}
|
||||
|
||||
TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") {
|
||||
CHECK_THAT(testStringForMatching(), !Contains("different"));
|
||||
}
|
||||
|
||||
TEST_CASE("Matchers can be negated (Not) with the ! operator - failing",
|
||||
"[matchers][operators][not][.failing]") {
|
||||
CHECK_THAT(testStringForMatching(), !Contains("substring"));
|
||||
}
|
||||
|
||||
TEST_CASE("Vector matchers", "[matchers][vector]") {
|
||||
std::vector<int> v;
|
||||
v.push_back(1);
|
||||
v.push_back(2);
|
||||
v.push_back(3);
|
||||
|
||||
std::vector<int> v2;
|
||||
v2.push_back(1);
|
||||
v2.push_back(2);
|
||||
|
||||
std::vector<double> v3;
|
||||
v3.push_back(1);
|
||||
v3.push_back(2);
|
||||
v3.push_back(3);
|
||||
|
||||
std::vector<double> v4;
|
||||
v4.push_back(1 + 1e-8);
|
||||
v4.push_back(2 + 1e-8);
|
||||
v4.push_back(3 + 1e-8);
|
||||
|
||||
std::vector<int> empty;
|
||||
|
||||
SECTION("Contains (element)") {
|
||||
CHECK_THAT(v, VectorContains(1));
|
||||
CHECK_THAT(v, VectorContains(2));
|
||||
}
|
||||
SECTION("Contains (vector)") {
|
||||
CHECK_THAT(v, Contains(v2));
|
||||
v2.push_back(3); // now exactly matches
|
||||
CHECK_THAT(v, Contains(v2));
|
||||
|
||||
CHECK_THAT(v, Contains(empty));
|
||||
CHECK_THAT(empty, Contains(empty));
|
||||
}
|
||||
SECTION("Contains (element), composed") {
|
||||
CHECK_THAT(v, VectorContains(1) && VectorContains(2));
|
||||
}
|
||||
|
||||
SECTION("Equals") {
|
||||
|
||||
// Same vector
|
||||
CHECK_THAT(v, Equals(v));
|
||||
|
||||
CHECK_THAT(empty, Equals(empty));
|
||||
|
||||
// Different vector with same elements
|
||||
v2.push_back(3);
|
||||
CHECK_THAT(v, Equals(v2));
|
||||
}
|
||||
SECTION("UnorderedEquals") {
|
||||
CHECK_THAT(v, UnorderedEquals(v));
|
||||
CHECK_THAT(empty, UnorderedEquals(empty));
|
||||
|
||||
auto permuted = v;
|
||||
std::next_permutation(begin(permuted), end(permuted));
|
||||
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||
|
||||
std::reverse(begin(permuted), end(permuted));
|
||||
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Vector matchers that fail", "[matchers][vector][.][failing]") {
|
||||
std::vector<int> v;
|
||||
v.push_back(1);
|
||||
v.push_back(2);
|
||||
v.push_back(3);
|
||||
|
||||
std::vector<int> v2;
|
||||
v2.push_back(1);
|
||||
v2.push_back(2);
|
||||
|
||||
std::vector<double> v3;
|
||||
v3.push_back(1);
|
||||
v3.push_back(2);
|
||||
v3.push_back(3);
|
||||
|
||||
std::vector<double> v4;
|
||||
v4.push_back(1.1);
|
||||
v4.push_back(2.1);
|
||||
v4.push_back(3.1);
|
||||
|
||||
std::vector<int> empty;
|
||||
|
||||
SECTION("Contains (element)") {
|
||||
CHECK_THAT(v, VectorContains(-1));
|
||||
CHECK_THAT(empty, VectorContains(1));
|
||||
}
|
||||
SECTION("Contains (vector)") {
|
||||
CHECK_THAT(empty, Contains(v));
|
||||
v2.push_back(4);
|
||||
CHECK_THAT(v, Contains(v2));
|
||||
}
|
||||
|
||||
SECTION("Equals") {
|
||||
|
||||
CHECK_THAT(v, Equals(v2));
|
||||
CHECK_THAT(v2, Equals(v));
|
||||
CHECK_THAT(empty, Equals(v));
|
||||
CHECK_THAT(v, Equals(empty));
|
||||
}
|
||||
SECTION("UnorderedEquals") {
|
||||
CHECK_THAT(v, UnorderedEquals(empty));
|
||||
CHECK_THAT(empty, UnorderedEquals(v));
|
||||
|
||||
auto permuted = v;
|
||||
std::next_permutation(begin(permuted), end(permuted));
|
||||
permuted.pop_back();
|
||||
CHECK_THAT(permuted, UnorderedEquals(v));
|
||||
|
||||
std::reverse(begin(permuted), end(permuted));
|
||||
CHECK_THAT(permuted, UnorderedEquals(v));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
|
||||
CHECK_THROWS_MATCHES(throwsSpecialException(1), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, ExceptionMatcher{2});
|
||||
}
|
||||
|
||||
TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") {
|
||||
SECTION("No exception") {
|
||||
CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{1});
|
||||
}
|
||||
SECTION("Type mismatch") {
|
||||
CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1});
|
||||
}
|
||||
SECTION("Contents are wrong") {
|
||||
CHECK_THROWS_MATCHES(throwsSpecialException(3), SpecialException, ExceptionMatcher{1});
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(4), SpecialException, ExceptionMatcher{1});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Floating point matchers: float", "[matchers][floating-point]") {
|
||||
SECTION("Relative") {
|
||||
REQUIRE_THAT(10.f, WithinRel(11.1f, 0.1f));
|
||||
REQUIRE_THAT(10.f, !WithinRel(11.2f, 0.1f));
|
||||
REQUIRE_THAT( 1.f, !WithinRel(0.f, 0.99f));
|
||||
REQUIRE_THAT(-0.f, WithinRel(0.f));
|
||||
SECTION("Some subnormal values") {
|
||||
auto v1 = std::numeric_limits<float>::min();
|
||||
auto v2 = v1;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
v2 = std::nextafter(v1, 0.f);
|
||||
}
|
||||
REQUIRE_THAT(v1, WithinRel(v2));
|
||||
}
|
||||
}
|
||||
SECTION("Margin") {
|
||||
REQUIRE_THAT(1.f, WithinAbs(1.f, 0));
|
||||
REQUIRE_THAT(0.f, WithinAbs(1.f, 1));
|
||||
|
||||
REQUIRE_THAT(0.f, !WithinAbs(1.f, 0.99f));
|
||||
REQUIRE_THAT(0.f, !WithinAbs(1.f, 0.99f));
|
||||
|
||||
REQUIRE_THAT(0.f, WithinAbs(-0.f, 0));
|
||||
|
||||
REQUIRE_THAT(11.f, !WithinAbs(10.f, 0.5f));
|
||||
REQUIRE_THAT(10.f, !WithinAbs(11.f, 0.5f));
|
||||
REQUIRE_THAT(-10.f, WithinAbs(-10.f, 0.5f));
|
||||
REQUIRE_THAT(-10.f, WithinAbs(-9.6f, 0.5f));
|
||||
}
|
||||
SECTION("ULPs") {
|
||||
REQUIRE_THAT(1.f, WithinULP(1.f, 0));
|
||||
|
||||
REQUIRE_THAT(nextafter(1.f, 2.f), WithinULP(1.f, 1));
|
||||
REQUIRE_THAT(0.f, WithinULP(nextafter(0.f, 1.f), 1));
|
||||
REQUIRE_THAT(1.f, WithinULP(nextafter(1.f, 0.f), 1));
|
||||
REQUIRE_THAT(1.f, !WithinULP(nextafter(1.f, 2.f), 0));
|
||||
|
||||
REQUIRE_THAT(1.f, WithinULP(1.f, 0));
|
||||
REQUIRE_THAT(-0.f, WithinULP(0.f, 0));
|
||||
}
|
||||
SECTION("Composed") {
|
||||
REQUIRE_THAT(1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1));
|
||||
REQUIRE_THAT(1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0));
|
||||
REQUIRE_THAT(0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f));
|
||||
}
|
||||
SECTION("Constructor validation") {
|
||||
REQUIRE_NOTHROW(WithinAbs(1.f, 0.f));
|
||||
REQUIRE_THROWS_AS(WithinAbs(1.f, -1.f), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinULP(1.f, 0));
|
||||
REQUIRE_THROWS_AS(WithinULP(1.f, static_cast<uint64_t>(-1)), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinRel(1.f, 0.f));
|
||||
REQUIRE_THROWS_AS(WithinRel(1.f, -0.2f), std::domain_error);
|
||||
REQUIRE_THROWS_AS(WithinRel(1.f, 1.f), std::domain_error);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") {
|
||||
SECTION("Relative") {
|
||||
REQUIRE_THAT(10., WithinRel(11.1, 0.1));
|
||||
REQUIRE_THAT(10., !WithinRel(11.2, 0.1));
|
||||
REQUIRE_THAT(1., !WithinRel(0., 0.99));
|
||||
REQUIRE_THAT(-0., WithinRel(0.));
|
||||
SECTION("Some subnormal values") {
|
||||
auto v1 = std::numeric_limits<double>::min();
|
||||
auto v2 = v1;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
v2 = std::nextafter(v1, 0);
|
||||
}
|
||||
REQUIRE_THAT(v1, WithinRel(v2));
|
||||
}
|
||||
}
|
||||
SECTION("Margin") {
|
||||
REQUIRE_THAT(1., WithinAbs(1., 0));
|
||||
REQUIRE_THAT(0., WithinAbs(1., 1));
|
||||
|
||||
REQUIRE_THAT(0., !WithinAbs(1., 0.99));
|
||||
REQUIRE_THAT(0., !WithinAbs(1., 0.99));
|
||||
|
||||
REQUIRE_THAT(11., !WithinAbs(10., 0.5));
|
||||
REQUIRE_THAT(10., !WithinAbs(11., 0.5));
|
||||
REQUIRE_THAT(-10., WithinAbs(-10., 0.5));
|
||||
REQUIRE_THAT(-10., WithinAbs(-9.6, 0.5));
|
||||
}
|
||||
SECTION("ULPs") {
|
||||
REQUIRE_THAT(1., WithinULP(1., 0));
|
||||
|
||||
REQUIRE_THAT(nextafter(1., 2.), WithinULP(1., 1));
|
||||
REQUIRE_THAT(0., WithinULP(nextafter(0., 1.), 1));
|
||||
REQUIRE_THAT(1., WithinULP(nextafter(1., 0.), 1));
|
||||
REQUIRE_THAT(1., !WithinULP(nextafter(1., 2.), 0));
|
||||
|
||||
REQUIRE_THAT(1., WithinULP(1., 0));
|
||||
REQUIRE_THAT(-0., WithinULP(0., 0));
|
||||
}
|
||||
SECTION("Composed") {
|
||||
REQUIRE_THAT(1., WithinAbs(1., 0.5) || WithinULP(2., 1));
|
||||
REQUIRE_THAT(1., WithinAbs(2., 0.5) || WithinULP(1., 0));
|
||||
REQUIRE_THAT(0.0001, WithinAbs(0., 0.001) || WithinRel(0., 0.1));
|
||||
}
|
||||
SECTION("Constructor validation") {
|
||||
REQUIRE_NOTHROW(WithinAbs(1., 0.));
|
||||
REQUIRE_THROWS_AS(WithinAbs(1., -1.), std::domain_error);
|
||||
|
||||
REQUIRE_NOTHROW(WithinULP(1., 0));
|
||||
|
||||
REQUIRE_NOTHROW(WithinRel(1., 0.));
|
||||
REQUIRE_THROWS_AS(WithinRel(1., -0.2), std::domain_error);
|
||||
REQUIRE_THROWS_AS(WithinRel(1., 1.), std::domain_error);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Floating point matchers that are problematic in approvals", "[approvals][matchers][floating-point]") {
|
||||
REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
|
||||
REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
|
||||
REQUIRE_THAT(NAN, !WithinULP(NAN, 123));
|
||||
REQUIRE_THAT(INFINITY, WithinRel(INFINITY));
|
||||
REQUIRE_THAT(-INFINITY, !WithinRel(INFINITY));
|
||||
REQUIRE_THAT(1., !WithinRel(INFINITY));
|
||||
REQUIRE_THAT(INFINITY, !WithinRel(1.));
|
||||
REQUIRE_THAT(NAN, !WithinRel(NAN));
|
||||
REQUIRE_THAT(1., !WithinRel(NAN));
|
||||
REQUIRE_THAT(NAN, !WithinRel(1.));
|
||||
}
|
||||
|
||||
TEST_CASE("Arbitrary predicate matcher", "[matchers][generic]") {
|
||||
SECTION("Function pointer") {
|
||||
REQUIRE_THAT(1, Predicate<int>(alwaysTrue, "always true"));
|
||||
REQUIRE_THAT(1, !Predicate<int>(alwaysFalse, "always false"));
|
||||
}
|
||||
SECTION("Lambdas + different type") {
|
||||
REQUIRE_THAT("Hello olleH",
|
||||
Predicate<std::string>(
|
||||
[] (std::string const& str) -> bool { return str.front() == str.back(); },
|
||||
"First and last character should be equal")
|
||||
);
|
||||
|
||||
REQUIRE_THAT("This wouldn't pass",
|
||||
!Predicate<std::string>(
|
||||
[] (std::string const& str) -> bool { return str.front() == str.back(); }
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Regression test #1", "[matchers][vector]") {
|
||||
// At some point, UnorderedEqualsMatcher skipped
|
||||
// mismatched prefixed before doing the comparison itself
|
||||
std::vector<char> actual = { 'a', 'b' };
|
||||
std::vector<char> expected = { 'c', 'b' };
|
||||
|
||||
CHECK_THAT(actual, !UnorderedEquals(expected));
|
||||
}
|
||||
|
||||
TEST_CASE("Predicate matcher can accept const char*", "[matchers][compilation]") {
|
||||
REQUIRE_THAT("foo", Predicate<const char*>([] (const char* const&) { return true; }));
|
||||
}
|
||||
|
||||
TEST_CASE("Vector Approx matcher", "[matchers][approx][vector]") {
|
||||
using Catch::Matchers::Approx;
|
||||
SECTION("Empty vector is roughly equal to an empty vector") {
|
||||
std::vector<double> empty;
|
||||
REQUIRE_THAT(empty, Approx(empty));
|
||||
}
|
||||
SECTION("Vectors with elements") {
|
||||
std::vector<double> v1({1., 2., 3.});
|
||||
SECTION("A vector is approx equal to itself") {
|
||||
REQUIRE_THAT(v1, Approx(v1));
|
||||
}
|
||||
std::vector<double> v2({1.5, 2.5, 3.5});
|
||||
SECTION("Different length") {
|
||||
auto temp(v1);
|
||||
temp.push_back(4);
|
||||
REQUIRE_THAT(v1, !Approx(temp));
|
||||
}
|
||||
SECTION("Same length, different elements") {
|
||||
REQUIRE_THAT(v1, !Approx(v2));
|
||||
REQUIRE_THAT(v1, Approx(v2).margin(0.5));
|
||||
REQUIRE_THAT(v1, Approx(v2).epsilon(0.5));
|
||||
REQUIRE_THAT(v1, Approx(v2).epsilon(0.1).scale(500));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Vector Approx matcher -- failing", "[matchers][approx][vector][.failing]") {
|
||||
using Catch::Matchers::Approx;
|
||||
SECTION("Empty and non empty vectors are not approx equal") {
|
||||
std::vector<double> empty, t1({1, 2});
|
||||
CHECK_THAT(empty, Approx(t1));
|
||||
}
|
||||
SECTION("Just different vectors") {
|
||||
std::vector<double> v1({2., 4., 6.}), v2({1., 3., 5.});
|
||||
CHECK_THAT(v1, Approx(v2));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Exceptions matchers", "[matchers][exceptions][!throws]") {
|
||||
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what"));
|
||||
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, !Message("derivedexception::what"));
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, !Message("DerivedException::what"));
|
||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
|
||||
}
|
||||
|
||||
} } // namespace MatchersTests
|
||||
|
||||
#endif // CATCH_CONFIG_DISABLE_MATCHERS
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
269
tests/SelfTest/UsageTests/Message.tests.cpp
Normal file
269
tests/SelfTest/UsageTests/Message.tests.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Created by Phil on 09/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <iostream>
|
||||
|
||||
TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) {
|
||||
INFO( "this is a " << "message" ); // This should output the message if a failure occurs
|
||||
WARN( "this is a " << "warning" ); // This should always output the message but then continue
|
||||
}
|
||||
|
||||
TEST_CASE( "#1455 - INFO and WARN can start with a linebreak", "[messages][.]" ) {
|
||||
// Previously these would be hidden from the console reporter output,
|
||||
// because it would fail at properly reflowing the text
|
||||
INFO( "\nThis info message starts with a linebreak" );
|
||||
WARN( "\nThis warning message starts with a linebreak" );
|
||||
}
|
||||
|
||||
TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) {
|
||||
SUCCEED( "this is a " << "success" );
|
||||
}
|
||||
|
||||
TEST_CASE( "INFO gets logged on failure", "[failing][messages][.]" ) {
|
||||
INFO( "this message should be logged" );
|
||||
INFO( "so should this" );
|
||||
int a = 2;
|
||||
REQUIRE( a == 1 );
|
||||
}
|
||||
|
||||
TEST_CASE( "INFO gets logged on failure, even if captured before successful assertions", "[failing][messages][.]" ) {
|
||||
INFO( "this message may be logged later" );
|
||||
int a = 2;
|
||||
CHECK( a == 2 );
|
||||
|
||||
INFO( "this message should be logged" );
|
||||
|
||||
CHECK( a == 1 );
|
||||
|
||||
INFO( "and this, but later" );
|
||||
|
||||
CHECK( a == 0 );
|
||||
|
||||
INFO( "but not this" );
|
||||
|
||||
CHECK( a == 2 );
|
||||
}
|
||||
|
||||
TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) {
|
||||
FAIL( "This is a " << "failure" ); // This should output the message and abort
|
||||
WARN( "We should never see this");
|
||||
}
|
||||
|
||||
TEST_CASE( "FAIL_CHECK does not abort the test", "[failing][messages][.]" ) {
|
||||
FAIL_CHECK( "This is a " << "failure" ); // This should output the message then continue
|
||||
WARN( "This message appears in the output");
|
||||
}
|
||||
|
||||
TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_CASE( "SUCCEED does not require an argument", "[messages][.]" ) {
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) {
|
||||
SECTION( "one" ) {
|
||||
FAIL( "Message from section one" );
|
||||
}
|
||||
|
||||
SECTION( "two" ) {
|
||||
FAIL( "Message from section two" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) {
|
||||
SECTION( "one" ) {
|
||||
std::cout << "Message from section one" << std::endl;
|
||||
}
|
||||
|
||||
SECTION( "two" ) {
|
||||
std::cout << "Message from section two" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Standard error is reported and redirected", "[messages][.][approvals]" ) {
|
||||
SECTION( "std::cerr" ) {
|
||||
std::cerr << "Write to std::cerr" << std::endl;
|
||||
}
|
||||
SECTION( "std::clog" ) {
|
||||
std::clog << "Write to std::clog" << std::endl;
|
||||
}
|
||||
SECTION( "Interleaved writes to cerr and clog" ) {
|
||||
std::cerr << "Inter";
|
||||
std::clog << "leaved";
|
||||
std::cerr << ' ';
|
||||
std::clog << "writes";
|
||||
std::cerr << " to error";
|
||||
std::clog << " streams" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "INFO is reset for each loop", "[messages][failing][.]" ) {
|
||||
for( int i=0; i<100; i++ )
|
||||
{
|
||||
INFO( "current counter " << i );
|
||||
CAPTURE( i );
|
||||
REQUIRE( i < 10 );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "The NO_FAIL macro reports a failure but does not fail the test", "[messages]" ) {
|
||||
CHECK_NOFAIL( 1 == 2 );
|
||||
}
|
||||
|
||||
TEST_CASE( "just info", "[info][isolated info][messages]" ) {
|
||||
INFO( "this should never be seen" );
|
||||
}
|
||||
TEST_CASE( "just failure", "[fail][isolated info][.][messages]" ) {
|
||||
FAIL( "Previous info should not be seen" );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "sends information to INFO", "[.][failing]" ) {
|
||||
INFO( "hi" );
|
||||
int i = 7;
|
||||
CAPTURE( i );
|
||||
REQUIRE( false );
|
||||
}
|
||||
|
||||
TEST_CASE( "Pointers can be converted to strings", "[messages][.][approvals]" ) {
|
||||
int p;
|
||||
WARN( "actual address of p: " << &p );
|
||||
WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void unscoped_info( T msg ) {
|
||||
UNSCOPED_INFO( msg );
|
||||
}
|
||||
|
||||
TEST_CASE( "just unscoped info", "[unscoped][info]" ) {
|
||||
unscoped_info( "this should NOT be seen" );
|
||||
unscoped_info( "this also should NOT be seen" );
|
||||
}
|
||||
|
||||
TEST_CASE( "just failure after unscoped info", "[failing][.][unscoped][info]" ) {
|
||||
FAIL( "previous unscoped info SHOULD not be seen" );
|
||||
}
|
||||
|
||||
TEST_CASE( "print unscoped info if passing unscoped info is printed", "[unscoped][info]" ) {
|
||||
unscoped_info( "this MAY be seen IF info is printed for passing assertions" );
|
||||
REQUIRE( true );
|
||||
}
|
||||
|
||||
TEST_CASE( "prints unscoped info on failure", "[failing][.][unscoped][info]" ) {
|
||||
unscoped_info( "this SHOULD be seen" );
|
||||
unscoped_info( "this SHOULD also be seen" );
|
||||
REQUIRE( false );
|
||||
unscoped_info( "but this should NOT be seen" );
|
||||
}
|
||||
|
||||
TEST_CASE( "not prints unscoped info from previous failures", "[failing][.][unscoped][info]" ) {
|
||||
unscoped_info( "this MAY be seen only for the FIRST assertion IF info is printed for passing assertions" );
|
||||
REQUIRE( true );
|
||||
unscoped_info( "this MAY be seen only for the SECOND assertion IF info is printed for passing assertions" );
|
||||
REQUIRE( true );
|
||||
unscoped_info( "this SHOULD be seen" );
|
||||
REQUIRE( false );
|
||||
}
|
||||
|
||||
TEST_CASE( "prints unscoped info only for the first assertion", "[failing][.][unscoped][info]" ) {
|
||||
unscoped_info( "this SHOULD be seen only ONCE" );
|
||||
CHECK( false );
|
||||
CHECK( true );
|
||||
unscoped_info( "this MAY also be seen only ONCE IF info is printed for passing assertions" );
|
||||
CHECK( true );
|
||||
CHECK( true );
|
||||
}
|
||||
|
||||
TEST_CASE( "stacks unscoped info in loops", "[failing][.][unscoped][info]" ) {
|
||||
UNSCOPED_INFO("Count 1 to 3...");
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
unscoped_info(i);
|
||||
}
|
||||
CHECK( false );
|
||||
|
||||
UNSCOPED_INFO("Count 4 to 6...");
|
||||
for (int i = 4; i <= 6; i++) {
|
||||
unscoped_info(i);
|
||||
}
|
||||
CHECK( false );
|
||||
}
|
||||
|
||||
TEST_CASE( "mix info, unscoped info and warning", "[unscoped][info]" ) {
|
||||
INFO("info");
|
||||
unscoped_info("unscoped info");
|
||||
WARN("and warn may mix");
|
||||
WARN("they are not cleared after warnings");
|
||||
}
|
||||
|
||||
TEST_CASE( "CAPTURE can deal with complex expressions", "[messages][capture]" ) {
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
int c = 3;
|
||||
CAPTURE( a, b, c, a + b, a+b, c > b, a == 1 );
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-value" // In (1, 2), the "1" is unused ...
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-value" // All the comma operators are side-effect free
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4709) // comma in indexing operator
|
||||
#endif
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct helper_1436 {
|
||||
helper_1436(T1 t1_, T2 t2_):
|
||||
t1{ t1_ },
|
||||
t2{ t2_ }
|
||||
{}
|
||||
T1 t1;
|
||||
T2 t2;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
std::ostream& operator<<(std::ostream& out, helper_1436<T1, T2> const& helper) {
|
||||
out << "{ " << helper.t1 << ", " << helper.t2 << " }";
|
||||
return out;
|
||||
}
|
||||
|
||||
TEST_CASE("CAPTURE can deal with complex expressions involving commas", "[messages][capture]") {
|
||||
CAPTURE(std::vector<int>{1, 2, 3}[0, 1, 2],
|
||||
std::vector<int>{1, 2, 3}[(0, 1)],
|
||||
std::vector<int>{1, 2, 3}[0]);
|
||||
CAPTURE((helper_1436<int, int>{12, -12}),
|
||||
(helper_1436<int, int>(-12, 12)));
|
||||
CAPTURE( (1, 2), (2, 3) );
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST_CASE("CAPTURE parses string and character constants", "[messages][capture]") {
|
||||
CAPTURE(("comma, in string", "escaped, \", "), "single quote in string,',", "some escapes, \\,\\\\");
|
||||
CAPTURE("some, ), unmatched, } prenheses {[<");
|
||||
CAPTURE('"', '\'', ',', '}', ')', '(', '{');
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
487
tests/SelfTest/UsageTests/Misc.tests.cpp
Normal file
487
tests/SelfTest/UsageTests/Misc.tests.cpp
Normal file
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* Created by Phil on 29/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
|
||||
#endif
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <cerrno>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <array>
|
||||
|
||||
namespace { namespace MiscTests {
|
||||
|
||||
#ifndef MISC_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
|
||||
#define MISC_TEST_HELPERS_INCLUDED
|
||||
|
||||
inline const char* makeString( bool makeNull ) {
|
||||
return makeNull ? nullptr : "valid string";
|
||||
}
|
||||
inline bool testCheckedIf( bool flag ) {
|
||||
CHECKED_IF( flag )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
inline bool testCheckedElse( bool flag ) {
|
||||
CHECKED_ELSE( flag )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned int Factorial( unsigned int number ) {
|
||||
return number > 1 ? Factorial(number-1)*number : 1;
|
||||
}
|
||||
|
||||
static int f() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline void manuallyRegisteredTestFunction() {
|
||||
SUCCEED( "was called" );
|
||||
}
|
||||
|
||||
struct AutoTestReg {
|
||||
AutoTestReg() {
|
||||
REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered" );
|
||||
}
|
||||
};
|
||||
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
|
||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||
static AutoTestReg autoTestReg;
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
template<typename T>
|
||||
struct Foo {
|
||||
size_t size() { return 0; }
|
||||
};
|
||||
|
||||
template<typename T, size_t S>
|
||||
struct Bar {
|
||||
size_t size() { return S; }
|
||||
};
|
||||
#endif
|
||||
|
||||
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
|
||||
SECTION( "doesn't equal" ) {
|
||||
REQUIRE( a != b );
|
||||
REQUIRE( b != a );
|
||||
}
|
||||
|
||||
SECTION( "not equal" ) {
|
||||
REQUIRE( a != b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) {
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
|
||||
SECTION( "doesn't equal" ) {
|
||||
REQUIRE( a != b );
|
||||
REQUIRE( b != a );
|
||||
|
||||
SECTION( "not equal" ) {
|
||||
REQUIRE( a != b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) {
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
|
||||
SECTION( "doesn't equal" ) {
|
||||
SECTION( "equal" ) {
|
||||
REQUIRE( a == b );
|
||||
}
|
||||
|
||||
SECTION( "not equal" ) {
|
||||
REQUIRE( a != b );
|
||||
}
|
||||
SECTION( "less than" ) {
|
||||
REQUIRE( a < b );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "even more nested SECTION tests", "[sections]" ) {
|
||||
SECTION( "c" ) {
|
||||
SECTION( "d (leaf)" ) {
|
||||
SUCCEED(); // avoid failing due to no tests
|
||||
}
|
||||
|
||||
SECTION( "e (leaf)" ) {
|
||||
SUCCEED(); // avoid failing due to no tests
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "f (leaf)" ) {
|
||||
SUCCEED(); // avoid failing due to no tests
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) {
|
||||
int a = 1;
|
||||
|
||||
for( int b = 0; b < 10; ++b ) {
|
||||
DYNAMIC_SECTION( "b is currently: " << b ) {
|
||||
CHECK( b > a );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "looped tests", "[.][failing]" ) {
|
||||
static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 };
|
||||
|
||||
for( std::size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) {
|
||||
INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" );
|
||||
CHECK( ( fib[i] % 2 ) == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) {
|
||||
std::cout << "A string sent directly to stdout" << std::endl;
|
||||
std::cerr << "A string sent directly to stderr" << std::endl;
|
||||
std::clog << "A string sent to stderr via clog" << std::endl;
|
||||
}
|
||||
|
||||
TEST_CASE( "null strings" ) {
|
||||
REQUIRE( makeString( false ) != static_cast<char*>(nullptr));
|
||||
REQUIRE( makeString( true ) == static_cast<char*>(nullptr));
|
||||
}
|
||||
|
||||
TEST_CASE( "checkedIf" ) {
|
||||
REQUIRE( testCheckedIf( true ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "checkedIf, failing", "[failing][.]" ) {
|
||||
REQUIRE( testCheckedIf( false ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "checkedElse" ) {
|
||||
REQUIRE( testCheckedElse( true ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "checkedElse, failing", "[failing][.]" ) {
|
||||
REQUIRE( testCheckedElse( false ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "xmlentitycheck" ) {
|
||||
SECTION( "embedded xml: <test>it should be possible to embed xml characters, such as <, \" or &, or even whole <xml>documents</xml> within an attribute</test>" ) {
|
||||
SUCCEED(); // We need this here to stop it failing due to no tests
|
||||
}
|
||||
SECTION( "encoded chars: these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) {
|
||||
SUCCEED(); // We need this here to stop it failing due to no tests
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "send a single char to INFO", "[failing][.]" ) {
|
||||
INFO(3);
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
TEST_CASE( "atomic if", "[failing][0]") {
|
||||
std::size_t x = 0;
|
||||
|
||||
if( x )
|
||||
REQUIRE(x > 0);
|
||||
else
|
||||
REQUIRE(x == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "Factorials are computed", "[factorial]" ) {
|
||||
REQUIRE( Factorial(0) == 1 );
|
||||
REQUIRE( Factorial(1) == 1 );
|
||||
REQUIRE( Factorial(2) == 2 );
|
||||
REQUIRE( Factorial(3) == 6 );
|
||||
REQUIRE( Factorial(10) == 3628800 );
|
||||
}
|
||||
|
||||
TEST_CASE( "An empty test with no assertions", "[empty]" ) {}
|
||||
|
||||
TEST_CASE( "Nice descriptive name", "[tag1][tag2][tag3][.]" ) {
|
||||
WARN( "This one ran" );
|
||||
}
|
||||
TEST_CASE( "first tag", "[tag1]" ) {}
|
||||
TEST_CASE( "second tag", "[tag2]" ) {}
|
||||
|
||||
//
|
||||
//TEST_CASE( "spawn a new process", "[.]" )
|
||||
//{
|
||||
// // !TBD Work in progress
|
||||
// char line[200];
|
||||
// FILE* output = popen("./CatchSelfTest ./failing/matchers/StartsWith", "r");
|
||||
// while ( fgets(line, 199, output) )
|
||||
// std::cout << line;
|
||||
//}
|
||||
|
||||
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
|
||||
|
||||
std::vector<int> v( 5 );
|
||||
|
||||
REQUIRE( v.size() == 5 );
|
||||
REQUIRE( v.capacity() >= 5 );
|
||||
|
||||
SECTION( "resizing bigger changes size and capacity" ) {
|
||||
v.resize( 10 );
|
||||
|
||||
REQUIRE( v.size() == 10 );
|
||||
REQUIRE( v.capacity() >= 10 );
|
||||
}
|
||||
SECTION( "resizing smaller changes size but not capacity" ) {
|
||||
v.resize( 0 );
|
||||
|
||||
REQUIRE( v.size() == 0 );
|
||||
REQUIRE( v.capacity() >= 5 );
|
||||
|
||||
SECTION( "We can use the 'swap trick' to reset the capacity" ) {
|
||||
std::vector<int> empty;
|
||||
empty.swap( v );
|
||||
|
||||
REQUIRE( v.capacity() == 0 );
|
||||
}
|
||||
}
|
||||
SECTION( "reserving bigger changes capacity but not size" ) {
|
||||
v.reserve( 10 );
|
||||
|
||||
REQUIRE( v.size() == 5 );
|
||||
REQUIRE( v.capacity() >= 10 );
|
||||
}
|
||||
SECTION( "reserving smaller does not change size or capacity" ) {
|
||||
v.reserve( 0 );
|
||||
|
||||
REQUIRE( v.size() == 5 );
|
||||
REQUIRE( v.capacity() >= 5 );
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE( "TemplateTest: vectors can be sized and resized", "[vector][template]", int, float, std::string, (std::tuple<int,float>) ) {
|
||||
|
||||
std::vector<TestType> v( 5 );
|
||||
|
||||
REQUIRE( v.size() == 5 );
|
||||
REQUIRE( v.capacity() >= 5 );
|
||||
|
||||
SECTION( "resizing bigger changes size and capacity" ) {
|
||||
v.resize( 10 );
|
||||
|
||||
REQUIRE( v.size() == 10 );
|
||||
REQUIRE( v.capacity() >= 10 );
|
||||
}
|
||||
SECTION( "resizing smaller changes size but not capacity" ) {
|
||||
v.resize( 0 );
|
||||
|
||||
REQUIRE( v.size() == 0 );
|
||||
REQUIRE( v.capacity() >= 5 );
|
||||
|
||||
SECTION( "We can use the 'swap trick' to reset the capacity" ) {
|
||||
std::vector<TestType> empty;
|
||||
empty.swap( v );
|
||||
|
||||
REQUIRE( v.capacity() == 0 );
|
||||
}
|
||||
}
|
||||
SECTION( "reserving bigger changes capacity but not size" ) {
|
||||
v.reserve( 10 );
|
||||
|
||||
REQUIRE( v.size() == 5 );
|
||||
REQUIRE( v.capacity() >= 10 );
|
||||
}
|
||||
SECTION( "reserving smaller does not change size or capacity" ) {
|
||||
v.reserve( 0 );
|
||||
|
||||
REQUIRE( v.size() == 5 );
|
||||
REQUIRE( v.capacity() >= 5 );
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE_TEST_CASE_SIG("TemplateTestSig: vectors can be sized and resized", "[vector][template][nttp]", ((typename TestType, int V), TestType, V), (int,5), (float,4), (std::string,15), ((std::tuple<int, float>), 6)) {
|
||||
|
||||
std::vector<TestType> v(V);
|
||||
|
||||
REQUIRE(v.size() == V);
|
||||
REQUIRE(v.capacity() >= V);
|
||||
|
||||
SECTION("resizing bigger changes size and capacity") {
|
||||
v.resize(2 * V);
|
||||
|
||||
REQUIRE(v.size() == 2 * V);
|
||||
REQUIRE(v.capacity() >= 2 * V);
|
||||
}
|
||||
SECTION("resizing smaller changes size but not capacity") {
|
||||
v.resize(0);
|
||||
|
||||
REQUIRE(v.size() == 0);
|
||||
REQUIRE(v.capacity() >= V);
|
||||
|
||||
SECTION("We can use the 'swap trick' to reset the capacity") {
|
||||
std::vector<TestType> empty;
|
||||
empty.swap(v);
|
||||
|
||||
REQUIRE(v.capacity() == 0);
|
||||
}
|
||||
}
|
||||
SECTION("reserving bigger changes capacity but not size") {
|
||||
v.reserve(2 * V);
|
||||
|
||||
REQUIRE(v.size() == V);
|
||||
REQUIRE(v.capacity() >= 2 * V);
|
||||
}
|
||||
SECTION("reserving smaller does not change size or capacity") {
|
||||
v.reserve(0);
|
||||
|
||||
REQUIRE(v.size() == V);
|
||||
REQUIRE(v.capacity() >= V);
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]", (std::vector, Foo), (int, float)) {
|
||||
TestType x;
|
||||
REQUIRE(x.size() == 0);
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE_SIG("A Template product test case with array signature", "[template][product][nttp]", ((typename T, size_t S), T, S), (std::array, Bar), ((int, 9), (float, 42))) {
|
||||
TestType x;
|
||||
REQUIRE(x.size() > 0);
|
||||
}
|
||||
|
||||
TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
|
||||
REQUIRE(std::tuple_size<TestType>::value >= 1);
|
||||
}
|
||||
|
||||
using MyTypes = std::tuple<int, char, float>;
|
||||
TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside std::tuple", "[template][list]", MyTypes)
|
||||
{
|
||||
REQUIRE(sizeof(TestType) > 0);
|
||||
}
|
||||
|
||||
struct NonDefaultConstructibleType {
|
||||
NonDefaultConstructibleType() = delete;
|
||||
};
|
||||
|
||||
using MyNonDefaultConstructibleTypes = std::tuple<NonDefaultConstructibleType, float>;
|
||||
TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside non-default-constructible std::tuple", "[template][list]", MyNonDefaultConstructibleTypes)
|
||||
{
|
||||
REQUIRE(sizeof(TestType) > 0);
|
||||
}
|
||||
|
||||
struct NonCopyableAndNonMovableType {
|
||||
NonCopyableAndNonMovableType() = default;
|
||||
|
||||
NonCopyableAndNonMovableType(NonCopyableAndNonMovableType const &) = delete;
|
||||
NonCopyableAndNonMovableType(NonCopyableAndNonMovableType &&) = delete;
|
||||
auto operator=(NonCopyableAndNonMovableType const &) -> NonCopyableAndNonMovableType & = delete;
|
||||
auto operator=(NonCopyableAndNonMovableType &&) -> NonCopyableAndNonMovableType & = delete;
|
||||
};
|
||||
|
||||
using NonCopyableAndNonMovableTypes = std::tuple<NonCopyableAndNonMovableType, float>;
|
||||
TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside non-copyable and non-movable std::tuple", "[template][list]", NonCopyableAndNonMovableTypes)
|
||||
{
|
||||
REQUIRE(sizeof(TestType) > 0);
|
||||
}
|
||||
|
||||
// https://github.com/philsquared/Catch/issues/166
|
||||
TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") {
|
||||
SECTION("Outer")
|
||||
SECTION("Inner")
|
||||
SUCCEED("that's not flying - that's failing in style");
|
||||
|
||||
FAIL("to infinity and beyond");
|
||||
}
|
||||
|
||||
TEST_CASE("not allowed", "[!throws]") {
|
||||
// This test case should not be included if you run with -e on the command line
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
//TEST_CASE( "Is big endian" ) {
|
||||
// CHECK( Catch::Detail::Endianness::which() == Catch::Detail::Endianness::Little );
|
||||
//}
|
||||
|
||||
TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) {
|
||||
|
||||
// Based on issue #242
|
||||
std::string s1 = "if ($b == 10) {\n\t\t$a\t= 20;\n}";
|
||||
std::string s2 = "if ($b == 10) {\n\t$a = 20;\n}\n";
|
||||
CHECK( s1 == s2 );
|
||||
}
|
||||
|
||||
|
||||
#ifdef CATCH_CONFIG_WCHAR
|
||||
TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) {
|
||||
const wchar_t * const s = L"wide load";
|
||||
std::string result = ::Catch::Detail::stringify( s );
|
||||
CHECK( result == "\"wide load\"" );
|
||||
}
|
||||
|
||||
TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) {
|
||||
const wchar_t * s = L"wide load";
|
||||
std::string result = ::Catch::Detail::stringify( s );
|
||||
CHECK( result == "\"wide load\"" );
|
||||
}
|
||||
|
||||
TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
|
||||
auto const s = const_cast<wchar_t*>( L"wide load" );
|
||||
std::string result = ::Catch::Detail::stringify( s );
|
||||
CHECK( result == "\"wide load\"" );
|
||||
}
|
||||
|
||||
TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
|
||||
auto s = const_cast<wchar_t*>( L"wide load" );
|
||||
std::string result = ::Catch::Detail::stringify( s );
|
||||
CHECK( result == "\"wide load\"" );
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE( "long long" ) {
|
||||
long long l = std::numeric_limits<long long>::max();
|
||||
|
||||
REQUIRE( l == std::numeric_limits<long long>::max() );
|
||||
}
|
||||
|
||||
TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" ) {
|
||||
SUCCEED( "oops!" );
|
||||
}
|
||||
|
||||
TEST_CASE( "# A test name that starts with a #" ) {
|
||||
SUCCEED( "yay" );
|
||||
}
|
||||
|
||||
TEST_CASE( "#835 -- errno should not be touched by Catch", "[.][failing][!shouldfail]" ) {
|
||||
errno = 1;
|
||||
CHECK(f() == 0);
|
||||
REQUIRE(errno == 1); // Check that f() doesn't touch errno.
|
||||
}
|
||||
|
||||
TEST_CASE( "#961 -- Dynamically created sections should all be reported", "[.]" ) {
|
||||
for (char i = '0'; i < '5'; ++i) {
|
||||
SECTION(std::string("Looped section ") + i) {
|
||||
SUCCEED( "Everything is OK" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "#1175 - Hidden Test", "[.]" ) {
|
||||
// Just for checking that hidden test is not listed by default
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
}} // namespace MiscTests
|
15
tests/SelfTest/UsageTests/ToStringByte.tests.cpp
Normal file
15
tests/SelfTest/UsageTests/ToStringByte.tests.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP17_BYTE)
|
||||
|
||||
TEST_CASE( "std::byte -> toString", "[toString][byte][approvals]" ) {
|
||||
using type = std::byte;
|
||||
REQUIRE( "0" == ::Catch::Detail::stringify( type{ 0 } ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::vector<std::byte> -> toString", "[toString][byte][approvals]" ) {
|
||||
using type = std::vector<std::byte>;
|
||||
REQUIRE( "{ 0, 1, 2 }" == ::Catch::Detail::stringify( type{ std::byte{0}, std::byte{1}, std::byte{2} } ) );
|
||||
}
|
||||
|
||||
#endif // CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
44
tests/SelfTest/UsageTests/ToStringChrono.tests.cpp
Normal file
44
tests/SelfTest/UsageTests/ToStringChrono.tests.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
||||
TEST_CASE("Stringifying std::chrono::duration helpers", "[toString][chrono]") {
|
||||
// No literals because we still support c++11
|
||||
auto hour = std::chrono::hours(1);
|
||||
auto minute = std::chrono::minutes(1);
|
||||
auto seconds = std::chrono::seconds(60);
|
||||
auto micro = std::chrono::microseconds(1);
|
||||
auto milli = std::chrono::milliseconds(1);
|
||||
auto nano = std::chrono::nanoseconds(1);
|
||||
REQUIRE(minute == seconds);
|
||||
REQUIRE(hour != seconds);
|
||||
REQUIRE(micro != milli);
|
||||
REQUIRE(nano != micro);
|
||||
}
|
||||
|
||||
TEST_CASE("Stringifying std::chrono::duration with weird ratios", "[toString][chrono]") {
|
||||
std::chrono::duration<int64_t, std::ratio<30>> half_minute(1);
|
||||
std::chrono::duration<int64_t, std::ratio<1, 1000000000000>> pico_second(1);
|
||||
std::chrono::duration<int64_t, std::ratio<1, 1000000000000000>> femto_second(1);
|
||||
std::chrono::duration<int64_t, std::ratio<1, 1000000000000000000>> atto_second(1);
|
||||
REQUIRE(half_minute != femto_second);
|
||||
REQUIRE(pico_second != atto_second);
|
||||
}
|
||||
|
||||
TEST_CASE("Stringifying std::chrono::time_point<system_clock>", "[toString][chrono]") {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto later = now + std::chrono::minutes(2);
|
||||
REQUIRE(now != later);
|
||||
}
|
||||
|
||||
TEST_CASE("Stringifying std::chrono::time_point<Clock>", "[toString][chrono][!nonportable]") {
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
auto later = now + std::chrono::minutes(2);
|
||||
REQUIRE(now != later);
|
||||
|
||||
auto now2 = std::chrono::steady_clock::now();
|
||||
auto later2 = now2 + std::chrono::minutes(2);
|
||||
REQUIRE(now2 != later2);
|
||||
}
|
210
tests/SelfTest/UsageTests/ToStringGeneral.tests.cpp
Normal file
210
tests/SelfTest/UsageTests/ToStringGeneral.tests.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Created by Martin on 17/02/2017.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
TEST_CASE( "Character pretty printing" ){
|
||||
SECTION("Specifically escaped"){
|
||||
char tab = '\t';
|
||||
char newline = '\n';
|
||||
char carr_return = '\r';
|
||||
char form_feed = '\f';
|
||||
CHECK(tab == '\t');
|
||||
CHECK(newline == '\n');
|
||||
CHECK(carr_return == '\r');
|
||||
CHECK(form_feed == '\f');
|
||||
}
|
||||
SECTION("General chars"){
|
||||
char space = ' ';
|
||||
CHECK(space == ' ');
|
||||
char chars[] = {'a', 'z', 'A', 'Z'};
|
||||
for (int i = 0; i < 4; ++i){
|
||||
char c = chars[i];
|
||||
REQUIRE(c == chars[i]);
|
||||
}
|
||||
}
|
||||
SECTION("Low ASCII"){
|
||||
char null_terminator = '\0';
|
||||
CHECK(null_terminator == '\0');
|
||||
for (int i = 2; i < 6; ++i){
|
||||
char c = static_cast<char>(i);
|
||||
REQUIRE(c == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "Capture and info messages" ) {
|
||||
SECTION("Capture should stringify like assertions") {
|
||||
int i = 2;
|
||||
CAPTURE(i);
|
||||
REQUIRE(true);
|
||||
}
|
||||
SECTION("Info should NOT stringify the way assertions do") {
|
||||
int i = 3;
|
||||
INFO(i);
|
||||
REQUIRE(true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "std::map is convertible string", "[toString]" ) {
|
||||
|
||||
SECTION( "empty" ) {
|
||||
std::map<std::string, int> emptyMap;
|
||||
|
||||
REQUIRE( Catch::Detail::stringify( emptyMap ) == "{ }" );
|
||||
}
|
||||
|
||||
SECTION( "single item" ) {
|
||||
std::map<std::string, int> map = { { "one", 1 } };
|
||||
|
||||
REQUIRE( Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" );
|
||||
}
|
||||
|
||||
SECTION( "several items" ) {
|
||||
std::map<std::string, int> map = {
|
||||
{ "abc", 1 },
|
||||
{ "def", 2 },
|
||||
{ "ghi", 3 }
|
||||
};
|
||||
|
||||
REQUIRE( Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "std::set is convertible string", "[toString]" ) {
|
||||
|
||||
SECTION( "empty" ) {
|
||||
std::set<std::string> emptySet;
|
||||
|
||||
REQUIRE( Catch::Detail::stringify( emptySet ) == "{ }" );
|
||||
}
|
||||
|
||||
SECTION( "single item" ) {
|
||||
std::set<std::string> set = { "one" };
|
||||
|
||||
REQUIRE( Catch::Detail::stringify( set ) == "{ \"one\" }" );
|
||||
}
|
||||
|
||||
SECTION( "several items" ) {
|
||||
std::set<std::string> set = { "abc", "def", "ghi" };
|
||||
|
||||
REQUIRE( Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Static arrays are convertible to string", "[toString]") {
|
||||
SECTION("Single item") {
|
||||
int singular[1] = { 1 };
|
||||
REQUIRE(Catch::Detail::stringify(singular) == "{ 1 }");
|
||||
}
|
||||
SECTION("Multiple") {
|
||||
int arr[3] = { 3, 2, 1 };
|
||||
REQUIRE(Catch::Detail::stringify(arr) == "{ 3, 2, 1 }");
|
||||
}
|
||||
SECTION("Non-trivial inner items") {
|
||||
std::vector<std::string> arr[2] = { {"1:1", "1:2", "1:3"}, {"2:1", "2:2"} };
|
||||
REQUIRE(Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
|
||||
|
||||
TEST_CASE("String views are stringified like other strings", "[toString][approvals]") {
|
||||
std::string_view view{"abc"};
|
||||
CHECK(Catch::Detail::stringify(view) == R"("abc")");
|
||||
|
||||
std::string_view arr[] { view };
|
||||
CHECK(Catch::Detail::stringify(arr) == R"({ "abc" })");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_CASE("Precision of floating point stringification can be set", "[toString][floatingPoint]") {
|
||||
SECTION("Floats") {
|
||||
using sm = Catch::StringMaker<float>;
|
||||
const auto oldPrecision = sm::precision;
|
||||
|
||||
const float testFloat = 1.12345678901234567899f;
|
||||
auto str1 = sm::convert(testFloat);
|
||||
sm::precision = 5;
|
||||
// "1." prefix = 2 chars, f suffix is another char
|
||||
CHECK(str1.size() == 3 + 5);
|
||||
|
||||
sm::precision = 10;
|
||||
auto str2 = sm::convert(testFloat);
|
||||
REQUIRE(str2.size() == 3 + 10);
|
||||
sm::precision = oldPrecision;
|
||||
}
|
||||
SECTION("Double") {
|
||||
using sm = Catch::StringMaker<double>;
|
||||
const auto oldPrecision = sm::precision;
|
||||
|
||||
const double testDouble = 1.123456789012345678901234567899;
|
||||
sm::precision = 5;
|
||||
auto str1 = sm::convert(testDouble);
|
||||
// "1." prefix = 2 chars
|
||||
CHECK(str1.size() == 2 + 5);
|
||||
|
||||
sm::precision = 15;
|
||||
auto str2 = sm::convert(testDouble);
|
||||
REQUIRE(str2.size() == 2 + 15);
|
||||
|
||||
sm::precision = oldPrecision;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct WhatException : std::exception {
|
||||
char const* what() const noexcept override {
|
||||
return "This exception has overridden what() method";
|
||||
}
|
||||
~WhatException() override;
|
||||
};
|
||||
|
||||
struct OperatorException : std::exception {
|
||||
~OperatorException() override;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, OperatorException const&) {
|
||||
out << "OperatorException";
|
||||
return out;
|
||||
}
|
||||
|
||||
struct StringMakerException : std::exception {
|
||||
~StringMakerException() override;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace Catch {
|
||||
template <>
|
||||
struct StringMaker<StringMakerException> {
|
||||
static std::string convert(StringMakerException const&) {
|
||||
return "StringMakerException";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Avoid -Wweak-tables
|
||||
WhatException::~WhatException() = default;
|
||||
OperatorException::~OperatorException() = default;
|
||||
StringMakerException::~StringMakerException() = default;
|
||||
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified", "[toString][exception]") {
|
||||
REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method");
|
||||
REQUIRE(::Catch::Detail::stringify(OperatorException{}) == "OperatorException");
|
||||
REQUIRE(::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException");
|
||||
}
|
23
tests/SelfTest/UsageTests/ToStringOptional.tests.cpp
Normal file
23
tests/SelfTest/UsageTests/ToStringOptional.tests.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP17_OPTIONAL)
|
||||
|
||||
TEST_CASE( "std::optional<int> -> toString", "[toString][optional][approvals]" ) {
|
||||
using type = std::optional<int>;
|
||||
REQUIRE( "{ }" == ::Catch::Detail::stringify( type{} ) );
|
||||
REQUIRE( "0" == ::Catch::Detail::stringify( type{ 0 } ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::optional<std::string> -> toString", "[toString][optional][approvals]" ) {
|
||||
using type = std::optional<std::string>;
|
||||
REQUIRE( "{ }" == ::Catch::Detail::stringify( type{} ) );
|
||||
REQUIRE( "\"abc\"" == ::Catch::Detail::stringify( type{ "abc" } ) );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::vector<std::optional<int> > -> toString", "[toString][optional][approvals]" ) {
|
||||
using type = std::vector<std::optional<int> >;
|
||||
REQUIRE( "{ 0, { }, 2 }" == ::Catch::Detail::stringify( type{ 0, {}, 2 } ) );
|
||||
}
|
||||
|
||||
#endif // CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
|
30
tests/SelfTest/UsageTests/ToStringPair.tests.cpp
Normal file
30
tests/SelfTest/UsageTests/ToStringPair.tests.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) {
|
||||
std::pair<int,std::string> value( 34, "xyzzy" );
|
||||
REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::pair<int,const std::string> -> toString", "[toString][pair]" ) {
|
||||
std::pair<int,const std::string> value( 34, "xyzzy" );
|
||||
REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "std::vector<std::pair<std::string,int> > -> toString", "[toString][pair]" ) {
|
||||
std::vector<std::pair<std::string,int> > pr;
|
||||
pr.push_back( std::make_pair("green", 55 ) );
|
||||
REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" );
|
||||
}
|
||||
|
||||
// This is pretty contrived - I figure if this works, anything will...
|
||||
TEST_CASE( "pair<pair<int,const char *,pair<std::string,int> > -> toString", "[toString][pair]" ) {
|
||||
typedef std::pair<int,const char *> left_t;
|
||||
typedef std::pair<std::string,int> right_t;
|
||||
|
||||
left_t left( 42, "Arthur" );
|
||||
right_t right( "Ford", 24 );
|
||||
|
||||
std::pair<left_t,right_t> pair( left, right );
|
||||
REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" );
|
||||
}
|
47
tests/SelfTest/UsageTests/ToStringTuple.tests.cpp
Normal file
47
tests/SelfTest/UsageTests/ToStringTuple.tests.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
TEST_CASE( "tuple<>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<> type;
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(type{}) );
|
||||
type value {};
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(value) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<int>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<int> type;
|
||||
CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "tuple<float,int>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<float,int> type;
|
||||
CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) );
|
||||
CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<string,string>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::string,std::string> type;
|
||||
CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<tuple<int>,tuple<>,float>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::tuple<int>,std::tuple<>,float> type;
|
||||
type value { std::tuple<int>{42}, {}, 1.2f };
|
||||
CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) );
|
||||
}
|
||||
|
||||
TEST_CASE( "tuple<nullptr,int,const char *>", "[toString][tuple]" )
|
||||
{
|
||||
typedef std::tuple<std::nullptr_t,int,const char *> type;
|
||||
type value { nullptr, 42, "Catch me" };
|
||||
CHECK( "{ nullptr, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) );
|
||||
}
|
||||
|
91
tests/SelfTest/UsageTests/ToStringVariant.tests.cpp
Normal file
91
tests/SelfTest/UsageTests/ToStringVariant.tests.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#if defined(CATCH_CONFIG_CPP17_VARIANT)
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
// We need 2 types with non-trivial copies/moves
|
||||
struct MyType1 {
|
||||
MyType1() = default;
|
||||
[[noreturn]] MyType1(MyType1 const&) { throw 1; }
|
||||
MyType1& operator=(MyType1 const&) { throw 3; }
|
||||
};
|
||||
struct MyType2 {
|
||||
MyType2() = default;
|
||||
[[noreturn]] MyType2(MyType2 const&) { throw 2; }
|
||||
MyType2& operator=(MyType2 const&) { throw 4; }
|
||||
};
|
||||
|
||||
TEST_CASE( "variant<std::monostate>", "[toString][variant][approvals]")
|
||||
{
|
||||
using type = std::variant<std::monostate>;
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(type{}) );
|
||||
type value {};
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(value) );
|
||||
CHECK( "{ }" == ::Catch::Detail::stringify(std::get<0>(value)) );
|
||||
}
|
||||
|
||||
TEST_CASE( "variant<int>", "[toString][variant][approvals]")
|
||||
{
|
||||
using type = std::variant<int>;
|
||||
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "variant<float, int>", "[toString][variant][approvals]")
|
||||
{
|
||||
using type = std::variant<float, int>;
|
||||
CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
|
||||
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "variant -- valueless-by-exception", "[toString][variant][approvals]" ) {
|
||||
using type = std::variant<MyType1, MyType2>;
|
||||
|
||||
type value;
|
||||
REQUIRE_THROWS_AS(value.emplace<MyType2>(MyType2{}), int);
|
||||
REQUIRE(value.valueless_by_exception());
|
||||
CHECK("{valueless variant}" == ::Catch::Detail::stringify(value));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "variant<string, int>", "[toString][variant][approvals]")
|
||||
{
|
||||
using type = std::variant<std::string, int>;
|
||||
CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
|
||||
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
||||
}
|
||||
|
||||
TEST_CASE( "variant<variant<float, int>, string>", "[toString][variant][approvals]")
|
||||
{
|
||||
using inner = std::variant<MyType1, float, int>;
|
||||
using type = std::variant<inner, std::string>;
|
||||
CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
|
||||
CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
|
||||
CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
|
||||
|
||||
SECTION("valueless nested variant") {
|
||||
type value = inner{0.5f};
|
||||
REQUIRE( std::holds_alternative<inner>(value) );
|
||||
REQUIRE( std::holds_alternative<float>(std::get<inner>(value)) );
|
||||
|
||||
REQUIRE_THROWS_AS( std::get<0>(value).emplace<MyType1>(MyType1{}), int );
|
||||
|
||||
// outer variant is still valid and contains inner
|
||||
REQUIRE( std::holds_alternative<inner>(value) );
|
||||
// inner variant is valueless
|
||||
REQUIRE( std::get<inner>(value).valueless_by_exception() );
|
||||
CHECK( "{valueless variant}" == ::Catch::Detail::stringify(value) );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "variant<nullptr,int,const char *>", "[toString][variant][approvals]" )
|
||||
{
|
||||
using type = std::variant<std::nullptr_t,int,const char *>;
|
||||
CHECK( "nullptr" == ::Catch::Detail::stringify(type{nullptr}) );
|
||||
CHECK( "42" == ::Catch::Detail::stringify(type{42}) );
|
||||
CHECK( "\"Catch me\"" == ::Catch::Detail::stringify(type{"Catch me"}) );
|
||||
}
|
||||
|
||||
#endif // CATCH_INTERNAL_CONFIG_CPP17_VARIANT
|
86
tests/SelfTest/UsageTests/ToStringVector.tests.cpp
Normal file
86
tests/SelfTest/UsageTests/ToStringVector.tests.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <catch2/catch.hpp>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
// vector
|
||||
TEST_CASE( "vector<int> -> toString", "[toString][vector]" )
|
||||
{
|
||||
std::vector<int> vv;
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" );
|
||||
vv.push_back( 42 );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" );
|
||||
vv.push_back( 250 );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "vector<string> -> toString", "[toString][vector]" )
|
||||
{
|
||||
std::vector<std::string> vv;
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" );
|
||||
vv.push_back( "hello" );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" );
|
||||
vv.push_back( "world" );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" );
|
||||
}
|
||||
|
||||
namespace {
|
||||
/* Minimal Allocator */
|
||||
template<typename T>
|
||||
struct minimal_allocator {
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
|
||||
minimal_allocator() = default;
|
||||
template <typename U>
|
||||
minimal_allocator(const minimal_allocator<U>&) {}
|
||||
|
||||
|
||||
T *allocate( size_type n ) {
|
||||
return static_cast<T *>( ::operator new( n * sizeof(T) ) );
|
||||
}
|
||||
void deallocate( T *p, size_type /*n*/ ) {
|
||||
::operator delete( static_cast<void *>(p) );
|
||||
}
|
||||
template<typename U>
|
||||
bool operator==( const minimal_allocator<U>& ) const { return true; }
|
||||
template<typename U>
|
||||
bool operator!=( const minimal_allocator<U>& ) const { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE( "vector<int,allocator> -> toString", "[toString][vector,allocator]" ) {
|
||||
std::vector<int,minimal_allocator<int> > vv;
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" );
|
||||
vv.push_back( 42 );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" );
|
||||
vv.push_back( 250 );
|
||||
REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "vec<vec<string,alloc>> -> toString", "[toString][vector,allocator]" ) {
|
||||
using inner = std::vector<std::string, minimal_allocator<std::string>>;
|
||||
using vector = std::vector<inner>;
|
||||
vector v;
|
||||
REQUIRE( ::Catch::Detail::stringify(v) == "{ }" );
|
||||
v.push_back( inner { "hello" } );
|
||||
v.push_back( inner { "world" } );
|
||||
REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" );
|
||||
}
|
||||
|
||||
// Based on PR by mat-so: https://github.com/catchorg/Catch2/pull/606/files#diff-43562f40f8c6dcfe2c54557316e0f852
|
||||
TEST_CASE( "vector<bool> -> toString", "[toString][containers][vector]" ) {
|
||||
std::vector<bool> bools;
|
||||
REQUIRE( ::Catch::Detail::stringify(bools) == "{ }");
|
||||
bools.push_back(true);
|
||||
REQUIRE( ::Catch::Detail::stringify(bools) == "{ true }");
|
||||
bools.push_back(false);
|
||||
REQUIRE( ::Catch::Detail::stringify(bools) == "{ true, false }");
|
||||
}
|
||||
TEST_CASE( "array<int, N> -> toString", "[toString][containers][array]" ) {
|
||||
std::array<int, 0> empty;
|
||||
REQUIRE( Catch::Detail::stringify( empty ) == "{ }" );
|
||||
std::array<int, 1> oneValue = {{ 42 }};
|
||||
REQUIRE( Catch::Detail::stringify( oneValue ) == "{ 42 }" );
|
||||
std::array<int, 2> twoValues = {{ 42, 250 }};
|
||||
REQUIRE( Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" );
|
||||
}
|
193
tests/SelfTest/UsageTests/ToStringWhich.tests.cpp
Normal file
193
tests/SelfTest/UsageTests/ToStringWhich.tests.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Demonstrate which version of toString/StringMaker is being used
|
||||
* for various types
|
||||
*/
|
||||
|
||||
// Replace fallback stringifier for this TU
|
||||
// We should avoid ODR violations because these specific types aren't
|
||||
// present in different TUs
|
||||
#include <string>
|
||||
template <typename T>
|
||||
std::string fallbackStringifier(T const&) {
|
||||
return "{ !!! }";
|
||||
}
|
||||
|
||||
#define CATCH_CONFIG_FALLBACK_STRINGIFIER fallbackStringifier
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// This has to be left enabled until end of the TU, because the GCC
|
||||
// frontend reports operator<<(std::ostream& os, const has_maker_and_operator&)
|
||||
// as unused anyway
|
||||
# pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
struct has_operator { };
|
||||
struct has_maker {};
|
||||
struct has_maker_and_operator {};
|
||||
struct has_neither {};
|
||||
struct has_template_operator {};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const has_operator&) {
|
||||
os << "operator<<( has_operator )";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const has_maker_and_operator&) {
|
||||
os << "operator<<( has_maker_and_operator )";
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename StreamT>
|
||||
StreamT& operator<<(StreamT& os, const has_template_operator&) {
|
||||
os << "operator<<( has_template_operator )";
|
||||
return os;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace Catch {
|
||||
template<>
|
||||
struct StringMaker<has_maker> {
|
||||
static std::string convert( const has_maker& ) {
|
||||
return "StringMaker<has_maker>";
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct StringMaker<has_maker_and_operator> {
|
||||
static std::string convert( const has_maker_and_operator& ) {
|
||||
return "StringMaker<has_maker_and_operator>";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Call the operator
|
||||
TEST_CASE( "stringify( has_operator )", "[toString]" ) {
|
||||
has_operator item;
|
||||
REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" );
|
||||
}
|
||||
|
||||
// Call the stringmaker
|
||||
TEST_CASE( "stringify( has_maker )", "[toString]" ) {
|
||||
has_maker item;
|
||||
REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" );
|
||||
}
|
||||
|
||||
// Call the stringmaker
|
||||
TEST_CASE( "stringify( has_maker_and_operator )", "[toString]" ) {
|
||||
has_maker_and_operator item;
|
||||
REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" );
|
||||
}
|
||||
|
||||
TEST_CASE("stringify( has_neither )", "[toString]") {
|
||||
has_neither item;
|
||||
REQUIRE( ::Catch::Detail::stringify(item) == "{ !!! }" );
|
||||
}
|
||||
|
||||
// Call the templated operator
|
||||
TEST_CASE( "stringify( has_template_operator )", "[toString]" ) {
|
||||
has_template_operator item;
|
||||
REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" );
|
||||
}
|
||||
|
||||
|
||||
// Vectors...
|
||||
|
||||
TEST_CASE( "stringify( vectors<has_operator> )", "[toString]" ) {
|
||||
std::vector<has_operator> v(1);
|
||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "stringify( vectors<has_maker> )", "[toString]" ) {
|
||||
std::vector<has_maker> v(1);
|
||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" );
|
||||
}
|
||||
|
||||
TEST_CASE( "stringify( vectors<has_maker_and_operator> )", "[toString]" ) {
|
||||
std::vector<has_maker_and_operator> v(1);
|
||||
REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" );
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Range-based conversion should only be used if other possibilities fail
|
||||
struct int_iterator {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = int;
|
||||
using reference = int&;
|
||||
using pointer = int*;
|
||||
|
||||
int_iterator() = default;
|
||||
int_iterator(int i) :val(i) {}
|
||||
|
||||
value_type operator*() const { return val; }
|
||||
bool operator==(int_iterator rhs) const { return val == rhs.val; }
|
||||
bool operator!=(int_iterator rhs) const { return val != rhs.val; }
|
||||
int_iterator operator++() { ++val; return *this; }
|
||||
int_iterator operator++(int) {
|
||||
auto temp(*this);
|
||||
++val;
|
||||
return temp;
|
||||
}
|
||||
private:
|
||||
int val = 5;
|
||||
};
|
||||
|
||||
struct streamable_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const streamable_range&) {
|
||||
os << "op<<(streamable_range)";
|
||||
return os;
|
||||
}
|
||||
|
||||
struct stringmaker_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace Catch {
|
||||
template <>
|
||||
struct StringMaker<stringmaker_range> {
|
||||
static std::string convert(stringmaker_range const&) {
|
||||
return "stringmaker(streamable_range)";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct just_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
struct disabled_range {
|
||||
int_iterator begin() const { return int_iterator{ 1 }; }
|
||||
int_iterator end() const { return {}; }
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace Catch {
|
||||
template <>
|
||||
struct is_range<disabled_range> {
|
||||
static const bool value = false;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("stringify ranges", "[toString]") {
|
||||
REQUIRE(::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)");
|
||||
REQUIRE(::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)");
|
||||
REQUIRE(::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }");
|
||||
REQUIRE(::Catch::Detail::stringify(disabled_range{}) == "{ !!! }");
|
||||
}
|
404
tests/SelfTest/UsageTests/Tricky.tests.cpp
Normal file
404
tests/SelfTest/UsageTests/Tricky.tests.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Created by Phil on 09/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4702) // Disable unreachable code warning for the last test
|
||||
// that is triggered when compiling as Win32|Release
|
||||
#endif
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Where there is more to the expression after the RHS",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
// int a = 1, b = 2;
|
||||
// REQUIRE( a == 2 || b == 2 );
|
||||
WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" );
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Where the LHS is not a simple value",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
/*
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
|
||||
// This only captures part of the expression, but issues a warning about the rest
|
||||
REQUIRE( a+1 == b-1 );
|
||||
*/
|
||||
WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" );
|
||||
}
|
||||
|
||||
struct Opaque
|
||||
{
|
||||
int val;
|
||||
bool operator ==( const Opaque& o ) const
|
||||
{
|
||||
return val == o.val;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"A failing expression with a non streamable type is still captured",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
|
||||
Opaque o1, o2;
|
||||
o1.val = 7;
|
||||
o2.val = 8;
|
||||
|
||||
CHECK( &o1 == &o2 );
|
||||
CHECK( o1 == o2 );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"string literals of different sizes can be compared",
|
||||
"[Tricky][failing][.]"
|
||||
)
|
||||
{
|
||||
REQUIRE( std::string( "first" ) == "second" );
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"An expression with side-effects should only be evaluated once",
|
||||
"[Tricky]"
|
||||
)
|
||||
{
|
||||
int i = 7;
|
||||
|
||||
REQUIRE( i++ == 7 );
|
||||
REQUIRE( i++ == 8 );
|
||||
|
||||
}
|
||||
|
||||
namespace A {
|
||||
struct X
|
||||
{
|
||||
X() : a(4), b(2), c(7) {}
|
||||
X(int v) : a(v), b(2), c(7) {}
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
}
|
||||
|
||||
namespace B {
|
||||
struct Y
|
||||
{
|
||||
Y() : a(4), b(2), c(7) {}
|
||||
Y(int v) : a(v), b(2), c(7) {}
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
}
|
||||
|
||||
inline bool operator==(const A::X& lhs, const B::Y& rhs)
|
||||
{
|
||||
return (lhs.a == rhs.a);
|
||||
}
|
||||
|
||||
inline bool operator==(const B::Y& lhs, const A::X& rhs)
|
||||
{
|
||||
return (lhs.a == rhs.a);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/* This, currently, does not compile with LLVM
|
||||
TEST_CASE
|
||||
(
|
||||
"Operators at different namespace levels not hijacked by Koenig lookup"
|
||||
"[Tricky]"
|
||||
)
|
||||
{
|
||||
A::X x;
|
||||
B::Y y;
|
||||
REQUIRE( x == y );
|
||||
}
|
||||
*/
|
||||
|
||||
namespace ObjectWithConversions
|
||||
{
|
||||
struct Object
|
||||
{
|
||||
operator unsigned int() const {return 0xc0000000;}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TEST_CASE
|
||||
(
|
||||
"Implicit conversions are supported inside assertion macros",
|
||||
"[Tricky][approvals]"
|
||||
)
|
||||
{
|
||||
Object o;
|
||||
REQUIRE(0xc0000000 == o );
|
||||
}
|
||||
}
|
||||
|
||||
namespace EnumBitFieldTests
|
||||
{
|
||||
enum Bits : uint32_t {
|
||||
bit0 = 0x0001,
|
||||
bit1 = 0x0002,
|
||||
bit2 = 0x0004,
|
||||
bit3 = 0x0008,
|
||||
bit1and2 = bit1 | bit2,
|
||||
bit30 = 0x40000000,
|
||||
bit31 = 0x80000000,
|
||||
bit30and31 = bit30 | bit31
|
||||
};
|
||||
|
||||
TEST_CASE( "Test enum bit values", "[Tricky]" )
|
||||
{
|
||||
REQUIRE( 0xc0000000 == bit30and31 );
|
||||
}
|
||||
}
|
||||
|
||||
struct Obj
|
||||
{
|
||||
Obj():prop(&p){}
|
||||
|
||||
int p;
|
||||
int* prop;
|
||||
};
|
||||
|
||||
TEST_CASE("boolean member", "[Tricky]")
|
||||
{
|
||||
Obj obj;
|
||||
REQUIRE( obj.prop != nullptr );
|
||||
}
|
||||
|
||||
// Tests for a problem submitted by Ralph McArdell
|
||||
//
|
||||
// The static bool value should not need to be defined outside the
|
||||
// struct it is declared in - but when evaluating it in a deduced
|
||||
// context it appears to require the extra definition.
|
||||
// The issue was fixed by adding bool overloads to bypass the
|
||||
// templates that were there to deduce it.
|
||||
template <bool B>
|
||||
struct is_true
|
||||
{
|
||||
static const bool value = B;
|
||||
};
|
||||
|
||||
TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" )
|
||||
{
|
||||
SECTION("compare to true")
|
||||
{
|
||||
REQUIRE( is_true<true>::value == true );
|
||||
REQUIRE( true == is_true<true>::value );
|
||||
}
|
||||
SECTION("compare to false")
|
||||
{
|
||||
REQUIRE( is_true<false>::value == false );
|
||||
REQUIRE( false == is_true<false>::value );
|
||||
}
|
||||
|
||||
SECTION("negation")
|
||||
{
|
||||
REQUIRE( !is_true<false>::value );
|
||||
}
|
||||
|
||||
SECTION("double negation")
|
||||
{
|
||||
REQUIRE( !!is_true<true>::value );
|
||||
}
|
||||
|
||||
SECTION("direct")
|
||||
{
|
||||
REQUIRE( is_true<true>::value );
|
||||
REQUIRE_FALSE( is_true<false>::value );
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment these tests to produce an error at test registration time
|
||||
/*
|
||||
TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
|
||||
{
|
||||
|
||||
}
|
||||
TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
struct Boolable
|
||||
{
|
||||
explicit Boolable( bool value ) : m_value( value ) {}
|
||||
|
||||
explicit operator bool() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" )
|
||||
{
|
||||
Boolable True( true );
|
||||
Boolable False( false );
|
||||
|
||||
CHECK( True );
|
||||
CHECK( !False );
|
||||
CHECK_FALSE( False );
|
||||
}
|
||||
|
||||
TEST_CASE( "Assertions then sections", "[Tricky]" )
|
||||
{
|
||||
// This was causing a failure due to the way the console reporter was handling
|
||||
// the current section
|
||||
|
||||
REQUIRE( true );
|
||||
|
||||
SECTION( "A section" )
|
||||
{
|
||||
REQUIRE( true );
|
||||
|
||||
SECTION( "Another section" )
|
||||
{
|
||||
REQUIRE( true );
|
||||
}
|
||||
SECTION( "Another other section" )
|
||||
{
|
||||
REQUIRE( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Awkward
|
||||
{
|
||||
operator int() const { return 7; }
|
||||
};
|
||||
|
||||
TEST_CASE( "non streamable - with conv. op", "[Tricky]" )
|
||||
{
|
||||
Awkward awkward;
|
||||
std::string s = ::Catch::Detail::stringify( awkward );
|
||||
REQUIRE( s == "7" );
|
||||
}
|
||||
|
||||
inline void foo() {}
|
||||
|
||||
typedef void (*fooptr_t)();
|
||||
|
||||
TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" )
|
||||
{
|
||||
// This was giving a warning in VS2010
|
||||
// #179
|
||||
fooptr_t a = foo;
|
||||
|
||||
REQUIRE( a );
|
||||
REQUIRE( a == &foo );
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
void f() {}
|
||||
};
|
||||
|
||||
|
||||
TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer][approvals]" )
|
||||
{
|
||||
typedef void (S::*MF)();
|
||||
MF m = &S::f;
|
||||
|
||||
CHECK( m == &S::f );
|
||||
}
|
||||
|
||||
class ClassName {};
|
||||
|
||||
TEST_CASE( "pointer to class", "[Tricky]" )
|
||||
{
|
||||
ClassName *p = 0;
|
||||
REQUIRE( p == 0 );
|
||||
}
|
||||
|
||||
#include <memory>
|
||||
|
||||
TEST_CASE( "null_ptr", "[Tricky]" )
|
||||
{
|
||||
std::unique_ptr<int> ptr;
|
||||
REQUIRE(ptr.get() == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); }
|
||||
TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); }
|
||||
TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); }
|
||||
TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); }
|
||||
|
||||
TEST_CASE( "has printf" ) {
|
||||
|
||||
// This can cause problems as, currently, stdout itself is not redirected - only the cout (and cerr) buffer
|
||||
printf( "loose text artifact\n" );
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct constructor_throws {
|
||||
[[noreturn]] constructor_throws() {
|
||||
throw 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Commas in various macros are allowed") {
|
||||
REQUIRE_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} );
|
||||
CHECK_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} );
|
||||
REQUIRE_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} );
|
||||
CHECK_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} );
|
||||
|
||||
REQUIRE(std::vector<int>{1, 2} == std::vector<int>{1, 2});
|
||||
CHECK( std::vector<int>{1, 2} == std::vector<int>{1, 2} );
|
||||
REQUIRE_FALSE(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3});
|
||||
CHECK_FALSE( std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} );
|
||||
|
||||
CHECK_NOFAIL( std::vector<int>{1, 2} == std::vector<int>{1, 2} );
|
||||
CHECKED_IF( std::vector<int>{1, 2} == std::vector<int>{1, 2} ) {
|
||||
REQUIRE(true);
|
||||
} CHECKED_ELSE( std::vector<int>{1, 2} == std::vector<int>{1, 2} ) {
|
||||
CHECK(true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "non-copyable objects", "[.][failing]" ) {
|
||||
// Thanks to Agustin Bergé (@k-ballo on the cpplang Slack) for raising this
|
||||
std::type_info const& ti = typeid(int);
|
||||
CHECK( ti == typeid(int) );
|
||||
}
|
||||
|
||||
TEST_CASE("#1514: stderr/stdout is not captured in tests aborted by an exception", "[output-capture][regression][.]") {
|
||||
std::cout << "This would not be caught previously\n" << std::flush;
|
||||
std::clog << "Nor would this\n" << std::flush;
|
||||
// FAIL aborts the test by throwing a Catch exception
|
||||
FAIL("1514");
|
||||
}
|
29
tests/SelfTest/UsageTests/VariadicMacros.tests.cpp
Normal file
29
tests/SelfTest/UsageTests/VariadicMacros.tests.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Created by Phil on 15/03/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
||||
TEST_CASE()
|
||||
{
|
||||
SUCCEED( "anonymous test case" );
|
||||
}
|
||||
|
||||
TEST_CASE( "Test case with one argument" )
|
||||
{
|
||||
SUCCEED( "no assertions" );
|
||||
}
|
||||
|
||||
TEST_CASE( "Variadic macros", "[variadic][sections]" )
|
||||
{
|
||||
SECTION( "Section with one argument" )
|
||||
{
|
||||
SUCCEED( "no assertions" );
|
||||
}
|
||||
}
|
||||
|
19
tests/SelfTest/WarnAboutNoTests.cmake
Normal file
19
tests/SelfTest/WarnAboutNoTests.cmake
Normal file
@@ -0,0 +1,19 @@
|
||||
# Workaround for a peculiarity where CTest disregards the return code from a
|
||||
# test command if a PASS_REGULAR_EXPRESSION is also set
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_ARGV3} -w NoTests "___nonexistent_test___"
|
||||
RESULT_VARIABLE ret
|
||||
OUTPUT_VARIABLE out
|
||||
)
|
||||
|
||||
message("${out}")
|
||||
|
||||
if(NOT ${ret} MATCHES "^[0-9]+$")
|
||||
message(FATAL_ERROR "${ret}")
|
||||
endif()
|
||||
|
||||
if(${ret} EQUAL 0)
|
||||
message(FATAL_ERROR "Expected nonzero return code")
|
||||
elseif(${out} MATCHES "Helper failed with")
|
||||
message(FATAL_ERROR "Helper failed")
|
||||
endif()
|
294
tests/XCode/OCTest/OCTest.xcodeproj/project.pbxproj
Normal file
294
tests/XCode/OCTest/OCTest.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,294 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
4A5C29AA1F715603007CB94C /* catch_objc_impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C29A91F715603007CB94C /* catch_objc_impl.mm */; };
|
||||
4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A63D2AB14E3C1A900F615CB /* OCTest.1 */; };
|
||||
4A63D2B314E3C1E600F615CB /* Main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2B214E3C1E600F615CB /* Main.mm */; };
|
||||
4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A63D2BF14E4544700F615CB /* Foundation.framework */; };
|
||||
4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */; };
|
||||
4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C314E454CC00F615CB /* OCTest.mm */; };
|
||||
4A63D2C814E454CC00F615CB /* TestObj.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C514E454CC00F615CB /* TestObj.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
4A63D2A314E3C1A900F615CB /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
4A5C29A91F715603007CB94C /* catch_objc_impl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = catch_objc_impl.mm; sourceTree = "<group>"; };
|
||||
4A63D2A514E3C1A900F615CB /* OCTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OCTest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4A63D2AB14E3C1A900F615CB /* OCTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = OCTest.1; sourceTree = "<group>"; };
|
||||
4A63D2B214E3C1E600F615CB /* Main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Main.mm; sourceTree = "<group>"; };
|
||||
4A63D2BF14E4544700F615CB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CatchOCTestCase.h; sourceTree = "<group>"; };
|
||||
4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CatchOCTestCase.mm; sourceTree = "<group>"; };
|
||||
4A63D2C314E454CC00F615CB /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = "<group>"; };
|
||||
4A63D2C414E454CC00F615CB /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = "<group>"; };
|
||||
4A63D2C514E454CC00F615CB /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
4A63D2A214E3C1A900F615CB /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
4A63D29A14E3C1A900F615CB = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4AA0D94F154C0A63004B4193 /* Catch */,
|
||||
4A63D2BF14E4544700F615CB /* Foundation.framework */,
|
||||
4A63D2A814E3C1A900F615CB /* OCTest */,
|
||||
4A63D2A614E3C1A900F615CB /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4A63D2A614E3C1A900F615CB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4A63D2A514E3C1A900F615CB /* OCTest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4A63D2A814E3C1A900F615CB /* OCTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */,
|
||||
4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */,
|
||||
4A63D2C314E454CC00F615CB /* OCTest.mm */,
|
||||
4A63D2C414E454CC00F615CB /* TestObj.h */,
|
||||
4A63D2C514E454CC00F615CB /* TestObj.m */,
|
||||
4A63D2B214E3C1E600F615CB /* Main.mm */,
|
||||
4A63D2AB14E3C1A900F615CB /* OCTest.1 */,
|
||||
);
|
||||
path = OCTest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4AA0D94F154C0A63004B4193 /* Catch */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4A5C29A91F715603007CB94C /* catch_objc_impl.mm */,
|
||||
);
|
||||
name = Catch;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
4A63D2A414E3C1A900F615CB /* OCTest */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */;
|
||||
buildPhases = (
|
||||
4A63D2A114E3C1A900F615CB /* Sources */,
|
||||
4A63D2A214E3C1A900F615CB /* Frameworks */,
|
||||
4A63D2A314E3C1A900F615CB /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = OCTest;
|
||||
productName = OCTest;
|
||||
productReference = 4A63D2A514E3C1A900F615CB /* OCTest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
4A63D29C14E3C1A900F615CB /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0940;
|
||||
};
|
||||
buildConfigurationList = 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 4A63D29A14E3C1A900F615CB;
|
||||
productRefGroup = 4A63D2A614E3C1A900F615CB /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
4A63D2A414E3C1A900F615CB /* OCTest */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
4A63D2A114E3C1A900F615CB /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4A63D2B314E3C1E600F615CB /* Main.mm in Sources */,
|
||||
4A5C29AA1F715603007CB94C /* catch_objc_impl.mm in Sources */,
|
||||
4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */,
|
||||
4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */,
|
||||
4A63D2C814E454CC00F615CB /* TestObj.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
4A63D2AD14E3C1A900F615CB /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = ../../../include;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4A63D2AE14E3C1A900F615CB /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = ../../../include;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4A63D2B014E3C1A900F615CB /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
HEADER_SEARCH_PATHS = ../../../include;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4A63D2B114E3C1A900F615CB /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
HEADER_SEARCH_PATHS = ../../../include;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4A63D2AD14E3C1A900F615CB /* Debug */,
|
||||
4A63D2AE14E3C1A900F615CB /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4A63D2B014E3C1A900F615CB /* Debug */,
|
||||
4A63D2B114E3C1A900F615CB /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 4A63D29C14E3C1A900F615CB /* Project object */;
|
||||
}
|
7
tests/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
tests/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:OCTest.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
25
tests/XCode/OCTest/OCTest/CatchOCTestCase.h
Normal file
25
tests/XCode/OCTest/OCTest/CatchOCTestCase.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// CatchOCTestCase.h
|
||||
// OCTest
|
||||
//
|
||||
// Created by Phil on 13/11/2010.
|
||||
// Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED
|
||||
#define TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "TestObj.h"
|
||||
|
||||
@interface TestFixture : NSObject <OcFixture>
|
||||
{
|
||||
TestObj* obj;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif // TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED
|
87
tests/XCode/OCTest/OCTest/CatchOCTestCase.mm
Normal file
87
tests/XCode/OCTest/OCTest/CatchOCTestCase.mm
Normal file
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// CatchOCTestCase.mm
|
||||
// OCTest
|
||||
//
|
||||
// Created by Phil Nash on 13/11/2010.
|
||||
// Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#import "CatchOCTestCase.h"
|
||||
|
||||
|
||||
@implementation TestFixture
|
||||
|
||||
|
||||
-(void) setUp
|
||||
{
|
||||
obj = [[TestObj alloc] init];
|
||||
}
|
||||
|
||||
-(void) tearDown
|
||||
{
|
||||
arcSafeRelease( obj );
|
||||
}
|
||||
|
||||
OC_TEST_CASE( "This is a test case", "" )
|
||||
{
|
||||
REQUIRE( obj.int_val == 0 );
|
||||
|
||||
obj.int_val = 1;
|
||||
|
||||
REQUIRE( obj.int_val == 1 );
|
||||
}
|
||||
|
||||
OC_TEST_CASE( "This is another test case", "" )
|
||||
{
|
||||
REQUIRE( obj.int_val == 0 );
|
||||
|
||||
obj.int_val = 2;
|
||||
|
||||
REQUIRE( obj.int_val == 2 );
|
||||
}
|
||||
|
||||
OC_TEST_CASE( "tests a boolean value", "[!shouldfail]" )
|
||||
{
|
||||
CHECK( [obj isTrue] == NO );
|
||||
CHECK( [obj isFalse] == YES );
|
||||
}
|
||||
|
||||
OC_TEST_CASE( "throws an Objective-C exception", "[!throws][!shouldfail]" )
|
||||
{
|
||||
@throw [[NSException alloc] initWithName: NSGenericException
|
||||
reason: @"Objective-C exception"
|
||||
userInfo: nil];
|
||||
}
|
||||
OC_TEST_CASE( "throws a std c++ exception", "[!throws][!shouldfail]" )
|
||||
{
|
||||
throw std::domain_error( "std C++ exception" );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename T>
|
||||
void useObject( const T& object ){}
|
||||
|
||||
template<typename T>
|
||||
void useObject( const T* object ){}
|
||||
|
||||
OC_TEST_CASE( "Matches work with OC types (NSString so far)", "[!shouldfail]" )
|
||||
{
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
REQUIRE_THAT( @"This is a string", Equals( @"This isn't a string" ) );
|
||||
REQUIRE_THAT( @"This is a string", Contains( @"is a" ) );
|
||||
REQUIRE_THAT( @"This is a string", StartsWith( @"This" ) );
|
||||
REQUIRE_THAT( @"This is a string", EndsWith( @"string" ) );
|
||||
}
|
||||
|
||||
OC_TEST_CASE( "nil NSString should not crash the test", "[!shouldfail]" )
|
||||
{
|
||||
using namespace Catch::Matchers;
|
||||
|
||||
CHECK_THAT( (NSString*)nil, Equals( @"This should fail, but not crash" ) );
|
||||
CHECK_THAT( (NSString*)nil, StartsWith( @"anything" ) );
|
||||
}
|
||||
|
||||
@end
|
2
tests/XCode/OCTest/OCTest/Main.mm
Normal file
2
tests/XCode/OCTest/OCTest/Main.mm
Normal file
@@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#import "catch.hpp"
|
79
tests/XCode/OCTest/OCTest/OCTest.1
Normal file
79
tests/XCode/OCTest/OCTest/OCTest.1
Normal file
@@ -0,0 +1,79 @@
|
||||
.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
|
||||
.\"See Also:
|
||||
.\"man mdoc.samples for a complete listing of options
|
||||
.\"man mdoc for the short list of editing options
|
||||
.\"/usr/share/misc/mdoc.template
|
||||
.Dd 09/02/2012 \" DATE
|
||||
.Dt OCTest 1 \" Program name and manual section number
|
||||
.Os Darwin
|
||||
.Sh NAME \" Section Header - required - don't modify
|
||||
.Nm OCTest,
|
||||
.\" The following lines are read in generating the apropos(man -k) database. Use only key
|
||||
.\" words here as the database is built based on the words here and in the .ND line.
|
||||
.Nm Other_name_for_same_program(),
|
||||
.Nm Yet another name for the same program.
|
||||
.\" Use .Nm macro to designate other names for the documented program.
|
||||
.Nd This line parsed for whatis database.
|
||||
.Sh SYNOPSIS \" Section Header - required - don't modify
|
||||
.Nm
|
||||
.Op Fl abcd \" [-abcd]
|
||||
.Op Fl a Ar path \" [-a path]
|
||||
.Op Ar file \" [file]
|
||||
.Op Ar \" [file ...]
|
||||
.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
|
||||
arg2 ... \" Arguments
|
||||
.Sh DESCRIPTION \" Section Header - required - don't modify
|
||||
Use the .Nm macro to refer to your program throughout the man page like such:
|
||||
.Nm
|
||||
Underlining is accomplished with the .Ar macro like this:
|
||||
.Ar underlined text .
|
||||
.Pp \" Inserts a space
|
||||
A list of items with descriptions:
|
||||
.Bl -tag -width -indent \" Begins a tagged list
|
||||
.It item a \" Each item preceded by .It macro
|
||||
Description of item a
|
||||
.It item b
|
||||
Description of item b
|
||||
.El \" Ends the list
|
||||
.Pp
|
||||
A list of flags and their descriptions:
|
||||
.Bl -tag -width -indent \" Differs from above in tag removed
|
||||
.It Fl a \"-a flag as a list item
|
||||
Description of -a flag
|
||||
.It Fl b
|
||||
Description of -b flag
|
||||
.El \" Ends the list
|
||||
.Pp
|
||||
.\" .Sh ENVIRONMENT \" May not be needed
|
||||
.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
|
||||
.\" .It Ev ENV_VAR_1
|
||||
.\" Description of ENV_VAR_1
|
||||
.\" .It Ev ENV_VAR_2
|
||||
.\" Description of ENV_VAR_2
|
||||
.\" .El
|
||||
.Sh FILES \" File used or created by the topic of the man page
|
||||
.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
|
||||
.It Pa /usr/share/file_name
|
||||
FILE_1 description
|
||||
.It Pa /Users/joeuser/Library/really_long_file_name
|
||||
FILE_2 description
|
||||
.El \" Ends the list
|
||||
.\" .Sh DIAGNOSTICS \" May not be needed
|
||||
.\" .Bl -diag
|
||||
.\" .It Diagnostic Tag
|
||||
.\" Diagnostic information here.
|
||||
.\" .It Diagnostic Tag
|
||||
.\" Diagnostic information here.
|
||||
.\" .El
|
||||
.Sh SEE ALSO
|
||||
.\" List links in ascending order by section, alphabetically within a section.
|
||||
.\" Please do not reference files that do not exist without filing a bug report
|
||||
.Xr a 1 ,
|
||||
.Xr b 1 ,
|
||||
.Xr c 1 ,
|
||||
.Xr a 2 ,
|
||||
.Xr b 2 ,
|
||||
.Xr a 3 ,
|
||||
.Xr b 3
|
||||
.\" .Sh BUGS \" Document known, unremedied bugs
|
||||
.\" .Sh HISTORY \" Document history if command behaves in a unique manner
|
28
tests/XCode/OCTest/OCTest/OCTest.mm
Normal file
28
tests/XCode/OCTest/OCTest/OCTest.mm
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* OCTest.mm
|
||||
* OCTest
|
||||
*
|
||||
* Created by Phil on 13/11/2010.
|
||||
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
*/
|
||||
|
||||
#import "catch.hpp"
|
||||
|
||||
#import "TestObj.h"
|
||||
|
||||
TEST_CASE( "OCTest/TestObj", "tests TestObj" )
|
||||
{
|
||||
TestObj* obj = [[TestObj alloc] init];
|
||||
|
||||
REQUIRE( obj.int_val == 0 );
|
||||
|
||||
obj.int_val = 1;
|
||||
|
||||
REQUIRE( obj.int_val == 1 );
|
||||
|
||||
arcSafeRelease( obj );
|
||||
}
|
28
tests/XCode/OCTest/OCTest/TestObj.h
Normal file
28
tests/XCode/OCTest/OCTest/TestObj.h
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// TestObj.h
|
||||
// OCTest
|
||||
//
|
||||
// Created by Phil on 13/11/2010.
|
||||
// Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef TWOBLUECUBES_TESTOBJ_H_INCLUDED
|
||||
#define TWOBLUECUBES_TESTOBJ_H_INCLUDED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface TestObj : NSObject {
|
||||
|
||||
int int_val;
|
||||
}
|
||||
|
||||
-(BOOL) isTrue;
|
||||
-(BOOL) isFalse;
|
||||
|
||||
@property (nonatomic, assign ) int int_val;
|
||||
|
||||
@end
|
||||
|
||||
#endif // TWOBLUECUBES_TESTOBJ_H_INCLUDED
|
25
tests/XCode/OCTest/OCTest/TestObj.m
Normal file
25
tests/XCode/OCTest/OCTest/TestObj.m
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// TestObj.m
|
||||
// OCTest
|
||||
//
|
||||
// Created by Phil on 13/11/2010.
|
||||
// Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#import "TestObj.h"
|
||||
|
||||
|
||||
@implementation TestObj
|
||||
|
||||
@synthesize int_val;
|
||||
|
||||
-(BOOL) isTrue {
|
||||
return YES;
|
||||
}
|
||||
-(BOOL) isFalse {
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
69
tests/XCode/OCTest/catch_objc_impl.mm
Normal file
69
tests/XCode/OCTest/catch_objc_impl.mm
Normal file
@@ -0,0 +1,69 @@
|
||||
// This file #includes all the .cpp files into a single .mm
|
||||
// - so they get compiled as ObjectiveC++
|
||||
|
||||
#include "../../../include/internal/catch_tostring.cpp"
|
||||
#include "../../../include/internal/catch_approx.cpp"
|
||||
#include "../../../include/internal/catch_assertionhandler.cpp"
|
||||
#include "../../../include/internal/catch_assertionresult.cpp"
|
||||
#include "../../../include/internal/catch_benchmark.cpp"
|
||||
#include "../../../include/internal/catch_capture_matchers.cpp"
|
||||
#include "../../../include/internal/catch_commandline.cpp"
|
||||
#include "../../../include/internal/catch_common.cpp"
|
||||
#include "../../../include/internal/catch_config.cpp"
|
||||
#include "../../../include/internal/catch_console_colour.cpp"
|
||||
#include "../../../include/internal/catch_context.cpp"
|
||||
#include "../../../include/internal/catch_debug_console.cpp"
|
||||
#include "../../../include/internal/catch_debugger.cpp"
|
||||
#include "../../../include/internal/catch_decomposer.cpp"
|
||||
#include "../../../include/internal/catch_errno_guard.cpp"
|
||||
#include "../../../include/internal/catch_exception_translator_registry.cpp"
|
||||
#include "../../../include/internal/catch_fatal_condition.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_capture.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_config.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_exception.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_registry_hub.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_reporter.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_runner.cpp"
|
||||
#include "../../../include/internal/catch_interfaces_testcase.cpp"
|
||||
#include "../../../include/internal/catch_leak_detector.cpp"
|
||||
#include "../../../include/internal/catch_list.cpp"
|
||||
#include "../../../include/internal/catch_matchers.cpp"
|
||||
#include "../../../include/internal/catch_matchers_string.cpp"
|
||||
#include "../../../include/internal/catch_message.cpp"
|
||||
#include "../../../include/internal/catch_output_redirect.cpp"
|
||||
#include "../../../include/internal/catch_random_number_generator.cpp"
|
||||
#include "../../../include/internal/catch_registry_hub.cpp"
|
||||
#include "../../../include/internal/catch_reporter_registry.cpp"
|
||||
#include "../../../include/internal/catch_result_type.cpp"
|
||||
#include "../../../include/internal/catch_run_context.cpp"
|
||||
#include "../../../include/internal/catch_section.cpp"
|
||||
#include "../../../include/internal/catch_section_info.cpp"
|
||||
#include "../../../include/internal/catch_session.cpp"
|
||||
#include "../../../include/internal/catch_startup_exception_registry.cpp"
|
||||
#include "../../../include/internal/catch_stream.cpp"
|
||||
#include "../../../include/internal/catch_string_manip.cpp"
|
||||
#include "../../../include/internal/catch_stringref.cpp"
|
||||
#include "../../../include/internal/catch_tag_alias.cpp"
|
||||
#include "../../../include/internal/catch_tag_alias_autoregistrar.cpp"
|
||||
#include "../../../include/internal/catch_tag_alias_registry.cpp"
|
||||
#include "../../../include/internal/catch_test_case_info.cpp"
|
||||
#include "../../../include/internal/catch_test_case_registry_impl.cpp"
|
||||
#include "../../../include/internal/catch_test_case_tracker.cpp"
|
||||
#include "../../../include/internal/catch_test_registry.cpp"
|
||||
#include "../../../include/internal/catch_test_spec.cpp"
|
||||
#include "../../../include/internal/catch_test_spec_parser.cpp"
|
||||
#include "../../../include/internal/catch_timer.cpp"
|
||||
#include "../../../include/internal/catch_totals.cpp"
|
||||
#include "../../../include/internal/catch_uncaught_exceptions.cpp"
|
||||
#include "../../../include/internal/catch_version.cpp"
|
||||
#include "../../../include/internal/catch_wildcard_pattern.cpp"
|
||||
#include "../../../include/internal/catch_xmlwriter.cpp"
|
||||
|
||||
|
||||
// Reporters
|
||||
#include "../../../include/reporters/catch_reporter_bases.cpp"
|
||||
#include "../../../include/reporters/catch_reporter_compact.cpp"
|
||||
#include "../../../include/reporters/catch_reporter_console.cpp"
|
||||
#include "../../../include/reporters/catch_reporter_junit.cpp"
|
||||
#include "../../../include/reporters/catch_reporter_listening.cpp"
|
||||
#include "../../../include/reporters/catch_reporter_xml.cpp"
|
Reference in New Issue
Block a user