mirror of
https://github.com/catchorg/Catch2.git
synced 2025-09-17 18:35:40 +02:00
Compare commits
137 Commits
v2.0.0-dev
...
v2.0.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
19ab2117c5 | ||
![]() |
4acf112c19 | ||
![]() |
53f6d3fc8e | ||
![]() |
cf76a795cc | ||
![]() |
811f4d13d7 | ||
![]() |
7423a481eb | ||
![]() |
46c7c9d3a0 | ||
![]() |
b119ebdde1 | ||
![]() |
1c43fb64c1 | ||
![]() |
8b40c26434 | ||
![]() |
fe05062f9e | ||
![]() |
31cc62e6b7 | ||
![]() |
a49e6fdc27 | ||
![]() |
2d91035404 | ||
![]() |
accf9859b4 | ||
![]() |
22ac9d2184 | ||
![]() |
00af677577 | ||
![]() |
ae21020640 | ||
![]() |
11f716f28d | ||
![]() |
c3ddd4a7e2 | ||
![]() |
c43ce85416 | ||
![]() |
4220f2eef2 | ||
![]() |
c1a91caf00 | ||
![]() |
96c5de678d | ||
![]() |
e68485e196 | ||
![]() |
88e912b4d1 | ||
![]() |
44244713f1 | ||
![]() |
eea9e1efd7 | ||
![]() |
2a3606f8e3 | ||
![]() |
a6cf19abff | ||
![]() |
601b2888ec | ||
![]() |
3049445d78 | ||
![]() |
c672512979 | ||
![]() |
57b4e0b64c | ||
![]() |
06586b7180 | ||
![]() |
93b3d2cb8f | ||
![]() |
a90473df28 | ||
![]() |
75a77b6f8c | ||
![]() |
5af918eefd | ||
![]() |
c9d9699ca8 | ||
![]() |
296955c437 | ||
![]() |
664cbf702c | ||
![]() |
fb6700df54 | ||
![]() |
05b1ca2884 | ||
![]() |
da6c2a6914 | ||
![]() |
c2b7bd15c0 | ||
![]() |
ba6845a865 | ||
![]() |
2eb93f47f7 | ||
![]() |
276393e4e5 | ||
![]() |
c7d9f02d5b | ||
![]() |
355ab78f4a | ||
![]() |
927f520a97 | ||
![]() |
cc0b093c20 | ||
![]() |
17cdf20968 | ||
![]() |
4899d891d3 | ||
![]() |
760a25e813 | ||
![]() |
79b405fd3f | ||
![]() |
f972732737 | ||
![]() |
61280e6d0a | ||
![]() |
7e9b53e40c | ||
![]() |
b80c5134f0 | ||
![]() |
70e0d48978 | ||
![]() |
11918b76d0 | ||
![]() |
5fe19f73e7 | ||
![]() |
c1416d55cb | ||
![]() |
2a1f8ae684 | ||
![]() |
9541e89e6a | ||
![]() |
80bbce8424 | ||
![]() |
3d49d83128 | ||
![]() |
bd46f66754 | ||
![]() |
e9f0773f37 | ||
![]() |
54f1ce2af2 | ||
![]() |
0a146e3af7 | ||
![]() |
b9ff7ec301 | ||
![]() |
a63b4a75bd | ||
![]() |
8da0d0473b | ||
![]() |
40209d1ae0 | ||
![]() |
4e85267203 | ||
![]() |
eaf850cd0c | ||
![]() |
9c07718b5f | ||
![]() |
9aa96712ae | ||
![]() |
6105282c4f | ||
![]() |
ca7021ae19 | ||
![]() |
03d41ce5b9 | ||
![]() |
c5608f0202 | ||
![]() |
8c39f9a725 | ||
![]() |
4e5a67bc44 | ||
![]() |
2d37649377 | ||
![]() |
8d03cb4915 | ||
![]() |
b000411434 | ||
![]() |
aef2e4d9e7 | ||
![]() |
ab5d176195 | ||
![]() |
b3a923133d | ||
![]() |
35bad89684 | ||
![]() |
792d3d0a26 | ||
![]() |
be067bce37 | ||
![]() |
115db71bab | ||
![]() |
3a5b951256 | ||
![]() |
4e4a13dfb4 | ||
![]() |
e8ec6bd73c | ||
![]() |
e871742534 | ||
![]() |
6388fc946f | ||
![]() |
a4df0b2c37 | ||
![]() |
97edf7ce65 | ||
![]() |
49a1408ff2 | ||
![]() |
9796c516bb | ||
![]() |
255f7d7369 | ||
![]() |
46e28791ff | ||
![]() |
0673b9be35 | ||
![]() |
48db47c737 | ||
![]() |
cde57d9365 | ||
![]() |
13213faa4e | ||
![]() |
5ca44b6872 | ||
![]() |
a04bd6d436 | ||
![]() |
784f6dfb34 | ||
![]() |
7818e2666d | ||
![]() |
cd30dd1a70 | ||
![]() |
8e8c0c1675 | ||
![]() |
b6e7c9bd7a | ||
![]() |
180d9242f5 | ||
![]() |
b7bd52cc98 | ||
![]() |
b07a2bdf87 | ||
![]() |
c03e8fce92 | ||
![]() |
27640a5a96 | ||
![]() |
dd3867bbcd | ||
![]() |
387f8d254d | ||
![]() |
c65eccd68e | ||
![]() |
61c5675c11 | ||
![]() |
70e4af9d44 | ||
![]() |
8f41bdb92d | ||
![]() |
7fa5d9ca94 | ||
![]() |
feaf355489 | ||
![]() |
2ce6c74f8f | ||
![]() |
9688891868 | ||
![]() |
4f21bb72ff | ||
![]() |
b435e0d7c7 | ||
![]() |
ba0a09fd9e |
@@ -9,6 +9,7 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|||||||
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
|
||||||
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
|
set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark)
|
||||||
set(HEADER_DIR ${CATCH_DIR}/include)
|
set(HEADER_DIR ${CATCH_DIR}/include)
|
||||||
|
set(CATCH_VERSION_NUMBER 2.0.1)
|
||||||
|
|
||||||
if(USE_CPP14)
|
if(USE_CPP14)
|
||||||
message(STATUS "Enabling C++14")
|
message(STATUS "Enabling C++14")
|
||||||
@@ -68,6 +69,7 @@ set(TEST_SOURCES
|
|||||||
${SELF_TEST_DIR}/PartTrackerTests.cpp
|
${SELF_TEST_DIR}/PartTrackerTests.cpp
|
||||||
${SELF_TEST_DIR}/TagAliasTests.cpp
|
${SELF_TEST_DIR}/TagAliasTests.cpp
|
||||||
${SELF_TEST_DIR}/TestMain.cpp
|
${SELF_TEST_DIR}/TestMain.cpp
|
||||||
|
${SELF_TEST_DIR}/ToStringChrono.cpp
|
||||||
${SELF_TEST_DIR}/ToStringGeneralTests.cpp
|
${SELF_TEST_DIR}/ToStringGeneralTests.cpp
|
||||||
${SELF_TEST_DIR}/ToStringPair.cpp
|
${SELF_TEST_DIR}/ToStringPair.cpp
|
||||||
${SELF_TEST_DIR}/ToStringTuple.cpp
|
${SELF_TEST_DIR}/ToStringTuple.cpp
|
||||||
@@ -85,16 +87,9 @@ CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
|
|||||||
set(SURROGATE_SOURCES
|
set(SURROGATE_SOURCES
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_registry_hub.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp
|
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
|
||||||
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
|
${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
|
||||||
@@ -105,7 +100,6 @@ CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
|
|||||||
# Please keep these ordered alphabetically
|
# Please keep these ordered alphabetically
|
||||||
set(TOP_LEVEL_HEADERS
|
set(TOP_LEVEL_HEADERS
|
||||||
${HEADER_DIR}/catch.hpp
|
${HEADER_DIR}/catch.hpp
|
||||||
${HEADER_DIR}/catch_session.hpp
|
|
||||||
${HEADER_DIR}/catch_with_main.hpp
|
${HEADER_DIR}/catch_with_main.hpp
|
||||||
)
|
)
|
||||||
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
|
CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
|
||||||
@@ -119,18 +113,18 @@ CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
|
|||||||
|
|
||||||
# Please keep these ordered alphabetically
|
# Please keep these ordered alphabetically
|
||||||
set(INTERNAL_HEADERS
|
set(INTERNAL_HEADERS
|
||||||
${HEADER_DIR}/internal/catch_approx.hpp
|
${HEADER_DIR}/internal/catch_approx.h
|
||||||
${HEADER_DIR}/internal/catch_assertionhandler.h
|
${HEADER_DIR}/internal/catch_assertionhandler.h
|
||||||
${HEADER_DIR}/internal/catch_assertioninfo.h
|
${HEADER_DIR}/internal/catch_assertioninfo.h
|
||||||
${HEADER_DIR}/internal/catch_assertionresult.h
|
${HEADER_DIR}/internal/catch_assertionresult.h
|
||||||
${HEADER_DIR}/internal/catch_capture.hpp
|
${HEADER_DIR}/internal/catch_capture.hpp
|
||||||
${HEADER_DIR}/internal/catch_capture_matchers.h
|
${HEADER_DIR}/internal/catch_capture_matchers.h
|
||||||
${HEADER_DIR}/internal/catch_clara.h
|
${HEADER_DIR}/internal/catch_clara.h
|
||||||
${HEADER_DIR}/internal/catch_commandline.hpp
|
${HEADER_DIR}/internal/catch_commandline.h
|
||||||
${HEADER_DIR}/internal/catch_common.h
|
${HEADER_DIR}/internal/catch_common.h
|
||||||
${HEADER_DIR}/internal/catch_compiler_capabilities.h
|
${HEADER_DIR}/internal/catch_compiler_capabilities.h
|
||||||
${HEADER_DIR}/internal/catch_config.hpp
|
${HEADER_DIR}/internal/catch_config.hpp
|
||||||
${HEADER_DIR}/internal/catch_console_colour.hpp
|
${HEADER_DIR}/internal/catch_console_colour.h
|
||||||
${HEADER_DIR}/internal/catch_context.h
|
${HEADER_DIR}/internal/catch_context.h
|
||||||
${HEADER_DIR}/internal/catch_debug_console.h
|
${HEADER_DIR}/internal/catch_debug_console.h
|
||||||
${HEADER_DIR}/internal/catch_debugger.h
|
${HEADER_DIR}/internal/catch_debugger.h
|
||||||
@@ -152,23 +146,24 @@ set(INTERNAL_HEADERS
|
|||||||
${HEADER_DIR}/internal/catch_interfaces_testcase.h
|
${HEADER_DIR}/internal/catch_interfaces_testcase.h
|
||||||
${HEADER_DIR}/internal/catch_leak_detector.h
|
${HEADER_DIR}/internal/catch_leak_detector.h
|
||||||
${HEADER_DIR}/internal/catch_list.h
|
${HEADER_DIR}/internal/catch_list.h
|
||||||
${HEADER_DIR}/internal/catch_matchers.hpp
|
${HEADER_DIR}/internal/catch_matchers.h
|
||||||
${HEADER_DIR}/internal/catch_matchers_string.h
|
${HEADER_DIR}/internal/catch_matchers_string.h
|
||||||
${HEADER_DIR}/internal/catch_matchers_vector.h
|
${HEADER_DIR}/internal/catch_matchers_vector.h
|
||||||
${HEADER_DIR}/internal/catch_message.h
|
${HEADER_DIR}/internal/catch_message.h
|
||||||
${HEADER_DIR}/internal/catch_notimplemented_exception.h
|
|
||||||
${HEADER_DIR}/internal/catch_objc.hpp
|
${HEADER_DIR}/internal/catch_objc.hpp
|
||||||
${HEADER_DIR}/internal/catch_objc_arc.hpp
|
${HEADER_DIR}/internal/catch_objc_arc.hpp
|
||||||
${HEADER_DIR}/internal/catch_option.hpp
|
${HEADER_DIR}/internal/catch_option.hpp
|
||||||
${HEADER_DIR}/internal/catch_platform.h
|
${HEADER_DIR}/internal/catch_platform.h
|
||||||
|
${HEADER_DIR}/internal/catch_random_number_generator.h
|
||||||
${HEADER_DIR}/internal/catch_reenable_warnings.h
|
${HEADER_DIR}/internal/catch_reenable_warnings.h
|
||||||
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
|
${HEADER_DIR}/internal/catch_reporter_registrars.hpp
|
||||||
${HEADER_DIR}/internal/catch_reporter_registry.hpp
|
${HEADER_DIR}/internal/catch_reporter_registry.h
|
||||||
${HEADER_DIR}/internal/catch_result_type.h
|
${HEADER_DIR}/internal/catch_result_type.h
|
||||||
${HEADER_DIR}/internal/catch_run_context.hpp
|
${HEADER_DIR}/internal/catch_run_context.h
|
||||||
${HEADER_DIR}/internal/catch_benchmark.h
|
${HEADER_DIR}/internal/catch_benchmark.h
|
||||||
${HEADER_DIR}/internal/catch_section.h
|
${HEADER_DIR}/internal/catch_section.h
|
||||||
${HEADER_DIR}/internal/catch_section_info.h
|
${HEADER_DIR}/internal/catch_section_info.h
|
||||||
|
${HEADER_DIR}/internal/catch_session.h
|
||||||
${HEADER_DIR}/internal/catch_startup_exception_registry.h
|
${HEADER_DIR}/internal/catch_startup_exception_registry.h
|
||||||
${HEADER_DIR}/internal/catch_stream.h
|
${HEADER_DIR}/internal/catch_stream.h
|
||||||
${HEADER_DIR}/internal/catch_streambuf.h
|
${HEADER_DIR}/internal/catch_streambuf.h
|
||||||
@@ -179,19 +174,19 @@ set(INTERNAL_HEADERS
|
|||||||
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h
|
${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h
|
||||||
${HEADER_DIR}/internal/catch_tag_alias_registry.h
|
${HEADER_DIR}/internal/catch_tag_alias_registry.h
|
||||||
${HEADER_DIR}/internal/catch_test_case_info.h
|
${HEADER_DIR}/internal/catch_test_case_info.h
|
||||||
${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp
|
${HEADER_DIR}/internal/catch_test_case_registry_impl.h
|
||||||
${HEADER_DIR}/internal/catch_test_case_tracker.hpp
|
${HEADER_DIR}/internal/catch_test_case_tracker.h
|
||||||
${HEADER_DIR}/internal/catch_test_registry.hpp
|
${HEADER_DIR}/internal/catch_test_registry.h
|
||||||
${HEADER_DIR}/internal/catch_test_spec.hpp
|
${HEADER_DIR}/internal/catch_test_spec.h
|
||||||
${HEADER_DIR}/internal/catch_test_spec_parser.hpp
|
${HEADER_DIR}/internal/catch_test_spec_parser.h
|
||||||
${HEADER_DIR}/internal/catch_text.h
|
${HEADER_DIR}/internal/catch_text.h
|
||||||
${HEADER_DIR}/internal/catch_timer.h
|
${HEADER_DIR}/internal/catch_timer.h
|
||||||
${HEADER_DIR}/internal/catch_tostring.h
|
${HEADER_DIR}/internal/catch_tostring.h
|
||||||
${HEADER_DIR}/internal/catch_totals.hpp
|
${HEADER_DIR}/internal/catch_totals.h
|
||||||
${HEADER_DIR}/internal/catch_version.h
|
${HEADER_DIR}/internal/catch_version.h
|
||||||
${HEADER_DIR}/internal/catch_wildcard_pattern.hpp
|
${HEADER_DIR}/internal/catch_wildcard_pattern.h
|
||||||
${HEADER_DIR}/internal/catch_windows_h_proxy.h
|
${HEADER_DIR}/internal/catch_windows_h_proxy.h
|
||||||
${HEADER_DIR}/internal/catch_xmlwriter.hpp
|
${HEADER_DIR}/internal/catch_xmlwriter.h
|
||||||
)
|
)
|
||||||
set(IMPL_SOURCES
|
set(IMPL_SOURCES
|
||||||
${HEADER_DIR}/internal/catch_approx.cpp
|
${HEADER_DIR}/internal/catch_approx.cpp
|
||||||
@@ -210,20 +205,29 @@ set(IMPL_SOURCES
|
|||||||
${HEADER_DIR}/internal/catch_errno_guard.cpp
|
${HEADER_DIR}/internal/catch_errno_guard.cpp
|
||||||
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
|
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
|
||||||
${HEADER_DIR}/internal/catch_fatal_condition.cpp
|
${HEADER_DIR}/internal/catch_fatal_condition.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_capture.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_config.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_exception.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_runner.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
|
||||||
${HEADER_DIR}/internal/catch_list.cpp
|
${HEADER_DIR}/internal/catch_list.cpp
|
||||||
${HEADER_DIR}/internal/catch_leak_detector.cpp
|
${HEADER_DIR}/internal/catch_leak_detector.cpp
|
||||||
${HEADER_DIR}/internal/catch_matchers.cpp
|
${HEADER_DIR}/internal/catch_matchers.cpp
|
||||||
${HEADER_DIR}/internal/catch_matchers_string.cpp
|
${HEADER_DIR}/internal/catch_matchers_string.cpp
|
||||||
${HEADER_DIR}/internal/catch_message.cpp
|
${HEADER_DIR}/internal/catch_message.cpp
|
||||||
${HEADER_DIR}/internal/catch_notimplemented_exception.cpp
|
|
||||||
${HEADER_DIR}/internal/catch_registry_hub.cpp
|
${HEADER_DIR}/internal/catch_registry_hub.cpp
|
||||||
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
|
${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_random_number_generator.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_reporter_registry.cpp
|
||||||
${HEADER_DIR}/internal/catch_result_type.cpp
|
${HEADER_DIR}/internal/catch_result_type.cpp
|
||||||
${HEADER_DIR}/internal/catch_run_context.cpp
|
${HEADER_DIR}/internal/catch_run_context.cpp
|
||||||
${HEADER_DIR}/internal/catch_section.cpp
|
${HEADER_DIR}/internal/catch_section.cpp
|
||||||
${HEADER_DIR}/internal/catch_section_info.cpp
|
${HEADER_DIR}/internal/catch_section_info.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_session.cpp
|
||||||
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
|
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
|
||||||
${HEADER_DIR}/internal/catch_stream.cpp
|
${HEADER_DIR}/internal/catch_stream.cpp
|
||||||
|
${HEADER_DIR}/internal/catch_streambuf.cpp
|
||||||
${HEADER_DIR}/internal/catch_stringref.cpp
|
${HEADER_DIR}/internal/catch_stringref.cpp
|
||||||
${HEADER_DIR}/internal/catch_string_manip.cpp
|
${HEADER_DIR}/internal/catch_string_manip.cpp
|
||||||
${HEADER_DIR}/internal/catch_tag_alias.cpp
|
${HEADER_DIR}/internal/catch_tag_alias.cpp
|
||||||
@@ -272,37 +276,29 @@ set(HEADERS
|
|||||||
${REPORTER_HEADERS}
|
${REPORTER_HEADERS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
set(BENCH_SOURCES
|
|
||||||
${BENCHMARK_DIR}/BenchMain.cpp
|
|
||||||
${BENCHMARK_DIR}/StringificationBench.cpp
|
|
||||||
)
|
|
||||||
CheckFileList(BENCH_SOURCES ${BENCHMARK_DIR})
|
|
||||||
|
|
||||||
# Provide some groupings for IDEs
|
# Provide some groupings for IDEs
|
||||||
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
|
||||||
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
|
||||||
SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES})
|
|
||||||
|
|
||||||
# configure the executable
|
# configure the executable
|
||||||
include_directories(${HEADER_DIR})
|
include_directories(${HEADER_DIR})
|
||||||
|
|
||||||
add_definitions( -DCATCH_CONFIG_FULL_PROJECT )
|
|
||||||
|
|
||||||
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
# Projects consuming Catch via ExternalProject_Add might want to use install step
|
||||||
# without building all of our selftests.
|
# without building all of our selftests.
|
||||||
if (NOT NO_SELFTEST)
|
if (NOT NO_SELFTEST)
|
||||||
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
|
add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
|
||||||
add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${HEADERS})
|
|
||||||
|
|
||||||
# Add desired warnings
|
# Add desired warnings
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
|
||||||
target_compile_options( SelfTest PRIVATE -Wall -Wextra )
|
target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code )
|
||||||
target_compile_options( Benchmark PRIVATE -Wall -Wextra )
|
endif()
|
||||||
|
# Clang specific warning go here
|
||||||
|
if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||||
|
# Actually keep these
|
||||||
|
target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
|
||||||
endif()
|
endif()
|
||||||
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
|
||||||
target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX )
|
target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX /w44061 /w44062 )
|
||||||
target_compile_options( Benchmark PRIVATE /W4 )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
@@ -316,7 +312,24 @@ if (NOT NO_SELFTEST)
|
|||||||
add_test(NAME ListTags COMMAND SelfTest --list-tags)
|
add_test(NAME ListTags COMMAND SelfTest --list-tags)
|
||||||
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
|
||||||
|
|
||||||
|
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
|
||||||
|
add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
|
||||||
|
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
|
||||||
endif() # !NO_SELFTEST
|
endif() # !NO_SELFTEST
|
||||||
|
|
||||||
|
|
||||||
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
install(DIRECTORY "single_include/" DESTINATION "include/catch")
|
||||||
|
|
||||||
|
## Provide some pkg-config integration
|
||||||
|
# Don't bother on Windows
|
||||||
|
if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
|
||||||
|
|
||||||
|
set(PKGCONFIG_INSTALL_DIR
|
||||||
|
"${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
|
||||||
|
CACHE PATH "Path where catch.pc is installed"
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/catch.pc.in ${CMAKE_CURRENT_BINARY_DIR}/catch.pc @ONLY)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR})
|
||||||
|
|
||||||
|
endif()
|
||||||
|
22
README.md
22
README.md
@@ -1,17 +1,23 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||

|

|
||||||
|
|
||||||
[](https://github.com/philsquared/catch/releases)
|
[](https://github.com/catchorg/catch2/releases)
|
||||||
[](https://travis-ci.org/philsquared/Catch?branch=catch2)
|
[](https://travis-ci.org/philsquared/Catch)
|
||||||
[](https://ci.appveyor.com/project/philsquared/catch/branch/catch2)
|
[](https://ci.appveyor.com/project/philsquared/catch)
|
||||||
|
|
||||||
<a href="https://github.com/philsquared/Catch/releases/download/v2.0.0-develop.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
<a href="https://github.com/catchorg/Catch2/releases/download/v2.0.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
|
||||||
|
|
||||||
|
## Catch2 is released!
|
||||||
|
|
||||||
|
If you've been using an earlier version of Catch, please see the
|
||||||
|
Breaking Changes section of [the release notes](https://github.com/catchorg/Catch2/releases/tag/v2.0.1)
|
||||||
|
before moving to Catch2.
|
||||||
|
|
||||||
## What's the Catch?
|
## What's the Catch?
|
||||||
|
|
||||||
Catch stands for C++ Automated Test Cases in Headers and is a
|
Catch2 stands for C++ Automated Test Cases in a Header and is a
|
||||||
multi-paradigm test framework for C++. which also supports Objective-C
|
multi-paradigm test framework for C++. which also supports Objective-C
|
||||||
and, maybe, C.
|
(and maybe C).
|
||||||
It is primarily distributed as a single header file, although certain
|
It is primarily distributed as a single header file, although certain
|
||||||
extensions may require additional headers.
|
extensions may require additional headers.
|
||||||
|
|
||||||
@@ -23,6 +29,6 @@ This documentation comprises these three parts:
|
|||||||
* [Reference section](docs/Readme.md#top) - all the details
|
* [Reference section](docs/Readme.md#top) - all the details
|
||||||
|
|
||||||
## More
|
## More
|
||||||
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues)
|
* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
|
||||||
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
|
* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
|
||||||
* See [who else is using Catch](docs/opensource-users.md#top)
|
* See [who else is using Catch2](docs/opensource-users.md#top)
|
||||||
|
9
catch.pc.in
Normal file
9
catch.pc.in
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
|
||||||
|
Name: Catch
|
||||||
|
Description: Testing library for C++
|
||||||
|
Requires:
|
||||||
|
Version: @CATCH_VERSION_NUMBER@
|
||||||
|
Libs:
|
||||||
|
Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@/include
|
@@ -4,7 +4,7 @@ from conans import ConanFile
|
|||||||
|
|
||||||
class CatchConan(ConanFile):
|
class CatchConan(ConanFile):
|
||||||
name = "Catch"
|
name = "Catch"
|
||||||
version = "2.0.0-develop.3"
|
version = "2.0.1"
|
||||||
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
|
||||||
author = "philsquared"
|
author = "philsquared"
|
||||||
generators = "cmake"
|
generators = "cmake"
|
||||||
@@ -14,3 +14,6 @@ class CatchConan(ConanFile):
|
|||||||
|
|
||||||
def package(self):
|
def package(self):
|
||||||
self.copy(pattern="catch.hpp", src="single_include", dst="include")
|
self.copy(pattern="catch.hpp", src="single_include", dst="include")
|
||||||
|
|
||||||
|
def package_id(self):
|
||||||
|
self.info.header_only()
|
||||||
|
@@ -36,6 +36,8 @@
|
|||||||
# -- adds fixture class name to the test name #
|
# -- adds fixture class name to the test name #
|
||||||
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
||||||
# -- adds cmake target name to the test name #
|
# -- adds cmake target name to the test name #
|
||||||
|
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
|
||||||
|
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
|
||||||
# #
|
# #
|
||||||
#==================================================================================================#
|
#==================================================================================================#
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OF
|
|||||||
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
||||||
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
||||||
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
||||||
|
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
|
||||||
|
|
||||||
function(PrintDebugMessage)
|
function(PrintDebugMessage)
|
||||||
if(PARSE_CATCH_TESTS_VERBOSE)
|
if(PARSE_CATCH_TESTS_VERBOSE)
|
||||||
@@ -85,6 +88,15 @@ function(ParseFile SourceFile TestTarget)
|
|||||||
# Find definition of test names
|
# Find definition of test names
|
||||||
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
||||||
|
|
||||||
|
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
|
||||||
|
PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
|
||||||
|
set_property(
|
||||||
|
DIRECTORY
|
||||||
|
APPEND
|
||||||
|
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
foreach(TestName ${Tests})
|
foreach(TestName ${Tests})
|
||||||
# Strip newlines
|
# Strip newlines
|
||||||
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Reference
|
# Reference
|
||||||
|
|
||||||
To get the most out of Catch, start with the [tutorial](tutorial.md#top).
|
To get the most out of Catch2, start with the [tutorial](tutorial.md#top).
|
||||||
Once you're up and running consider the following reference material.
|
Once you're up and running consider the following reference material.
|
||||||
|
|
||||||
Writing tests:
|
Writing tests:
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Assertion Macros
|
# Assertion Macros
|
||||||
|
|
||||||
**Contents**
|
**Contents**<br>
|
||||||
[Natural Expressions](#natural-expressions)
|
[Natural Expressions](#natural-expressions)<br>
|
||||||
[Exceptions](#exceptions)
|
[Exceptions](#exceptions)<br>
|
||||||
[Matcher expressions](#matcher-expressions)
|
[Matcher expressions](#matcher-expressions)<br>
|
||||||
[Thread Safety](#thread-safety)
|
[Thread Safety](#thread-safety)<br>
|
||||||
|
|
||||||
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
|
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ This way `Approx` is constructed with reasonable defaults, covering most simple
|
|||||||
|
|
||||||
* __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`.
|
* __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`.
|
||||||
* __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`.
|
* __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`.
|
||||||
* __scale__ - scale serves to adjust the base for comparison used by epsilon, can be used when By default set to `1.0`.
|
* __scale__ - scale serves to adjust the epsilon's multiplicator. By default set to `0.0`.
|
||||||
|
|
||||||
#### epsilon example
|
#### epsilon example
|
||||||
```cpp
|
```cpp
|
||||||
@@ -84,7 +84,12 @@ Approx target = Approx(100).margin(5);
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### scale
|
#### scale
|
||||||
Scale can be useful if the computation leading to the result worked on different scale, than is used by the results (and thus expected errors are on a different scale than would be expected based on the results alone).
|
Scale can be useful if the computation leading to the result worked
|
||||||
|
on different scale than is used by the results. Since allowed difference
|
||||||
|
between Approx's value and compared value is based primarily on Approx's value
|
||||||
|
(the allowed difference is computed as
|
||||||
|
`(Approx::scale + Approx::value) * epsilon`), the resulting comparison could
|
||||||
|
need rescaling to be correct.
|
||||||
|
|
||||||
|
|
||||||
## Exceptions
|
## Exceptions
|
||||||
|
@@ -16,7 +16,7 @@ The XML Reporter writes in an XML format that is specific to Catch.
|
|||||||
|
|
||||||
The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
|
The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
|
||||||
|
|
||||||
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course.
|
The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course.
|
||||||
|
|
||||||
### JUnit Reporter
|
### JUnit Reporter
|
||||||
```-r junit```
|
```-r junit```
|
||||||
|
@@ -1,29 +1,29 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Command line
|
# Command line
|
||||||
|
|
||||||
**Contents**
|
**Contents**<br>
|
||||||
[Specifying which tests to run](#specifying-which-tests-to-run)
|
[Specifying which tests to run](#specifying-which-tests-to-run)<br>
|
||||||
[Choosing a reporter to use](#choosing-a-reporter-to-use)
|
[Choosing a reporter to use](#choosing-a-reporter-to-use)<br>
|
||||||
[Breaking into the debugger](#breaking-into-the-debugger)
|
[Breaking into the debugger](#breaking-into-the-debugger)<br>
|
||||||
[Showing results for successful tests](#showing-results-for-successful-tests)
|
[Showing results for successful tests](#showing-results-for-successful-tests)<br>
|
||||||
[Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures)
|
[Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures)<br>
|
||||||
[Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters)
|
[Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters)<br>
|
||||||
[Sending output to a file](#sending-output-to-a-file)
|
[Sending output to a file](#sending-output-to-a-file)<br>
|
||||||
[Naming a test run](#naming-a-test-run)
|
[Naming a test run](#naming-a-test-run)<br>
|
||||||
[Eliding assertions expected to throw](#eliding-assertions-expected-to-throw)
|
[Eliding assertions expected to throw](#eliding-assertions-expected-to-throw)<br>
|
||||||
[Make whitespace visible](#make-whitespace-visible)
|
[Make whitespace visible](#make-whitespace-visible)<br>
|
||||||
[Warnings](#warnings)
|
[Warnings](#warnings)<br>
|
||||||
[Reporting timings](#reporting-timings)
|
[Reporting timings](#reporting-timings)<br>
|
||||||
[Load test names to run from a file](#load-test-names-to-run-from-a-file)
|
[Load test names to run from a file](#load-test-names-to-run-from-a-file)<br>
|
||||||
[Just test names](#just-test-names)
|
[Just test names](#just-test-names)<br>
|
||||||
[Specify the order test cases are run](#specify-the-order-test-cases-are-run)
|
[Specify the order test cases are run](#specify-the-order-test-cases-are-run)<br>
|
||||||
[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator)
|
[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator)<br>
|
||||||
[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard)
|
[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard)<br>
|
||||||
[Wait for key before continuing](#wait-for-key-before-continuing)
|
[Wait for key before continuing](#wait-for-key-before-continuing)<br>
|
||||||
[Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for)
|
[Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for)<br>
|
||||||
[Usage](#usage)
|
[Usage](#usage)<br>
|
||||||
[Specify the section to run](#specify-the-section-to-run)
|
[Specify the section to run](#specify-the-section-to-run)<br>
|
||||||
[Filenames as tags](#filenames-as-tags)
|
[Filenames as tags](#filenames-as-tags)<br>
|
||||||
|
|
||||||
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
|
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
|
||||||
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
|
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Compile-time configuration
|
# Compile-time configuration
|
||||||
|
|
||||||
**Contents**
|
**Contents**<br>
|
||||||
[main()/ implementation](#main-implementation)
|
[main()/ implementation](#main-implementation)<br>
|
||||||
[Prefixing Catch macros](#prefixing-catch-macros)
|
[Prefixing Catch macros](#prefixing-catch-macros)<br>
|
||||||
[Terminal colour](#terminal-colour)
|
[Terminal colour](#terminal-colour)<br>
|
||||||
[Console width](#console-width)
|
[Console width](#console-width)<br>
|
||||||
[stdout](#stdout)
|
[stdout](#stdout)<br>
|
||||||
[Other toggles](#other-toggles)
|
[Other toggles](#other-toggles)<br>
|
||||||
[Windows header clutter](#windows-header-clutter)
|
[Windows header clutter](#windows-header-clutter)<br>
|
||||||
|
[Enabling stringification](#enabling-stringification)<br>
|
||||||
|
|
||||||
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matcher
|
|||||||
_Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._
|
_Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._
|
||||||
|
|
||||||
### `CATCH_CONFIG_DISABLE_STRINGIFICATION`
|
### `CATCH_CONFIG_DISABLE_STRINGIFICATION`
|
||||||
This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#Visual Studio 2017 -- raw string literal in assert fails to compile)
|
This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#visual-studio-2017----raw-string-literal-in-assert-fails-to-compile).
|
||||||
|
|
||||||
### `CATCH_CONFIG_DISABLE`
|
### `CATCH_CONFIG_DISABLE`
|
||||||
This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files.
|
This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files.
|
||||||
@@ -121,6 +122,17 @@ On Windows Catch includes `windows.h`. To minimize global namespace clutter in t
|
|||||||
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
|
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
|
||||||
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
|
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
|
||||||
|
|
||||||
|
|
||||||
|
## Enabling stringification
|
||||||
|
|
||||||
|
By default, Catch does not stringify some types from the standard library. This is done to avoid dragging in various standard library headers by default. However, Catch does contain these and can be configured to provide them, using these macros:
|
||||||
|
|
||||||
|
CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER // Provide StringMaker specialization for std::pair
|
||||||
|
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple
|
||||||
|
CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
|
||||||
|
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Open Source projects using Catch
|
# Open Source projects using Catch
|
||||||
|
|
||||||
Catch is great for open source. With it's [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
|
Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
|
||||||
it's easy to just drop the header into your project and start writing tests - what's not to like?
|
it's easy to just drop the header into your project and start writing tests - what's not to like?
|
||||||
|
|
||||||
As a result Catch is now being used in many Open Source projects, including some quite well known ones.
|
As a result Catch is now being used in many Open Source projects, including some quite well known ones.
|
||||||
|
@@ -43,30 +43,16 @@ int main( int argc, char* argv[] )
|
|||||||
// writing to session.configData() here sets defaults
|
// writing to session.configData() here sets defaults
|
||||||
// this is the preferred way to set them
|
// this is the preferred way to set them
|
||||||
|
|
||||||
// Verify that all tests, aliases, etc registered properly
|
|
||||||
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
|
|
||||||
if ( !exceptions.empty() ) {
|
|
||||||
// iterate over all exceptions and notify user
|
|
||||||
for ( const auto& ex_ptr : exceptions ) {
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(ex_ptr);
|
|
||||||
} catch (std::exception const& ex) {
|
|
||||||
Catch::cerr() << ex.what();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Indicate that an error occured before main
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int returnCode = session.applyCommandLine( argc, argv );
|
int returnCode = session.applyCommandLine( argc, argv );
|
||||||
if( returnCode != 0 ) // Indicates a command line error
|
if( returnCode != 0 ) // Indicates a command line error
|
||||||
return returnCode;
|
return returnCode;
|
||||||
|
|
||||||
// writing to session.configData() or session.Config() here
|
// writing to session.configData() or session.Config() here
|
||||||
// overrides command line args
|
// overrides command line args
|
||||||
// only do this if you know you need to
|
// only do this if you know you need to
|
||||||
|
|
||||||
int numFailed = session.run();
|
int numFailed = session.run();
|
||||||
|
|
||||||
// numFailed is clamped to 255 as some unices only use the lower 8 bits.
|
// numFailed is clamped to 255 as some unices only use the lower 8 bits.
|
||||||
// This clamping has already been applied, so just return it here
|
// This clamping has already been applied, so just return it here
|
||||||
// You can also do any post run clean-up here
|
// You can also do any post run clean-up here
|
||||||
@@ -80,7 +66,44 @@ To take full control of the config simply omit the call to ```applyCommandLine()
|
|||||||
|
|
||||||
## Adding your own command line options
|
## Adding your own command line options
|
||||||
|
|
||||||
Catch embeds a powerful command line parser which you can also use to parse your own options out. This capability is still in active development but will be documented here when it is ready.
|
Catch embeds a powerful command line parser called [Clara](https://github.com/philsquared/Clara).
|
||||||
|
As of Catch2 (and Clara 1.0) Clara allows you to write _composable_ option and argument parsers,
|
||||||
|
so extending Catch's own command line options is now easy.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#define CATCH_CONFIG_RUNNER
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
int main( int argc, char* argv[] )
|
||||||
|
{
|
||||||
|
Catch::Session session; // There must be exactly one instance
|
||||||
|
|
||||||
|
int height = 0; // Some user variable you want to be able to set
|
||||||
|
|
||||||
|
// Build a new parser on top of Catch's
|
||||||
|
auto cli
|
||||||
|
= session.cli() // Get Catch's composite command line parser
|
||||||
|
| Opt( height, "height" ) // bind variable to a new option, with a hint string
|
||||||
|
["-g"]["--height"] // the option names it will respond to
|
||||||
|
("how high?"); // description string for the help output
|
||||||
|
|
||||||
|
// Now pass the new composite back to Catch so it uses that
|
||||||
|
session.cli( cli );
|
||||||
|
|
||||||
|
// Let Catch (using Clara) parse the command line
|
||||||
|
int returnCode = session.applyCommandLine( argc, argv );
|
||||||
|
if( returnCode != 0 ) // Indicates a command line error
|
||||||
|
return returnCode;
|
||||||
|
|
||||||
|
// if set on the command line then 'height' is now set at this point
|
||||||
|
if( height > 0 )
|
||||||
|
std::cout << "height: " << height << std::endl;
|
||||||
|
|
||||||
|
return session.run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Clara documentation](https://github.com/philsquared/Clara/blob/master/README.md) for more details.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# 2.0.0 (in progress)
|
# 2.0.1
|
||||||
|
|
||||||
## Breaking changes
|
## Breaking changes
|
||||||
* Removed C++98 support
|
* Removed C++98 support
|
||||||
@@ -17,6 +17,19 @@
|
|||||||
* `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type.
|
* `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type.
|
||||||
* `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions
|
* `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions
|
||||||
* This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section.
|
* This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section.
|
||||||
|
* Removed deprecated matcher utility functions `Not`, `AllOf` and `AnyOf`.
|
||||||
|
* They are superseded by operators `!`, `&&` and `||`, which are natural and do not have limited arity
|
||||||
|
* Removed support for non-const comparison operators
|
||||||
|
* Non-const comparison operators are an abomination that should not exist
|
||||||
|
* They were breaking support for comparing function to function pointer
|
||||||
|
* `std::pair` and `std::tuple` are no longer stringified by default
|
||||||
|
* This is done to avoid dragging in `<tuple>` and `<utility>` headers in common path
|
||||||
|
* Their stringification can be enabled per-file via new configuration macros
|
||||||
|
* `Approx` is subtly different and hopefully behaves more as users would expect
|
||||||
|
* `Approx::scale` defaults to `0.0`
|
||||||
|
* `Approx::epsilon` no longer applies to the larger of the two compared values, but only to the `Approx`'s value
|
||||||
|
* `INFINITY == Approx(INFINITY)` returns true
|
||||||
|
|
||||||
|
|
||||||
## Improvements
|
## Improvements
|
||||||
* Reporters and Listeners can be defined in files different from the main file
|
* Reporters and Listeners can be defined in files different from the main file
|
||||||
@@ -36,13 +49,32 @@
|
|||||||
* All parts of matchers can be removed from a TU by defining `CATCH_CONFIG_DISABLE_MATCHERS`
|
* All parts of matchers can be removed from a TU by defining `CATCH_CONFIG_DISABLE_MATCHERS`
|
||||||
* This can be used to somewhat speed up compilation times
|
* This can be used to somewhat speed up compilation times
|
||||||
* An experimental implementation of `CATCH_CONFIG_DISABLE` has been added
|
* An experimental implementation of `CATCH_CONFIG_DISABLE` has been added
|
||||||
* Speeds up compilation by removing away Catch tests
|
* Inspired by Doctest's `DOCTEST_CONFIG_DISABLE`
|
||||||
* Currently removes all assertions and prevents `TEST_CASE` registrations
|
|
||||||
* Useful for implementing tests in source files
|
* Useful for implementing tests in source files
|
||||||
* ie for functions in anonymous namespaces
|
* ie for functions in anonymous namespaces
|
||||||
* Inspired by Doctest's `DOCTEST_CONFIG_DISABLE`
|
* Removes all assertions
|
||||||
|
* Prevents `TEST_CASE` registrations
|
||||||
|
* Exception translators are not registered
|
||||||
|
* Reporters are not registered
|
||||||
|
* Listeners are not registered
|
||||||
|
* Reporters/Listeners are now notified of fatal errors
|
||||||
|
* This means specific signals or structured exceptions
|
||||||
|
* The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility
|
||||||
|
* Stringification of `std::chrono::duration` and `std::chrono::time_point` is now supported
|
||||||
|
* Needs to be enabled by a per-file compile time configuration option
|
||||||
|
* Add `pkg-config` support to CMake install command
|
||||||
|
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
* Don't use console colour if running in XCode
|
||||||
|
* Explicit constructor in reporter base class
|
||||||
|
* Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings
|
||||||
|
* Compilation for Universal Windows Platform (UWP) is supported
|
||||||
|
* SEH handling and colorized output are disabled when compiling for UWP
|
||||||
|
* Implemented a workaround for `std::uncaught_exception` issues in libcxxrt
|
||||||
|
* These issues caused incorrect section traversals
|
||||||
|
* The workaround is only partial, user's test can still trigger the issue by using `throw;` to rethrow an exception
|
||||||
|
* Suppressed C4061 warning under MSVC
|
||||||
|
|
||||||
|
|
||||||
## Internal changes
|
## Internal changes
|
||||||
@@ -53,7 +85,6 @@
|
|||||||
* New library (TextFlow) is used for formatting text to output
|
* New library (TextFlow) is used for formatting text to output
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Older versions
|
# Older versions
|
||||||
|
|
||||||
## 1.9.x
|
## 1.9.x
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Why do my tests take so long to compile?
|
# Why do my tests take so long to compile?
|
||||||
|
|
||||||
**Contents**
|
**Contents**<br>
|
||||||
[Short answer](#short-answer)
|
[Short answer](#short-answer)<br>
|
||||||
[Long answer](#long-answer)
|
[Long answer](#long-answer)<br>
|
||||||
[Practical example](#practical-example)
|
[Practical example](#practical-example)<br>
|
||||||
[Other possible solutions](#other-possible-solutions)
|
[Other possible solutions](#other-possible-solutions)<br>
|
||||||
|
|
||||||
Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that?
|
Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that?
|
||||||
|
|
||||||
|
@@ -39,13 +39,13 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
|
|||||||
|
|
||||||
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
|
* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
|
||||||
|
|
||||||
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests.
|
* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
|
||||||
|
|
||||||
* `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes.
|
* `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes.
|
||||||
|
|
||||||
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
|
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
|
||||||
|
|
||||||
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
|
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`.
|
||||||
|
|
||||||
* `[@<alias>]` - tag aliases all begin with `@` (see below).
|
* `[@<alias>]` - tag aliases all begin with `@` (see below).
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
|
|||||||
|
|
||||||
## Tag aliases
|
## Tag aliases
|
||||||
|
|
||||||
Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form:
|
Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. This can be done, in code, using the following form:
|
||||||
|
|
||||||
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
|
CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
|
||||||
|
|
||||||
|
@@ -1,27 +1,27 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Tutorial
|
# Tutorial
|
||||||
|
|
||||||
**Contents**
|
**Contents**<br>
|
||||||
[Getting Catch](#getting-catch)
|
[Getting Catch2](#getting-catch2)<br>
|
||||||
[Where to put it?](#where-to-put-it)
|
[Where to put it?](#where-to-put-it)<br>
|
||||||
[Writing tests](#writing-tests)
|
[Writing tests](#writing-tests)<br>
|
||||||
[Test cases and sections](#test-cases-and-sections)
|
[Test cases and sections](#test-cases-and-sections)<br>
|
||||||
[BDD-Style](#bdd-style)
|
[BDD-Style](#bdd-style)<br>
|
||||||
[Scaling up](#scaling-up)
|
[Scaling up](#scaling-up)<br>
|
||||||
[Next steps](#next-steps)
|
[Next steps](#next-steps)<br>
|
||||||
|
|
||||||
## Getting Catch
|
## Getting Catch2
|
||||||
|
|
||||||
The simplest way to get Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
|
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/CatchOrg/Catch2/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
|
||||||
|
|
||||||
The full source for Catch, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
|
The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
|
||||||
|
|
||||||
|
|
||||||
## Where to put it?
|
## Where to put it?
|
||||||
|
|
||||||
Catch is header only. All you need to do is drop the file(s) somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html).
|
Catch2 is header only. All you need to do is drop the file somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html).
|
||||||
|
|
||||||
The rest of this tutorial will assume that the Catch single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
|
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
|
||||||
|
|
||||||
## Writing tests
|
## Writing tests
|
||||||
|
|
||||||
|
@@ -20,6 +20,9 @@
|
|||||||
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
|
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
|
||||||
# define CATCH_IMPL
|
# define CATCH_IMPL
|
||||||
# define CATCH_CONFIG_EXTERNAL_INTERFACES
|
# define CATCH_CONFIG_EXTERNAL_INTERFACES
|
||||||
|
# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
|
||||||
|
# undef CATCH_CONFIG_DISABLE_MATCHERS
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "internal/catch_platform.h"
|
#include "internal/catch_platform.h"
|
||||||
@@ -32,14 +35,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "internal/catch_tag_alias_autoregistrar.h"
|
#include "internal/catch_tag_alias_autoregistrar.h"
|
||||||
#include "internal/catch_test_registry.hpp"
|
#include "internal/catch_test_registry.h"
|
||||||
#include "internal/catch_capture.hpp"
|
#include "internal/catch_capture.hpp"
|
||||||
#include "internal/catch_section.h"
|
#include "internal/catch_section.h"
|
||||||
#include "internal/catch_benchmark.h"
|
#include "internal/catch_benchmark.h"
|
||||||
#include "internal/catch_interfaces_exception.h"
|
#include "internal/catch_interfaces_exception.h"
|
||||||
#include "internal/catch_approx.hpp"
|
#include "internal/catch_approx.h"
|
||||||
#include "internal/catch_compiler_capabilities.h"
|
#include "internal/catch_compiler_capabilities.h"
|
||||||
#include "internal/catch_interfaces_tag_alias_registry.h"
|
#include "internal/catch_string_manip.h"
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
|
||||||
#include "internal/catch_capture_matchers.h"
|
#include "internal/catch_capture_matchers.h"
|
||||||
|
@@ -1,264 +0,0 @@
|
|||||||
/*
|
|
||||||
* Created by Phil on 31/10/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_CATCH_RUNNER_HPP_INCLUDED
|
|
||||||
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include "internal/catch_commandline.hpp"
|
|
||||||
#include "internal/catch_console_colour.hpp"
|
|
||||||
#include "internal/catch_enforce.h"
|
|
||||||
#include "internal/catch_list.h"
|
|
||||||
#include "internal/catch_run_context.hpp"
|
|
||||||
#include "internal/catch_stream.h"
|
|
||||||
#include "internal/catch_test_spec.hpp"
|
|
||||||
#include "internal/catch_version.h"
|
|
||||||
#include "internal/catch_interfaces_reporter.h"
|
|
||||||
#include "internal/catch_startup_exception_registry.h"
|
|
||||||
#include "internal/catch_text.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <limits>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) {
|
|
||||||
auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config );
|
|
||||||
CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" );
|
|
||||||
|
|
||||||
return reporter;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
|
|
||||||
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IStreamingReporterPtr makeReporter( std::shared_ptr<Config> const& config ) {
|
|
||||||
auto const& reporterNames = config->getReporterNames();
|
|
||||||
if( reporterNames.empty() )
|
|
||||||
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config );
|
|
||||||
|
|
||||||
IStreamingReporterPtr reporter;
|
|
||||||
for( auto const& name : reporterNames )
|
|
||||||
addReporter( reporter, createReporter( name, config ) );
|
|
||||||
return reporter;
|
|
||||||
}
|
|
||||||
void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) {
|
|
||||||
auto const& listeners = getRegistryHub().getReporterRegistry().getListeners();
|
|
||||||
for( auto const& listener : listeners )
|
|
||||||
addReporter(reporters, listener->create( ReporterConfig( config ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Totals runTests( std::shared_ptr<Config> const& config ) {
|
|
||||||
|
|
||||||
IStreamingReporterPtr reporter = makeReporter( config );
|
|
||||||
addListeners( reporter, config );
|
|
||||||
|
|
||||||
RunContext context( config, std::move( reporter ) );
|
|
||||||
|
|
||||||
Totals totals;
|
|
||||||
|
|
||||||
context.testGroupStarting( config->name(), 1, 1 );
|
|
||||||
|
|
||||||
TestSpec testSpec = config->testSpec();
|
|
||||||
if( !testSpec.hasFilters() )
|
|
||||||
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
|
|
||||||
|
|
||||||
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *config );
|
|
||||||
for( auto const& testCase : allTestCases ) {
|
|
||||||
if( !context.aborting() && matchTest( testCase, testSpec, *config ) )
|
|
||||||
totals += context.runTest( testCase );
|
|
||||||
else
|
|
||||||
context.reporter().skipTest( testCase );
|
|
||||||
}
|
|
||||||
|
|
||||||
context.testGroupEnded( config->name(), totals, 1, 1 );
|
|
||||||
return totals;
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyFilenamesAsTags( IConfig const& config ) {
|
|
||||||
auto& tests = const_cast<std::vector<TestCase>&>( getAllTestCasesSorted( config ) );
|
|
||||||
for( auto& testCase : tests ) {
|
|
||||||
auto tags = testCase.tags;
|
|
||||||
|
|
||||||
std::string filename = testCase.lineInfo.file;
|
|
||||||
std::string::size_type lastSlash = filename.find_last_of( "\\/" );
|
|
||||||
if( lastSlash != std::string::npos )
|
|
||||||
filename = filename.substr( lastSlash+1 );
|
|
||||||
|
|
||||||
std::string::size_type lastDot = filename.find_last_of( '.' );
|
|
||||||
if( lastDot != std::string::npos )
|
|
||||||
filename = filename.substr( 0, lastDot );
|
|
||||||
|
|
||||||
tags.push_back( '#' + filename );
|
|
||||||
setTags( testCase, tags );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Session : NonCopyable {
|
|
||||||
static const int MaxExitCode;
|
|
||||||
public:
|
|
||||||
|
|
||||||
Session() {
|
|
||||||
static bool alreadyInstantiated = false;
|
|
||||||
if( alreadyInstantiated )
|
|
||||||
CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" );
|
|
||||||
alreadyInstantiated = true;
|
|
||||||
m_cli = makeCommandLineParser( m_configData );
|
|
||||||
}
|
|
||||||
~Session() override {
|
|
||||||
Catch::cleanUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void showHelp() const {
|
|
||||||
Catch::cout()
|
|
||||||
<< "\nCatch v" << libraryVersion() << "\n"
|
|
||||||
<< m_cli << std::endl
|
|
||||||
<< "For more detailed usage please see the project docs\n" << std::endl;
|
|
||||||
}
|
|
||||||
void libIdentify() {
|
|
||||||
Catch::cout()
|
|
||||||
<< std::left << std::setw(16) << "description: " << "A Catch test executable\n"
|
|
||||||
<< std::left << std::setw(16) << "category: " << "testframework\n"
|
|
||||||
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
|
|
||||||
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int applyCommandLine( int argc, char* argv[] ) {
|
|
||||||
auto result = m_cli.parse( clara::Args( argc, argv ) );
|
|
||||||
if( !result ) {
|
|
||||||
Catch::cerr()
|
|
||||||
<< Colour( Colour::Red )
|
|
||||||
<< "\nError(s) in input:\n"
|
|
||||||
<< Column( result.errorMessage() ).indent( 2 )
|
|
||||||
<< "\n\n";
|
|
||||||
Catch::cerr() << "Run with -? for usage\n" << std::endl;
|
|
||||||
return MaxExitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_configData.showHelp )
|
|
||||||
showHelp();
|
|
||||||
if( m_configData.libIdentify )
|
|
||||||
libIdentify();
|
|
||||||
m_config.reset();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void useConfigData( ConfigData const& configData ) {
|
|
||||||
m_configData = configData;
|
|
||||||
m_config.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
int run( int argc, char* argv[] ) {
|
|
||||||
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
|
|
||||||
if ( !exceptions.empty() ) {
|
|
||||||
Catch::cerr() << "Errors occured during startup!" << '\n';
|
|
||||||
// iterate over all exceptions and notify user
|
|
||||||
for ( const auto& ex_ptr : exceptions ) {
|
|
||||||
try {
|
|
||||||
std::rethrow_exception(ex_ptr);
|
|
||||||
} catch ( std::exception const& ex ) {
|
|
||||||
Catch::cerr() << ex.what() << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int returnCode = applyCommandLine( argc, argv );
|
|
||||||
if( returnCode == 0 )
|
|
||||||
returnCode = run();
|
|
||||||
return returnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(WIN32) && defined(UNICODE)
|
|
||||||
int run( int argc, wchar_t* const argv[] ) {
|
|
||||||
|
|
||||||
char **utf8Argv = new char *[ argc ];
|
|
||||||
|
|
||||||
for ( int i = 0; i < argc; ++i ) {
|
|
||||||
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
|
|
||||||
|
|
||||||
utf8Argv[ i ] = new char[ bufSize ];
|
|
||||||
|
|
||||||
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
int returnCode = run( argc, utf8Argv );
|
|
||||||
|
|
||||||
for ( int i = 0; i < argc; ++i )
|
|
||||||
delete [] utf8Argv[ i ];
|
|
||||||
|
|
||||||
delete [] utf8Argv;
|
|
||||||
|
|
||||||
return returnCode;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
int run() {
|
|
||||||
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
|
|
||||||
Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
|
|
||||||
static_cast<void>(std::getchar());
|
|
||||||
}
|
|
||||||
int exitCode = runInternal();
|
|
||||||
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
|
|
||||||
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
|
|
||||||
static_cast<void>(std::getchar());
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
clara::Parser const& cli() const {
|
|
||||||
return m_cli;
|
|
||||||
}
|
|
||||||
void cli( clara::Parser const& newParser ) {
|
|
||||||
m_cli = newParser;
|
|
||||||
}
|
|
||||||
ConfigData& configData() {
|
|
||||||
return m_configData;
|
|
||||||
}
|
|
||||||
Config& config() {
|
|
||||||
if( !m_config )
|
|
||||||
m_config = std::make_shared<Config>( m_configData );
|
|
||||||
return *m_config;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int runInternal() {
|
|
||||||
if( m_configData.showHelp || m_configData.libIdentify )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
config(); // Force config to be constructed
|
|
||||||
|
|
||||||
seedRng( *m_config );
|
|
||||||
|
|
||||||
if( m_configData.filenamesAsTags )
|
|
||||||
applyFilenamesAsTags( *m_config );
|
|
||||||
|
|
||||||
// Handle list request
|
|
||||||
if( Option<std::size_t> listed = list( config() ) )
|
|
||||||
return static_cast<int>( *listed );
|
|
||||||
|
|
||||||
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
|
|
||||||
}
|
|
||||||
catch( std::exception& ex ) {
|
|
||||||
Catch::cerr() << ex.what() << std::endl;
|
|
||||||
return MaxExitCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clara::Parser m_cli;
|
|
||||||
ConfigData m_configData;
|
|
||||||
std::shared_ptr<Config> m_config;
|
|
||||||
};
|
|
||||||
|
|
||||||
const int Session::MaxExitCode = 255;
|
|
||||||
|
|
||||||
} // end namespace Catch
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
|
|
522
include/external/clara.hpp
vendored
522
include/external/clara.hpp
vendored
@@ -1,14 +1,16 @@
|
|||||||
// v1.0
|
// v1.0-develop.2
|
||||||
// See https://github.com/philsquared/Clara
|
// See https://github.com/philsquared/Clara
|
||||||
|
|
||||||
#ifndef CATCH_CLARA_HPP_INCLUDED
|
#ifndef CATCH_CLARA_HPP_INCLUDED
|
||||||
#define CATCH_CLARA_HPP_INCLUDED
|
#define CATCH_CLARA_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
||||||
#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
|
#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
|
||||||
|
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
|
||||||
|
#endif
|
||||||
|
|
||||||
// ----------- #included from clara_textflow.hpp -----------
|
// ----------- #included from clara_textflow.hpp -----------
|
||||||
|
|
||||||
@@ -24,7 +26,6 @@
|
|||||||
#ifndef CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
|
#ifndef CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
|
||||||
#define CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
|
#define CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -135,7 +136,7 @@ namespace Catch { namespace clara { namespace TextFlow {
|
|||||||
|
|
||||||
auto operator *() const -> std::string {
|
auto operator *() const -> std::string {
|
||||||
assert( m_stringIndex < m_column.m_strings.size() );
|
assert( m_stringIndex < m_column.m_strings.size() );
|
||||||
assert( m_pos < m_end );
|
assert( m_pos <= m_end );
|
||||||
if( m_pos + m_column.m_width < m_end )
|
if( m_pos + m_column.m_width < m_end )
|
||||||
return addIndentAndSuffix(line().substr(m_pos, m_len));
|
return addIndentAndSuffix(line().substr(m_pos, m_len));
|
||||||
else
|
else
|
||||||
@@ -350,9 +351,8 @@ namespace Catch { namespace clara { namespace TextFlow {
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
|
#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
|
||||||
#define CLARA_PLATFORM_WINDOWS
|
#define CATCH_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Catch { namespace clara {
|
namespace Catch { namespace clara {
|
||||||
@@ -360,15 +360,15 @@ namespace detail {
|
|||||||
|
|
||||||
// Traits for extracting arg and return type of lambdas (for single argument lambdas)
|
// Traits for extracting arg and return type of lambdas (for single argument lambdas)
|
||||||
template<typename L>
|
template<typename L>
|
||||||
struct UnaryLambdaTraits : UnaryLambdaTraits<decltype(&L::operator())> {};
|
struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
|
||||||
|
|
||||||
template<typename ClassT, typename ReturnT, typename... Args>
|
template<typename ClassT, typename ReturnT, typename... Args>
|
||||||
struct UnaryLambdaTraits<ReturnT(ClassT::*)(Args...) const> {
|
struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
|
||||||
static const bool isValid = false;
|
static const bool isValid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ClassT, typename ReturnT, typename ArgT>
|
template<typename ClassT, typename ReturnT, typename ArgT>
|
||||||
struct UnaryLambdaTraits<ReturnT(ClassT::*)(ArgT) const> {
|
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
|
||||||
static const bool isValid = true;
|
static const bool isValid = true;
|
||||||
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
|
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;;
|
||||||
using ReturnType = ReturnT;
|
using ReturnType = ReturnT;
|
||||||
@@ -383,13 +383,13 @@ namespace detail {
|
|||||||
std::vector<std::string> m_args;
|
std::vector<std::string> m_args;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Args(int argc, char *argv[]) {
|
Args( int argc, char *argv[] ) {
|
||||||
m_exeName = argv[0];
|
m_exeName = argv[0];
|
||||||
for (int i = 1; i < argc; ++i)
|
for( int i = 1; i < argc; ++i )
|
||||||
m_args.push_back(argv[i]);
|
m_args.push_back( argv[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
Args(std::initializer_list<std::string> args)
|
Args( std::initializer_list<std::string> args )
|
||||||
: m_exeName( *args.begin() ),
|
: m_exeName( *args.begin() ),
|
||||||
m_args( args.begin()+1, args.end() )
|
m_args( args.begin()+1, args.end() )
|
||||||
{}
|
{}
|
||||||
@@ -409,6 +409,14 @@ namespace detail {
|
|||||||
std::string token;
|
std::string token;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline auto isOptPrefix( char c ) -> bool {
|
||||||
|
return c == '-'
|
||||||
|
#ifdef CATCH_PLATFORM_WINDOWS
|
||||||
|
|| c == '/'
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
// Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
|
// Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
|
||||||
class TokenStream {
|
class TokenStream {
|
||||||
using Iterator = std::vector<std::string>::const_iterator;
|
using Iterator = std::vector<std::string>::const_iterator;
|
||||||
@@ -417,40 +425,40 @@ namespace detail {
|
|||||||
std::vector<Token> m_tokenBuffer;
|
std::vector<Token> m_tokenBuffer;
|
||||||
|
|
||||||
void loadBuffer() {
|
void loadBuffer() {
|
||||||
m_tokenBuffer.resize(0);
|
m_tokenBuffer.resize( 0 );
|
||||||
|
|
||||||
// Skip any empty strings
|
// Skip any empty strings
|
||||||
while (it != itEnd && it->empty())
|
while( it != itEnd && it->empty() )
|
||||||
++it;
|
++it;
|
||||||
|
|
||||||
if (it != itEnd) {
|
if( it != itEnd ) {
|
||||||
auto const &next = *it;
|
auto const &next = *it;
|
||||||
if (next[0] == '-' || next[0] == '/') {
|
if( isOptPrefix( next[0] ) ) {
|
||||||
auto delimiterPos = next.find_first_of(" :=");
|
auto delimiterPos = next.find_first_of( " :=" );
|
||||||
if (delimiterPos != std::string::npos) {
|
if( delimiterPos != std::string::npos ) {
|
||||||
m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)});
|
m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
|
||||||
m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)});
|
m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
|
||||||
} else {
|
} else {
|
||||||
if (next[1] != '-' && next.size() > 2) {
|
if( next[1] != '-' && next.size() > 2 ) {
|
||||||
std::string opt = "- ";
|
std::string opt = "- ";
|
||||||
for (size_t i = 1; i < next.size(); ++i) {
|
for( size_t i = 1; i < next.size(); ++i ) {
|
||||||
opt[1] = next[i];
|
opt[1] = next[i];
|
||||||
m_tokenBuffer.push_back({TokenType::Option, opt});
|
m_tokenBuffer.push_back( { TokenType::Option, opt } );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_tokenBuffer.push_back({TokenType::Option, next});
|
m_tokenBuffer.push_back( { TokenType::Option, next } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_tokenBuffer.push_back({TokenType::Argument, next});
|
m_tokenBuffer.push_back( { TokenType::Argument, next } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
|
explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
|
||||||
|
|
||||||
TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) {
|
TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
|
||||||
loadBuffer();
|
loadBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,20 +469,20 @@ namespace detail {
|
|||||||
auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
|
auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
|
||||||
|
|
||||||
auto operator*() const -> Token {
|
auto operator*() const -> Token {
|
||||||
assert(!m_tokenBuffer.empty());
|
assert( !m_tokenBuffer.empty() );
|
||||||
return m_tokenBuffer.front();
|
return m_tokenBuffer.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator->() const -> Token const * {
|
auto operator->() const -> Token const * {
|
||||||
assert(!m_tokenBuffer.empty());
|
assert( !m_tokenBuffer.empty() );
|
||||||
return &m_tokenBuffer.front();
|
return &m_tokenBuffer.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator++() -> TokenStream & {
|
auto operator++() -> TokenStream & {
|
||||||
if (m_tokenBuffer.size() >= 2) {
|
if( m_tokenBuffer.size() >= 2 ) {
|
||||||
m_tokenBuffer.erase(m_tokenBuffer.begin());
|
m_tokenBuffer.erase( m_tokenBuffer.begin() );
|
||||||
} else {
|
} else {
|
||||||
if (it != itEnd)
|
if( it != itEnd )
|
||||||
++it;
|
++it;
|
||||||
loadBuffer();
|
loadBuffer();
|
||||||
}
|
}
|
||||||
@@ -490,7 +498,7 @@ namespace detail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ResultBase(Type type) : m_type(type) {}
|
ResultBase( Type type ) : m_type( type ) {}
|
||||||
virtual ~ResultBase() = default;
|
virtual ~ResultBase() = default;
|
||||||
|
|
||||||
virtual void enforceOk() const = 0;
|
virtual void enforceOk() const = 0;
|
||||||
@@ -507,28 +515,28 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ResultValueBase(Type type) : ResultBase(type) {}
|
ResultValueBase( Type type ) : ResultBase( type ) {}
|
||||||
|
|
||||||
ResultValueBase(ResultValueBase const &other) : ResultBase(other) {
|
ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
|
||||||
if (m_type == ResultBase::Ok)
|
if( m_type == ResultBase::Ok )
|
||||||
new(&m_value) T(other.m_value);
|
new( &m_value ) T( other.m_value );
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultValueBase(Type, T const &value) : ResultBase(Ok) {
|
ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
|
||||||
new(&m_value) T(value);
|
new( &m_value ) T( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator=(ResultValueBase const &other) -> ResultValueBase & {
|
auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
|
||||||
if (m_type == ResultBase::Ok)
|
if( m_type == ResultBase::Ok )
|
||||||
m_value.~T();
|
m_value.~T();
|
||||||
ResultBase::operator=(other);
|
ResultBase::operator=(other);
|
||||||
if (m_type == ResultBase::Ok)
|
if( m_type == ResultBase::Ok )
|
||||||
new(&m_value) T(other.m_value);
|
new( &m_value ) T( other.m_value );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ResultValueBase() {
|
~ResultValueBase() {
|
||||||
if (m_type == Ok)
|
if( m_type == Ok )
|
||||||
m_value.~T();
|
m_value.~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,37 +555,31 @@ namespace detail {
|
|||||||
class BasicResult : public ResultValueBase<T> {
|
class BasicResult : public ResultValueBase<T> {
|
||||||
public:
|
public:
|
||||||
template<typename U>
|
template<typename U>
|
||||||
explicit BasicResult(BasicResult<U> const &other)
|
explicit BasicResult( BasicResult<U> const &other )
|
||||||
: ResultValueBase<T>(other.type()),
|
: ResultValueBase<T>( other.type() ),
|
||||||
m_errorMessage(other.errorMessage()) {
|
m_errorMessage( other.errorMessage() )
|
||||||
assert(type() != ResultBase::Ok);
|
{
|
||||||
|
assert( type() != ResultBase::Ok );
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto ok() -> BasicResult { return {ResultBase::Ok}; }
|
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; }
|
static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
|
||||||
|
static auto ok() -> BasicResult { return { ResultBase::Ok }; }
|
||||||
static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; }
|
static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
|
||||||
|
static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
|
||||||
static auto runtimeError(std::string const &message) -> BasicResult {
|
|
||||||
return {ResultBase::RuntimeError, message};
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const { return m_type == ResultBase::Ok; }
|
explicit operator bool() const { return m_type == ResultBase::Ok; }
|
||||||
|
|
||||||
auto type() const -> ResultBase::Type { return m_type; }
|
auto type() const -> ResultBase::Type { return m_type; }
|
||||||
|
|
||||||
auto errorMessage() const -> std::string { return m_errorMessage; }
|
auto errorMessage() const -> std::string { return m_errorMessage; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void enforceOk() const {
|
virtual void enforceOk() const {
|
||||||
// !TBD: If no exceptions, std::terminate here or something
|
// !TBD: If no exceptions, std::terminate here or something
|
||||||
switch (m_type) {
|
switch( m_type ) {
|
||||||
case ResultBase::LogicError:
|
case ResultBase::LogicError:
|
||||||
throw std::logic_error(m_errorMessage);
|
throw std::logic_error( m_errorMessage );
|
||||||
case ResultBase::RuntimeError:
|
case ResultBase::RuntimeError:
|
||||||
throw std::runtime_error(m_errorMessage);
|
throw std::runtime_error( m_errorMessage );
|
||||||
case ResultBase::Ok:
|
case ResultBase::Ok:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -585,10 +587,11 @@ namespace detail {
|
|||||||
|
|
||||||
std::string m_errorMessage; // Only populated if resultType is an error
|
std::string m_errorMessage; // Only populated if resultType is an error
|
||||||
|
|
||||||
BasicResult(ResultBase::Type type, std::string const &message)
|
BasicResult( ResultBase::Type type, std::string const &message )
|
||||||
: ResultValueBase<T>(type),
|
: ResultValueBase<T>(type),
|
||||||
m_errorMessage(message) {
|
m_errorMessage(message)
|
||||||
assert(m_type != ResultBase::Ok);
|
{
|
||||||
|
assert( m_type != ResultBase::Ok );
|
||||||
}
|
}
|
||||||
|
|
||||||
using ResultValueBase<T>::ResultValueBase;
|
using ResultValueBase<T>::ResultValueBase;
|
||||||
@@ -602,12 +605,12 @@ namespace detail {
|
|||||||
class ParseState {
|
class ParseState {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ParseState(ParseResultType type, TokenStream const &remainingTokens)
|
ParseState( ParseResultType type, TokenStream const &remainingTokens )
|
||||||
: m_type(type),
|
: m_type(type),
|
||||||
m_remainingTokens(remainingTokens) {}
|
m_remainingTokens( remainingTokens )
|
||||||
|
{}
|
||||||
|
|
||||||
auto type() const -> ParseResultType { return m_type; }
|
auto type() const -> ParseResultType { return m_type; }
|
||||||
|
|
||||||
auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
|
auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -625,69 +628,62 @@ namespace detail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline auto convertInto(std::string const &source, T& target) -> ParserResult {
|
inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << source;
|
ss << source;
|
||||||
ss >> target;
|
ss >> target;
|
||||||
if (ss.fail())
|
if( ss.fail() )
|
||||||
return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type");
|
return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
|
||||||
else
|
else
|
||||||
return ParserResult::ok(ParseResultType::Matched);
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
}
|
}
|
||||||
inline auto convertInto(std::string const &source, std::string& target) -> ParserResult {
|
inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
|
||||||
target = source;
|
target = source;
|
||||||
return ParserResult::ok(ParseResultType::Matched);
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
}
|
}
|
||||||
inline auto convertInto(std::string const &source, bool &target) -> ParserResult {
|
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
|
||||||
std::string srcLC = source;
|
std::string srcLC = source;
|
||||||
std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast<char>( ::tolower(c) ); } );
|
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
|
||||||
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
|
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
|
||||||
target = true;
|
target = true;
|
||||||
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
|
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
|
||||||
target = false;
|
target = false;
|
||||||
else
|
else
|
||||||
return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'");
|
return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
|
||||||
return ParserResult::ok(ParseResultType::Matched);
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BoundRefBase {
|
struct BoundRefBase {
|
||||||
BoundRefBase() = default;
|
BoundRefBase() = default;
|
||||||
|
BoundRefBase( BoundRefBase const & ) = delete;
|
||||||
BoundRefBase(BoundRefBase const &) = delete;
|
BoundRefBase( BoundRefBase && ) = delete;
|
||||||
|
BoundRefBase &operator=( BoundRefBase const & ) = delete;
|
||||||
BoundRefBase(BoundRefBase &&) = delete;
|
BoundRefBase &operator=( BoundRefBase && ) = delete;
|
||||||
|
|
||||||
BoundRefBase &operator=(BoundRefBase const &) = delete;
|
|
||||||
|
|
||||||
BoundRefBase &operator=(BoundRefBase &&) = delete;
|
|
||||||
|
|
||||||
virtual ~BoundRefBase() = default;
|
virtual ~BoundRefBase() = default;
|
||||||
|
|
||||||
virtual auto isFlag() const -> bool = 0;
|
virtual auto isFlag() const -> bool = 0;
|
||||||
|
|
||||||
virtual auto isContainer() const -> bool { return false; }
|
virtual auto isContainer() const -> bool { return false; }
|
||||||
|
virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
|
||||||
virtual auto setValue(std::string const &arg) -> ParserResult = 0;
|
virtual auto setFlag( bool flag ) -> ParserResult = 0;
|
||||||
|
|
||||||
virtual auto setFlag(bool flag) -> ParserResult = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BoundValueRefBase : BoundRefBase {
|
struct BoundValueRefBase : BoundRefBase {
|
||||||
auto isFlag() const -> bool override { return false; }
|
auto isFlag() const -> bool override { return false; }
|
||||||
|
|
||||||
auto setFlag(bool) -> ParserResult override {
|
auto setFlag( bool ) -> ParserResult override {
|
||||||
return ParserResult::logicError("Flags can only be set on boolean fields");
|
return ParserResult::logicError( "Flags can only be set on boolean fields" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BoundFlagRefBase : BoundRefBase {
|
struct BoundFlagRefBase : BoundRefBase {
|
||||||
auto isFlag() const -> bool override { return true; }
|
auto isFlag() const -> bool override { return true; }
|
||||||
|
|
||||||
auto setValue(std::string const &arg) -> ParserResult override {
|
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||||
bool flag;
|
bool flag;
|
||||||
auto result = convertInto(arg, flag);
|
auto result = convertInto( arg, flag );
|
||||||
if (result)
|
if( result )
|
||||||
setFlag(flag);
|
setFlag( flag );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -696,10 +692,10 @@ namespace detail {
|
|||||||
struct BoundRef : BoundValueRefBase {
|
struct BoundRef : BoundValueRefBase {
|
||||||
T &m_ref;
|
T &m_ref;
|
||||||
|
|
||||||
explicit BoundRef(T &ref) : m_ref(ref) {}
|
explicit BoundRef( T &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
auto setValue(std::string const &arg) -> ParserResult override {
|
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||||
return convertInto(arg, m_ref);
|
return convertInto( arg, m_ref );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -707,15 +703,15 @@ namespace detail {
|
|||||||
struct BoundRef<std::vector<T>> : BoundValueRefBase {
|
struct BoundRef<std::vector<T>> : BoundValueRefBase {
|
||||||
std::vector<T> &m_ref;
|
std::vector<T> &m_ref;
|
||||||
|
|
||||||
explicit BoundRef(std::vector<T> &ref) : m_ref(ref) {}
|
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
auto isContainer() const -> bool override { return true; }
|
auto isContainer() const -> bool override { return true; }
|
||||||
|
|
||||||
auto setValue(std::string const &arg) -> ParserResult override {
|
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||||
T temp;
|
T temp;
|
||||||
auto result = convertInto(arg, temp);
|
auto result = convertInto( arg, temp );
|
||||||
if (result)
|
if( result )
|
||||||
m_ref.push_back(temp);
|
m_ref.push_back( temp );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -723,40 +719,40 @@ namespace detail {
|
|||||||
struct BoundFlagRef : BoundFlagRefBase {
|
struct BoundFlagRef : BoundFlagRefBase {
|
||||||
bool &m_ref;
|
bool &m_ref;
|
||||||
|
|
||||||
explicit BoundFlagRef(bool &ref) : m_ref(ref) {}
|
explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
auto setFlag(bool flag) -> ParserResult override {
|
auto setFlag( bool flag ) -> ParserResult override {
|
||||||
m_ref = flag;
|
m_ref = flag;
|
||||||
return ParserResult::ok(ParseResultType::Matched);
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ReturnType>
|
template<typename ReturnType>
|
||||||
struct LambdaInvoker {
|
struct LambdaInvoker {
|
||||||
static_assert(std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult");
|
static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
|
||||||
|
|
||||||
template<typename L, typename ArgType>
|
template<typename L, typename ArgType>
|
||||||
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult {
|
static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
|
||||||
return lambda(arg);
|
return lambda( arg );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct LambdaInvoker<void> {
|
struct LambdaInvoker<void> {
|
||||||
template<typename L, typename ArgType>
|
template<typename L, typename ArgType>
|
||||||
static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult {
|
static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
|
||||||
lambda(arg);
|
lambda( arg );
|
||||||
return ParserResult::ok(ParseResultType::Matched);
|
return ParserResult::ok( ParseResultType::Matched );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ArgType, typename L>
|
template<typename ArgType, typename L>
|
||||||
inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult {
|
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
|
||||||
ArgType temp;
|
ArgType temp;
|
||||||
auto result = convertInto(arg, temp);
|
auto result = convertInto( arg, temp );
|
||||||
return !result
|
return !result
|
||||||
? result
|
? result
|
||||||
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(lambda, temp);
|
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -765,10 +761,10 @@ namespace detail {
|
|||||||
L m_lambda;
|
L m_lambda;
|
||||||
|
|
||||||
static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
|
static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
|
||||||
explicit BoundLambda(L const &lambda) : m_lambda(lambda) {}
|
explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
|
||||||
|
|
||||||
auto setValue(std::string const &arg) -> ParserResult override {
|
auto setValue( std::string const &arg ) -> ParserResult override {
|
||||||
return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg);
|
return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -779,16 +775,14 @@ namespace detail {
|
|||||||
static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
|
static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
|
||||||
static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
|
static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
|
||||||
|
|
||||||
explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {}
|
explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
|
||||||
|
|
||||||
auto setFlag(bool flag) -> ParserResult override {
|
auto setFlag( bool flag ) -> ParserResult override {
|
||||||
return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag);
|
return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Optionality {
|
enum class Optionality { Optional, Required };
|
||||||
Optional, Required
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parser;
|
struct Parser;
|
||||||
|
|
||||||
@@ -799,8 +793,8 @@ namespace detail {
|
|||||||
virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0;
|
virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0;
|
||||||
virtual auto cardinality() const -> size_t { return 1; }
|
virtual auto cardinality() const -> size_t { return 1; }
|
||||||
|
|
||||||
auto parse(Args const &args) const -> InternalParseResult {
|
auto parse( Args const &args ) const -> InternalParseResult {
|
||||||
return parse( args.exeName(), TokenStream(args));
|
return parse( args.exeName(), TokenStream( args ) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -808,7 +802,7 @@ namespace detail {
|
|||||||
class ComposableParserImpl : public ParserBase {
|
class ComposableParserImpl : public ParserBase {
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto operator+(T const &other) const -> Parser;
|
auto operator|( T const &other ) const -> Parser;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Common code and state for Args and Opts
|
// Common code and state for Args and Opts
|
||||||
@@ -820,17 +814,22 @@ namespace detail {
|
|||||||
std::string m_hint;
|
std::string m_hint;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
|
|
||||||
explicit ParserRefImpl(std::shared_ptr<BoundRefBase> const &ref) : m_ref(ref) {}
|
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared<BoundRef<T>>(ref)), m_hint(hint) {}
|
ParserRefImpl( T &ref, std::string const &hint )
|
||||||
|
: m_ref( std::make_shared<BoundRef<T>>( ref ) ),
|
||||||
|
m_hint( hint )
|
||||||
|
{}
|
||||||
|
|
||||||
template<typename LambdaT>
|
template<typename LambdaT>
|
||||||
ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)),
|
ParserRefImpl( LambdaT const &ref, std::string const &hint )
|
||||||
m_hint(hint) {}
|
: m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
|
||||||
|
m_hint(hint)
|
||||||
|
{}
|
||||||
|
|
||||||
auto operator()(std::string const &description) -> DerivedT & {
|
auto operator()( std::string const &description ) -> DerivedT & {
|
||||||
m_description = description;
|
m_description = description;
|
||||||
return static_cast<DerivedT &>( *this );
|
return static_cast<DerivedT &>( *this );
|
||||||
}
|
}
|
||||||
@@ -850,7 +849,7 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto cardinality() const -> size_t override {
|
auto cardinality() const -> size_t override {
|
||||||
if (m_ref->isContainer())
|
if( m_ref->isContainer() )
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
@@ -865,13 +864,13 @@ namespace detail {
|
|||||||
|
|
||||||
template<typename LambdaT>
|
template<typename LambdaT>
|
||||||
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
|
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> {
|
||||||
return std::make_shared<BoundLambda<LambdaT>>(lambda);
|
return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExeName() : m_name(std::make_shared<std::string>("<executable>")) {}
|
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
|
||||||
|
|
||||||
explicit ExeName(std::string &ref) : ExeName() {
|
explicit ExeName( std::string &ref ) : ExeName() {
|
||||||
m_ref = std::make_shared<BoundRef<std::string>>( ref );
|
m_ref = std::make_shared<BoundRef<std::string>>( ref );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,14 +881,14 @@ namespace detail {
|
|||||||
|
|
||||||
// The exe name is not parsed out of the normal tokens, but is handled specially
|
// The exe name is not parsed out of the normal tokens, but is handled specially
|
||||||
auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
|
auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
|
||||||
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
|
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name() const -> std::string { return *m_name; }
|
auto name() const -> std::string { return *m_name; }
|
||||||
auto set( std::string const& newName ) -> ParserResult {
|
auto set( std::string const& newName ) -> ParserResult {
|
||||||
|
|
||||||
auto lastSlash = newName.find_last_of( "\\/" );
|
auto lastSlash = newName.find_last_of( "\\/" );
|
||||||
auto filename = (lastSlash == std::string::npos)
|
auto filename = ( lastSlash == std::string::npos )
|
||||||
? newName
|
? newName
|
||||||
: newName.substr( lastSlash+1 );
|
: newName.substr( lastSlash+1 );
|
||||||
|
|
||||||
@@ -905,28 +904,30 @@ namespace detail {
|
|||||||
public:
|
public:
|
||||||
using ParserRefImpl::ParserRefImpl;
|
using ParserRefImpl::ParserRefImpl;
|
||||||
|
|
||||||
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override {
|
auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {
|
||||||
auto validationResult = validate();
|
auto validationResult = validate();
|
||||||
if (!validationResult)
|
if( !validationResult )
|
||||||
return InternalParseResult(validationResult);
|
return InternalParseResult( validationResult );
|
||||||
|
|
||||||
auto remainingTokens = tokens;
|
auto remainingTokens = tokens;
|
||||||
auto const &token = *remainingTokens;
|
auto const &token = *remainingTokens;
|
||||||
if (token.type != TokenType::Argument)
|
if( token.type != TokenType::Argument )
|
||||||
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
|
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||||
|
|
||||||
auto result = m_ref->setValue(remainingTokens->token);
|
auto result = m_ref->setValue( remainingTokens->token );
|
||||||
if (!result)
|
if( !result )
|
||||||
return InternalParseResult(result);
|
return InternalParseResult( result );
|
||||||
else
|
else
|
||||||
return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens));
|
return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline auto normaliseOpt(std::string const &optName) -> std::string {
|
inline auto normaliseOpt( std::string const &optName ) -> std::string {
|
||||||
if (optName[0] == '/')
|
#ifdef CATCH_PLATFORM_WINDOWS
|
||||||
return "-" + optName.substr(1);
|
if( optName[0] == '/' )
|
||||||
|
return "-" + optName.substr( 1 );
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
return optName;
|
return optName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,9 +937,9 @@ namespace detail {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename LambdaT>
|
template<typename LambdaT>
|
||||||
explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref)) {}
|
explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
|
||||||
|
|
||||||
explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
|
explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
|
||||||
|
|
||||||
template<typename LambdaT>
|
template<typename LambdaT>
|
||||||
Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
|
Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
|
||||||
@@ -946,34 +947,30 @@ namespace detail {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
|
Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
|
||||||
|
|
||||||
auto operator[](std::string const &optName) -> Opt & {
|
auto operator[]( std::string const &optName ) -> Opt & {
|
||||||
m_optNames.push_back(optName);
|
m_optNames.push_back( optName );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto const &opt : m_optNames) {
|
for( auto const &opt : m_optNames ) {
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
oss << ", ";
|
oss << ", ";
|
||||||
oss << opt;
|
oss << opt;
|
||||||
}
|
}
|
||||||
if (!m_hint.empty())
|
if( !m_hint.empty() )
|
||||||
oss << " <" << m_hint << ">";
|
oss << " <" << m_hint << ">";
|
||||||
return {{oss.str(), m_description}};
|
return { { oss.str(), m_description } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto isMatch(std::string const &optToken) const -> bool {
|
auto isMatch( std::string const &optToken ) const -> bool {
|
||||||
#ifdef CLARA_PLATFORM_WINDOWS
|
|
||||||
auto normalisedToken = normaliseOpt( optToken );
|
auto normalisedToken = normaliseOpt( optToken );
|
||||||
#else
|
for( auto const &name : m_optNames ) {
|
||||||
auto const &normalisedToken = optToken;
|
if( normaliseOpt( name ) == normalisedToken )
|
||||||
#endif
|
|
||||||
for (auto const &name : m_optNames) {
|
|
||||||
if (normaliseOpt(name) == normalisedToken)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -983,46 +980,51 @@ namespace detail {
|
|||||||
|
|
||||||
auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
|
auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
|
||||||
auto validationResult = validate();
|
auto validationResult = validate();
|
||||||
if (!validationResult)
|
if( !validationResult )
|
||||||
return InternalParseResult(validationResult);
|
return InternalParseResult( validationResult );
|
||||||
|
|
||||||
auto remainingTokens = tokens;
|
auto remainingTokens = tokens;
|
||||||
if (remainingTokens && remainingTokens->type == TokenType::Option) {
|
if( remainingTokens && remainingTokens->type == TokenType::Option ) {
|
||||||
auto const &token = *remainingTokens;
|
auto const &token = *remainingTokens;
|
||||||
if (isMatch(token.token)) {
|
if( isMatch(token.token ) ) {
|
||||||
if (m_ref->isFlag()) {
|
if( m_ref->isFlag() ) {
|
||||||
auto result = m_ref->setFlag(true);
|
auto result = m_ref->setFlag( true );
|
||||||
if (!result)
|
if( !result )
|
||||||
return InternalParseResult(result);
|
return InternalParseResult( result );
|
||||||
if (result.value() == ParseResultType::ShortCircuitAll)
|
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||||
return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
|
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
||||||
} else {
|
} else {
|
||||||
++remainingTokens;
|
++remainingTokens;
|
||||||
if (!remainingTokens)
|
if( !remainingTokens )
|
||||||
return InternalParseResult::runtimeError("Expected argument following " + token.token);
|
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||||
auto const &argToken = *remainingTokens;
|
auto const &argToken = *remainingTokens;
|
||||||
if (argToken.type != TokenType::Argument)
|
if( argToken.type != TokenType::Argument )
|
||||||
return InternalParseResult::runtimeError("Expected argument following " + token.token);
|
return InternalParseResult::runtimeError( "Expected argument following " + token.token );
|
||||||
auto result = m_ref->setValue(argToken.token);
|
auto result = m_ref->setValue( argToken.token );
|
||||||
if (!result)
|
if( !result )
|
||||||
return InternalParseResult(result);
|
return InternalParseResult( result );
|
||||||
if (result.value() == ParseResultType::ShortCircuitAll)
|
if( result.value() == ParseResultType::ShortCircuitAll )
|
||||||
return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
|
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
|
||||||
}
|
}
|
||||||
return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens));
|
return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
|
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto validate() const -> Result override {
|
auto validate() const -> Result override {
|
||||||
if (m_optNames.empty())
|
if( m_optNames.empty() )
|
||||||
return Result::logicError("No options supplied to Opt");
|
return Result::logicError( "No options supplied to Opt" );
|
||||||
for (auto const &name : m_optNames) {
|
for( auto const &name : m_optNames ) {
|
||||||
if (name.empty())
|
if( name.empty() )
|
||||||
return Result::logicError("Option name cannot be empty");
|
return Result::logicError( "Option name cannot be empty" );
|
||||||
if (name[0] != '-' && name[0] != '/')
|
#ifdef CATCH_PLATFORM_WINDOWS
|
||||||
return Result::logicError("Option name must begin with '-' or '/'");
|
if( name[0] != '-' && name[0] != '/' )
|
||||||
|
return Result::logicError( "Option name must begin with '-' or '/'" );
|
||||||
|
#else
|
||||||
|
if( name[0] != '-' )
|
||||||
|
return Result::logicError( "Option name must begin with '-'" );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return ParserRefImpl::validate();
|
return ParserRefImpl::validate();
|
||||||
}
|
}
|
||||||
@@ -1031,11 +1033,11 @@ namespace detail {
|
|||||||
struct Help : Opt {
|
struct Help : Opt {
|
||||||
Help( bool &showHelpFlag )
|
Help( bool &showHelpFlag )
|
||||||
: Opt([&]( bool flag ) {
|
: Opt([&]( bool flag ) {
|
||||||
showHelpFlag = flag;
|
showHelpFlag = flag;
|
||||||
return ParserResult::ok(ParseResultType::ShortCircuitAll);
|
return ParserResult::ok( ParseResultType::ShortCircuitAll );
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
static_cast<Opt &>(*this)
|
static_cast<Opt &>( *this )
|
||||||
("display usage information")
|
("display usage information")
|
||||||
["-?"]["-h"]["--help"]
|
["-?"]["-h"]["--help"]
|
||||||
.optional();
|
.optional();
|
||||||
@@ -1049,61 +1051,61 @@ namespace detail {
|
|||||||
std::vector<Opt> m_options;
|
std::vector<Opt> m_options;
|
||||||
std::vector<Arg> m_args;
|
std::vector<Arg> m_args;
|
||||||
|
|
||||||
auto operator+=(ExeName const &exeName) -> Parser & {
|
auto operator|=( ExeName const &exeName ) -> Parser & {
|
||||||
m_exeName = exeName;
|
m_exeName = exeName;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator+=(Arg const &arg) -> Parser & {
|
auto operator|=( Arg const &arg ) -> Parser & {
|
||||||
m_args.push_back(arg);
|
m_args.push_back(arg);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator+=(Opt const &opt) -> Parser & {
|
auto operator|=( Opt const &opt ) -> Parser & {
|
||||||
m_options.push_back(opt);
|
m_options.push_back(opt);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator+=(Parser const &other) -> Parser & {
|
auto operator|=( Parser const &other ) -> Parser & {
|
||||||
m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
|
m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
|
||||||
m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
|
m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto operator+(T const &other) const -> Parser {
|
auto operator|( T const &other ) const -> Parser {
|
||||||
return Parser(*this) += other;
|
return Parser( *this ) |= other;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
auto getHelpColumns() const -> std::vector<HelpColumns> {
|
||||||
std::vector<HelpColumns> cols;
|
std::vector<HelpColumns> cols;
|
||||||
for (auto const &o : m_options) {
|
for (auto const &o : m_options) {
|
||||||
auto childCols = o.getHelpColumns();
|
auto childCols = o.getHelpColumns();
|
||||||
cols.insert(cols.end(), childCols.begin(), childCols.end());
|
cols.insert( cols.end(), childCols.begin(), childCols.end() );
|
||||||
}
|
}
|
||||||
return cols;
|
return cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeToStream(std::ostream &os) const {
|
void writeToStream( std::ostream &os ) const {
|
||||||
if (!m_exeName.name().empty()) {
|
if (!m_exeName.name().empty()) {
|
||||||
os << "usage:\n" << " " << m_exeName.name() << " ";
|
os << "usage:\n" << " " << m_exeName.name() << " ";
|
||||||
bool required = true, first = true;
|
bool required = true, first = true;
|
||||||
for (auto const &arg : m_args) {
|
for( auto const &arg : m_args ) {
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
os << " ";
|
os << " ";
|
||||||
if (arg.isOptional() && required) {
|
if( arg.isOptional() && required ) {
|
||||||
os << "[";
|
os << "[";
|
||||||
required = false;
|
required = false;
|
||||||
}
|
}
|
||||||
os << "<" << arg.hint() << ">";
|
os << "<" << arg.hint() << ">";
|
||||||
if (arg.cardinality() == 0)
|
if( arg.cardinality() == 0 )
|
||||||
os << " ... ";
|
os << " ... ";
|
||||||
}
|
}
|
||||||
if (!required)
|
if( !required )
|
||||||
os << "]";
|
os << "]";
|
||||||
if (!m_options.empty())
|
if( !m_options.empty() )
|
||||||
os << " options";
|
os << " options";
|
||||||
os << "\n\nwhere options are:" << std::endl;
|
os << "\n\nwhere options are:" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -1111,32 +1113,32 @@ namespace detail {
|
|||||||
auto rows = getHelpColumns();
|
auto rows = getHelpColumns();
|
||||||
size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
|
size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
|
||||||
size_t optWidth = 0;
|
size_t optWidth = 0;
|
||||||
for (auto const &cols : rows)
|
for( auto const &cols : rows )
|
||||||
optWidth = std::max(optWidth, cols.left.size() + 2);
|
optWidth = (std::max)(optWidth, cols.left.size() + 2);
|
||||||
|
|
||||||
for (auto const &cols : rows) {
|
for( auto const &cols : rows ) {
|
||||||
auto row =
|
auto row =
|
||||||
TextFlow::Column(cols.left).width(optWidth).indent(2) +
|
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
|
||||||
TextFlow::Spacer(4) +
|
TextFlow::Spacer(4) +
|
||||||
TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
|
TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
|
||||||
os << row << std::endl;
|
os << row << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & {
|
friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {
|
||||||
parser.writeToStream(os);
|
parser.writeToStream( os );
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto validate() const -> Result override {
|
auto validate() const -> Result override {
|
||||||
for (auto const &opt : m_options) {
|
for( auto const &opt : m_options ) {
|
||||||
auto result = opt.validate();
|
auto result = opt.validate();
|
||||||
if (!result)
|
if( !result )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
for (auto const &arg : m_args) {
|
for( auto const &arg : m_args ) {
|
||||||
auto result = arg.validate();
|
auto result = arg.validate();
|
||||||
if (!result)
|
if( !result )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return Result::ok();
|
return Result::ok();
|
||||||
@@ -1144,47 +1146,47 @@ namespace detail {
|
|||||||
|
|
||||||
using ParserBase::parse;
|
using ParserBase::parse;
|
||||||
|
|
||||||
auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override {
|
auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
|
||||||
std::vector<ParserBase const *> allParsers;
|
|
||||||
allParsers.reserve(m_args.size() + m_options.size());
|
|
||||||
std::set<ParserBase const *> requiredParsers;
|
|
||||||
|
|
||||||
for (auto const &opt : m_options) {
|
struct ParserInfo {
|
||||||
allParsers.push_back(&opt);
|
ParserBase const* parser = nullptr;
|
||||||
if (!opt.isOptional())
|
size_t count = 0;
|
||||||
requiredParsers.insert(&opt);
|
};
|
||||||
}
|
const size_t totalParsers = m_options.size() + m_args.size();
|
||||||
|
assert( totalParsers < 512 );
|
||||||
|
// ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
|
||||||
|
ParserInfo parseInfos[512];
|
||||||
|
|
||||||
size_t optionalArgs = 0;
|
{
|
||||||
for (auto const &arg : m_args) {
|
size_t i = 0;
|
||||||
allParsers.push_back(&arg);
|
for (auto const &opt : m_options) parseInfos[i++].parser = &opt;
|
||||||
if (!arg.isOptional()) {
|
for (auto const &arg : m_args) parseInfos[i++].parser = &arg;
|
||||||
if (optionalArgs > 0)
|
|
||||||
return InternalParseResult::logicError(
|
|
||||||
"Required arguments must preceed any optional arguments");
|
|
||||||
else
|
|
||||||
++optionalArgs;
|
|
||||||
requiredParsers.insert(&arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_exeName.set( exeName );
|
m_exeName.set( exeName );
|
||||||
|
|
||||||
auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
|
auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
|
||||||
while (result.value().remainingTokens()) {
|
while( result.value().remainingTokens() ) {
|
||||||
auto remainingTokenCount = result.value().remainingTokens().count();
|
bool tokenParsed = false;
|
||||||
for (auto parser : allParsers) {
|
|
||||||
result = parser->parse( exeName, result.value().remainingTokens() );
|
for( size_t i = 0; i < totalParsers; ++i ) {
|
||||||
if (!result || result.value().type() != ParseResultType::NoMatch) {
|
auto& parseInfo = parseInfos[i];
|
||||||
if (parser->cardinality() == 1)
|
if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
|
||||||
allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser),
|
result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
|
||||||
allParsers.end());
|
if (!result)
|
||||||
requiredParsers.erase(parser);
|
return result;
|
||||||
break;
|
if (result.value().type() != ParseResultType::NoMatch) {
|
||||||
|
tokenParsed = true;
|
||||||
|
++parseInfo.count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!result || remainingTokenCount == result.value().remainingTokens().count())
|
|
||||||
|
if( result.value().type() == ParseResultType::ShortCircuitAll )
|
||||||
return result;
|
return result;
|
||||||
|
if( !tokenParsed )
|
||||||
|
return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
|
||||||
}
|
}
|
||||||
// !TBD Check missing required options
|
// !TBD Check missing required options
|
||||||
return result;
|
return result;
|
||||||
@@ -1193,8 +1195,8 @@ namespace detail {
|
|||||||
|
|
||||||
template<typename DerivedT>
|
template<typename DerivedT>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto ComposableParserImpl<DerivedT>::operator+(T const &other) const -> Parser {
|
auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {
|
||||||
return Parser() + static_cast<DerivedT const &>( *this ) + other;
|
return Parser() | static_cast<DerivedT const &>( *this ) | other;
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
@@ -6,24 +6,28 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_approx.hpp"
|
#include "catch_approx.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Performs equivalent check of std::fabs(lhs - rhs) <= margin
|
||||||
|
// But without the subtraction to allow for INFINITY in comparison
|
||||||
|
bool marginComparison(double lhs, double rhs, double margin) {
|
||||||
|
return (lhs + margin >= rhs) && (rhs + margin >= lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
|
|
||||||
double max(double lhs, double rhs) {
|
|
||||||
if (lhs < rhs) {
|
|
||||||
return rhs;
|
|
||||||
}
|
|
||||||
return lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Approx::Approx ( double value )
|
Approx::Approx ( double value )
|
||||||
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
|
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
|
||||||
m_margin( 0.0 ),
|
m_margin( 0.0 ),
|
||||||
m_scale( 1.0 ),
|
m_scale( 0.0 ),
|
||||||
m_value( value )
|
m_value( value )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -37,6 +41,12 @@ namespace Detail {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Approx::equalityComparisonImpl(const double other) const {
|
||||||
|
// First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
|
||||||
|
// Thanks to Richard Harris for his help refining the scaled margin value
|
||||||
|
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Detail
|
} // end namespace Detail
|
||||||
|
|
||||||
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
|
std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
|
||||||
|
@@ -8,18 +8,18 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_enforce.h"
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
|
|
||||||
double max(double lhs, double rhs);
|
|
||||||
|
|
||||||
class Approx {
|
class Approx {
|
||||||
|
private:
|
||||||
|
bool equalityComparisonImpl(double other) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Approx ( double value );
|
explicit Approx ( double value );
|
||||||
|
|
||||||
@@ -41,13 +41,8 @@ namespace Detail {
|
|||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
friend bool operator == ( const T& lhs, Approx const& rhs ) {
|
friend bool operator == ( const T& lhs, Approx const& rhs ) {
|
||||||
// Thanks to Richard Harris for his help refining this formula
|
|
||||||
auto lhs_v = static_cast<double>(lhs);
|
auto lhs_v = static_cast<double>(lhs);
|
||||||
bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
|
return rhs.equalityComparisonImpl(lhs_v);
|
||||||
if (relativeOK) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
@@ -87,13 +82,21 @@ namespace Detail {
|
|||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& epsilon( T const& newEpsilon ) {
|
Approx& epsilon( T const& newEpsilon ) {
|
||||||
m_epsilon = static_cast<double>(newEpsilon);
|
double epsilonAsDouble = static_cast<double>(newEpsilon);
|
||||||
|
CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0,
|
||||||
|
"Invalid Approx::epsilon: " << epsilonAsDouble
|
||||||
|
<< ", Approx::epsilon has to be between 0 and 1");
|
||||||
|
m_epsilon = epsilonAsDouble;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& margin( T const& newMargin ) {
|
Approx& margin( T const& newMargin ) {
|
||||||
m_margin = static_cast<double>(newMargin);
|
double marginAsDouble = static_cast<double>(newMargin);
|
||||||
|
CATCH_ENFORCE(marginAsDouble >= 0,
|
||||||
|
"Invalid Approx::margin: " << marginAsDouble
|
||||||
|
<< ", Approx::Margin has to be non-negative.");
|
||||||
|
m_margin = marginAsDouble;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
|
AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
|
||||||
resultType(_resultType),
|
lazyExpression(_lazyExpression),
|
||||||
lazyExpression(_lazyExpression) {}
|
resultType(_resultType) {}
|
||||||
|
|
||||||
std::string AssertionResultData::reconstructExpression() const {
|
std::string AssertionResultData::reconstructExpression() const {
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string AssertionResult::getExpression() const {
|
std::string AssertionResult::getExpression() const {
|
||||||
if (isFalseTest(m_info.resultDisposition))
|
if( isFalseTest( m_info.resultDisposition ) )
|
||||||
return '!' + std::string(m_info.capturedExpression);
|
return "!(" + std::string(m_info.capturedExpression) + ")";
|
||||||
else
|
else
|
||||||
return m_info.capturedExpression;
|
return m_info.capturedExpression;
|
||||||
}
|
}
|
||||||
|
@@ -23,13 +23,12 @@ namespace Catch {
|
|||||||
|
|
||||||
AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
|
AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
|
||||||
|
|
||||||
ResultWas::OfType resultType = ResultWas::Unknown;
|
|
||||||
std::string message;
|
std::string message;
|
||||||
|
mutable std::string reconstructedExpression;
|
||||||
LazyExpression lazyExpression;
|
LazyExpression lazyExpression;
|
||||||
|
ResultWas::OfType resultType;
|
||||||
|
|
||||||
std::string reconstructExpression() const;
|
std::string reconstructExpression() const;
|
||||||
mutable std::string reconstructedExpression;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AssertionResult {
|
class AssertionResult {
|
||||||
|
@@ -19,8 +19,8 @@ namespace Catch {
|
|||||||
class BenchmarkLooper {
|
class BenchmarkLooper {
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
size_t m_count = 0;
|
std::size_t m_count = 0;
|
||||||
size_t m_iterationsToRun = 1;
|
std::size_t m_iterationsToRun = 1;
|
||||||
uint64_t m_resolution;
|
uint64_t m_resolution;
|
||||||
Timer m_timer;
|
Timer m_timer;
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "catch_assertionhandler.h"
|
#include "catch_assertionhandler.h"
|
||||||
#include "catch_message.h"
|
#include "catch_message.h"
|
||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
|
#include "catch_debugger.h"
|
||||||
|
|
||||||
#if !defined(CATCH_CONFIG_DISABLE)
|
#if !defined(CATCH_CONFIG_DISABLE)
|
||||||
|
|
||||||
@@ -38,8 +39,6 @@
|
|||||||
|
|
||||||
#else // CATCH_CONFIG_FAST_COMPILE
|
#else // CATCH_CONFIG_FAST_COMPILE
|
||||||
|
|
||||||
#include "catch_debugger.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// In the event of a failure works out if the debugger needs to be invoked
|
// In the event of a failure works out if the debugger needs to be invoked
|
||||||
// and/or an exception thrown and takes appropriate action.
|
// and/or an exception thrown and takes appropriate action.
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_capture.hpp"
|
#include "catch_capture.hpp"
|
||||||
#include "catch_matchers.hpp"
|
#include "catch_matchers.h"
|
||||||
#include "catch_matchers_string.h"
|
#include "catch_matchers_string.h"
|
||||||
#include "catch_matchers_vector.h"
|
#include "catch_matchers_vector.h"
|
||||||
|
|
||||||
|
@@ -16,9 +16,18 @@
|
|||||||
#endif
|
#endif
|
||||||
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
|
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||||
|
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#pragma clang diagnostic ignored "-Wshadow"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../external/clara.hpp"
|
#include "../external/clara.hpp"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
// Restore Clara's value for console width, if present
|
// Restore Clara's value for console width, if present
|
||||||
#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
|
#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_commandline.hpp"
|
#include "catch_commandline.h"
|
||||||
|
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
@@ -98,84 +98,84 @@ namespace Catch {
|
|||||||
|
|
||||||
auto cli
|
auto cli
|
||||||
= ExeName( config.processName )
|
= ExeName( config.processName )
|
||||||
+ Help( config.showHelp )
|
| Help( config.showHelp )
|
||||||
+ Opt( config.listTests )
|
| Opt( config.listTests )
|
||||||
["-l"]["--list-tests"]
|
["-l"]["--list-tests"]
|
||||||
( "list all/matching test cases" )
|
( "list all/matching test cases" )
|
||||||
+ Opt( config.listTags )
|
| Opt( config.listTags )
|
||||||
["-t"]["--list-tags"]
|
["-t"]["--list-tags"]
|
||||||
( "list all/matching tags" )
|
( "list all/matching tags" )
|
||||||
+ Opt( config.showSuccessfulTests )
|
| Opt( config.showSuccessfulTests )
|
||||||
["-s"]["--success"]
|
["-s"]["--success"]
|
||||||
( "include successful tests in output" )
|
( "include successful tests in output" )
|
||||||
+ Opt( config.shouldDebugBreak )
|
| Opt( config.shouldDebugBreak )
|
||||||
["-b"]["--break"]
|
["-b"]["--break"]
|
||||||
( "break into debugger on failure" )
|
( "break into debugger on failure" )
|
||||||
+ Opt( config.noThrow )
|
| Opt( config.noThrow )
|
||||||
["-e"]["--nothrow"]
|
["-e"]["--nothrow"]
|
||||||
( "skip exception tests" )
|
( "skip exception tests" )
|
||||||
+ Opt( config.showInvisibles )
|
| Opt( config.showInvisibles )
|
||||||
["-i"]["--invisibles"]
|
["-i"]["--invisibles"]
|
||||||
( "show invisibles (tabs, newlines)" )
|
( "show invisibles (tabs, newlines)" )
|
||||||
+ Opt( config.outputFilename, "filename" )
|
| Opt( config.outputFilename, "filename" )
|
||||||
["-o"]["--out"]
|
["-o"]["--out"]
|
||||||
( "output filename" )
|
( "output filename" )
|
||||||
+ Opt( config.reporterNames, "name" )
|
| Opt( config.reporterNames, "name" )
|
||||||
["-r"]["--reporter"]
|
["-r"]["--reporter"]
|
||||||
( "reporter to use (defaults to console)" )
|
( "reporter to use (defaults to console)" )
|
||||||
+ Opt( config.name, "name" )
|
| Opt( config.name, "name" )
|
||||||
["-n"]["--name"]
|
["-n"]["--name"]
|
||||||
( "suite name" )
|
( "suite name" )
|
||||||
+ Opt( [&]( bool ){ config.abortAfter = 1; } )
|
| Opt( [&]( bool ){ config.abortAfter = 1; } )
|
||||||
["-a"]["--abort"]
|
["-a"]["--abort"]
|
||||||
( "abort at first failure" )
|
( "abort at first failure" )
|
||||||
+ Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
|
| Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
|
||||||
["-x"]["--abortx"]
|
["-x"]["--abortx"]
|
||||||
( "abort after x failures" )
|
( "abort after x failures" )
|
||||||
+ Opt( setWarning, "warning name" )
|
| Opt( setWarning, "warning name" )
|
||||||
["-w"]["--warn"]
|
["-w"]["--warn"]
|
||||||
( "enable warnings" )
|
( "enable warnings" )
|
||||||
+ Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
|
| Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
|
||||||
["-d"]["--durations"]
|
["-d"]["--durations"]
|
||||||
( "show test durations" )
|
( "show test durations" )
|
||||||
+ Opt( loadTestNamesFromFile, "filename" )
|
| Opt( loadTestNamesFromFile, "filename" )
|
||||||
["-f"]["--input-file"]
|
["-f"]["--input-file"]
|
||||||
( "load test names to run from a file" )
|
( "load test names to run from a file" )
|
||||||
+ Opt( config.filenamesAsTags )
|
| Opt( config.filenamesAsTags )
|
||||||
["-#"]["--filenames-as-tags"]
|
["-#"]["--filenames-as-tags"]
|
||||||
( "adds a tag for the filename" )
|
( "adds a tag for the filename" )
|
||||||
+ Opt( config.sectionsToRun, "section name" )
|
| Opt( config.sectionsToRun, "section name" )
|
||||||
["-c"]["--section"]
|
["-c"]["--section"]
|
||||||
( "specify section to run" )
|
( "specify section to run" )
|
||||||
+ Opt( setVerbosity, "quiet|normal|high" )
|
| Opt( setVerbosity, "quiet|normal|high" )
|
||||||
["-v"]["--verbosity"]
|
["-v"]["--verbosity"]
|
||||||
( "set output verbosity" )
|
( "set output verbosity" )
|
||||||
+ Opt( config.listTestNamesOnly )
|
| Opt( config.listTestNamesOnly )
|
||||||
["--list-test-names-only"]
|
["--list-test-names-only"]
|
||||||
( "list all/matching test cases names only" )
|
( "list all/matching test cases names only" )
|
||||||
+ Opt( config.listReporters )
|
| Opt( config.listReporters )
|
||||||
["--list-reporters"]
|
["--list-reporters"]
|
||||||
( "list all reporters" )
|
( "list all reporters" )
|
||||||
+ Opt( setTestOrder, "decl|lex|rand" )
|
| Opt( setTestOrder, "decl|lex|rand" )
|
||||||
["--order"]
|
["--order"]
|
||||||
( "test case order (defaults to decl)" )
|
( "test case order (defaults to decl)" )
|
||||||
+ Opt( setRngSeed, "'time'|number" )
|
| Opt( setRngSeed, "'time'|number" )
|
||||||
["--rng-seed"]
|
["--rng-seed"]
|
||||||
( "set a specific seed for random numbers" )
|
( "set a specific seed for random numbers" )
|
||||||
+ Opt( setColourUsage, "yes|no" )
|
| Opt( setColourUsage, "yes|no" )
|
||||||
["--use-colour"]
|
["--use-colour"]
|
||||||
( "should output be colourised" )
|
( "should output be colourised" )
|
||||||
+ Opt( config.libIdentify )
|
| Opt( config.libIdentify )
|
||||||
["--libidentify"]
|
["--libidentify"]
|
||||||
( "report name and version according to libidentify standard" )
|
( "report name and version according to libidentify standard" )
|
||||||
+ Opt( setWaitForKeypress, "start|exit|both" )
|
| Opt( setWaitForKeypress, "start|exit|both" )
|
||||||
["--wait-for-keypress"]
|
["--wait-for-keypress"]
|
||||||
( "waits for a keypress before exiting" )
|
( "waits for a keypress before exiting" )
|
||||||
+ Opt( config.benchmarkResolutionMultiple, "multiplier" )
|
| Opt( config.benchmarkResolutionMultiple, "multiplier" )
|
||||||
["--benchmark-resolution-multiple"]
|
["--benchmark-resolution-multiple"]
|
||||||
( "multiple of clock resolution to run benchmarks" )
|
( "multiple of clock resolution to run benchmarks" )
|
||||||
|
|
||||||
+ Arg( config.testsOrTags, "test name|pattern|tags" )
|
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
||||||
( "which test or tests to use" );
|
( "which test or tests to use" );
|
||||||
|
|
||||||
return cli;
|
return cli;
|
||||||
|
@@ -29,14 +29,6 @@ namespace Catch {
|
|||||||
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
|
return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void seedRng( IConfig const& config ) {
|
|
||||||
if( config.rngSeed() != 0 )
|
|
||||||
std::srand( config.rngSeed() );
|
|
||||||
}
|
|
||||||
unsigned int rngSeed() {
|
|
||||||
return getCurrentContext().getConfig()->rngSeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
|
||||||
#ifndef __GNUG__
|
#ifndef __GNUG__
|
||||||
os << info.file << '(' << info.line << ')';
|
os << info.file << '(' << info.line << ')';
|
||||||
@@ -54,4 +46,7 @@ namespace Catch {
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonCopyable::NonCopyable() = default;
|
||||||
|
NonCopyable::~NonCopyable() = default;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -18,17 +18,12 @@
|
|||||||
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
|
|
||||||
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
|
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct IConfig;
|
|
||||||
|
|
||||||
struct CaseSensitive { enum Choice {
|
struct CaseSensitive { enum Choice {
|
||||||
Yes,
|
Yes,
|
||||||
No
|
No
|
||||||
@@ -41,7 +36,7 @@ namespace Catch {
|
|||||||
NonCopyable& operator = ( NonCopyable && ) = delete;
|
NonCopyable& operator = ( NonCopyable && ) = delete;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NonCopyable() {}
|
NonCopyable();
|
||||||
virtual ~NonCopyable();
|
virtual ~NonCopyable();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,9 +65,6 @@ namespace Catch {
|
|||||||
bool alwaysTrue();
|
bool alwaysTrue();
|
||||||
bool alwaysFalse();
|
bool alwaysFalse();
|
||||||
|
|
||||||
void seedRng( IConfig const& config );
|
|
||||||
unsigned int rngSeed();
|
|
||||||
|
|
||||||
// Use this in variadic streaming macros to allow
|
// Use this in variadic streaming macros to allow
|
||||||
// >> +StreamEndStop
|
// >> +StreamEndStop
|
||||||
// as well as
|
// as well as
|
||||||
|
@@ -35,11 +35,11 @@
|
|||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
|
|
||||||
|
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
|
||||||
_Pragma( "clang diagnostic push" ) \
|
_Pragma( "clang diagnostic push" ) \
|
||||||
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
|
_Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
_Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
|
||||||
|
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
_Pragma( "clang diagnostic pop" )
|
_Pragma( "clang diagnostic pop" )
|
||||||
|
|
||||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
|
||||||
@@ -80,23 +80,28 @@
|
|||||||
// Visual C++
|
// Visual C++
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
|
// Universal Windows platform does not support SEH
|
||||||
|
// Or console colours (or console at all...)
|
||||||
|
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||||
|
# define CATCH_CONFIG_COLOUR_NONE
|
||||||
|
# else
|
||||||
|
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// All supported compilers support COUNTER macro,
|
// Use of __COUNTER__ is suppressed during code analysis in
|
||||||
//but user still might want to turn it off
|
// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
|
||||||
#define CATCH_INTERNAL_CONFIG_COUNTER
|
// handled by it.
|
||||||
|
// Otherwise all supported compilers support COUNTER macro,
|
||||||
|
// but user still might want to turn it off
|
||||||
|
#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
|
||||||
|
#define CATCH_INTERNAL_CONFIG_COUNTER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
|
||||||
// Now set the actual defines based on the above + anything the user has configured
|
|
||||||
|
|
||||||
// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
|
|
||||||
// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
|
|
||||||
// This does not affect compilation
|
|
||||||
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
|
|
||||||
# define CATCH_CONFIG_COUNTER
|
# define CATCH_CONFIG_COUNTER
|
||||||
#endif
|
#endif
|
||||||
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
|
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
|
||||||
@@ -111,9 +116,9 @@
|
|||||||
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS)
|
#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
|
||||||
# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
|
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@@ -8,9 +8,12 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_test_spec_parser.hpp"
|
#include "catch_test_spec_parser.h"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
|
// Libstdc++ doesn't like incomplete classes for unique_ptr
|
||||||
|
#include "catch_stream.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -59,7 +62,6 @@ namespace Catch {
|
|||||||
|
|
||||||
|
|
||||||
class Config : public IConfig {
|
class Config : public IConfig {
|
||||||
virtual void dummy();
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Config() = default;
|
Config() = default;
|
||||||
|
@@ -6,13 +6,22 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_console_colour.hpp"
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "catch_console_colour.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_errno_guard.h"
|
#include "catch_errno_guard.h"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_platform.h"
|
#include "catch_platform.h"
|
||||||
|
#include "catch_debugger.h"
|
||||||
|
#include "catch_windows_h_proxy.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -45,8 +54,6 @@ namespace Catch {
|
|||||||
|
|
||||||
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
|
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
|
||||||
|
|
||||||
#include "catch_windows_h_proxy.h"
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -149,6 +156,13 @@ namespace {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool useColourOnPlatform() {
|
||||||
|
return
|
||||||
|
#ifdef CATCH_PLATFORM_MAC
|
||||||
|
!isDebuggerActive() &&
|
||||||
|
#endif
|
||||||
|
isatty(STDOUT_FILENO);
|
||||||
|
}
|
||||||
IColourImpl* platformColourInstance() {
|
IColourImpl* platformColourInstance() {
|
||||||
ErrnoGuard guard;
|
ErrnoGuard guard;
|
||||||
IConfigPtr config = getCurrentContext().getConfig();
|
IConfigPtr config = getCurrentContext().getConfig();
|
||||||
@@ -156,7 +170,7 @@ namespace {
|
|||||||
? config->useColour()
|
? config->useColour()
|
||||||
: UseColour::Auto;
|
: UseColour::Auto;
|
||||||
if( colourMode == UseColour::Auto )
|
if( colourMode == UseColour::Auto )
|
||||||
colourMode = isatty(STDOUT_FILENO)
|
colourMode = useColourOnPlatform()
|
||||||
? UseColour::Yes
|
? UseColour::Yes
|
||||||
: UseColour::No;
|
: UseColour::No;
|
||||||
return colourMode == UseColour::Yes
|
return colourMode == UseColour::Yes
|
||||||
@@ -202,3 +216,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -24,6 +24,8 @@ namespace Catch {
|
|||||||
return m_config;
|
return m_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~Context() override;
|
||||||
|
|
||||||
public: // IMutableContext
|
public: // IMutableContext
|
||||||
virtual void setResultCapture( IResultCapture* resultCapture ) override {
|
virtual void setResultCapture( IResultCapture* resultCapture ) override {
|
||||||
m_resultCapture = resultCapture;
|
m_resultCapture = resultCapture;
|
||||||
@@ -59,4 +61,7 @@ namespace Catch {
|
|||||||
delete currentContext;
|
delete currentContext;
|
||||||
currentContext = nullptr;
|
currentContext = nullptr;
|
||||||
}
|
}
|
||||||
|
IContext::~IContext() = default;
|
||||||
|
IMutableContext::~IMutableContext() = default;
|
||||||
|
Context::~Context() = default;
|
||||||
}
|
}
|
||||||
|
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
class TestCase;
|
|
||||||
class Stream;
|
|
||||||
struct IResultCapture;
|
struct IResultCapture;
|
||||||
struct IRunner;
|
struct IRunner;
|
||||||
struct IConfig;
|
struct IConfig;
|
||||||
@@ -22,7 +20,7 @@ namespace Catch {
|
|||||||
|
|
||||||
struct IContext
|
struct IContext
|
||||||
{
|
{
|
||||||
virtual ~IContext() = default;
|
virtual ~IContext();
|
||||||
|
|
||||||
virtual IResultCapture* getResultCapture() = 0;
|
virtual IResultCapture* getResultCapture() = 0;
|
||||||
virtual IRunner* getRunner() = 0;
|
virtual IRunner* getRunner() = 0;
|
||||||
@@ -31,7 +29,7 @@ namespace Catch {
|
|||||||
|
|
||||||
struct IMutableContext : IContext
|
struct IMutableContext : IContext
|
||||||
{
|
{
|
||||||
virtual ~IMutableContext() = default;
|
virtual ~IMutableContext();
|
||||||
virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
|
virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
|
||||||
virtual void setRunner( IRunner* runner ) = 0;
|
virtual void setRunner( IRunner* runner ) = 0;
|
||||||
virtual void setConfig( IConfigPtr const& config ) = 0;
|
virtual void setConfig( IConfigPtr const& config ) = 0;
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
namespace Catch{
|
namespace Catch {
|
||||||
|
|
||||||
// The following function is taken directly from the following technical note:
|
// The following function is taken directly from the following technical note:
|
||||||
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
|
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
int mib[4];
|
int mib[4];
|
||||||
struct kinfo_proc info;
|
struct kinfo_proc info;
|
||||||
size_t size;
|
std::size_t size;
|
||||||
|
|
||||||
// Initialize the flags so that, if sysctl fails for some bizarre
|
// Initialize the flags so that, if sysctl fails for some bizarre
|
||||||
// reason, we get a predictable result.
|
// reason, we get a predictable result.
|
||||||
|
@@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) {
|
ITransientExpression::~ITransientExpression() = default;
|
||||||
|
|
||||||
|
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
|
||||||
if( lhs.size() + rhs.size() < 40 &&
|
if( lhs.size() + rhs.size() < 40 &&
|
||||||
lhs.find('\n') == std::string::npos &&
|
lhs.find('\n') == std::string::npos &&
|
||||||
rhs.find('\n') == std::string::npos )
|
rhs.find('\n') == std::string::npos )
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
|
||||||
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
|
#pragma warning(disable:4018) // more "signed/unsigned mismatch"
|
||||||
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
|
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
|
||||||
|
#pragma warning(disable:4180) // qualifier applied to function type has no meaning
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@@ -29,16 +30,16 @@ namespace Catch {
|
|||||||
|
|
||||||
// We don't actually need a virtual destructore, but many static analysers
|
// We don't actually need a virtual destructore, but many static analysers
|
||||||
// complain if it's not here :-(
|
// complain if it's not here :-(
|
||||||
virtual ~ITransientExpression() = default;
|
virtual ~ITransientExpression();
|
||||||
};
|
};
|
||||||
|
|
||||||
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs );
|
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
||||||
|
|
||||||
template<typename LhsT, typename RhsT>
|
template<typename LhsT, typename RhsT>
|
||||||
class BinaryExpr : public ITransientExpression {
|
class BinaryExpr : public ITransientExpression {
|
||||||
bool m_result;
|
bool m_result;
|
||||||
LhsT m_lhs;
|
LhsT m_lhs;
|
||||||
std::string m_op;
|
StringRef m_op;
|
||||||
RhsT m_rhs;
|
RhsT m_rhs;
|
||||||
|
|
||||||
auto isBinaryExpression() const -> bool override { return true; }
|
auto isBinaryExpression() const -> bool override { return true; }
|
||||||
@@ -50,8 +51,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs )
|
BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
||||||
: m_result( comparisionResult ),
|
: m_result( comparisonResult ),
|
||||||
m_lhs( lhs ),
|
m_lhs( lhs ),
|
||||||
m_op( op ),
|
m_op( op ),
|
||||||
m_rhs( rhs )
|
m_rhs( rhs )
|
||||||
@@ -76,26 +77,26 @@ namespace Catch {
|
|||||||
|
|
||||||
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
|
// Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
|
||||||
template<typename LhsT, typename RhsT>
|
template<typename LhsT, typename RhsT>
|
||||||
auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast<LhsT&>( lhs ) == rhs; };
|
auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; };
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); };
|
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); };
|
auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; };
|
auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; };
|
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
|
||||||
|
|
||||||
template<typename LhsT, typename RhsT>
|
template<typename LhsT, typename RhsT>
|
||||||
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast<LhsT&>( lhs ) != rhs; };
|
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; };
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); };
|
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); };
|
auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; };
|
auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; };
|
auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
|
||||||
|
|
||||||
|
|
||||||
template<typename LhsT>
|
template<typename LhsT>
|
||||||
@@ -105,36 +106,36 @@ namespace Catch {
|
|||||||
ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator == ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs );
|
return BinaryExpr<LhsT, RhsT const&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs );
|
||||||
}
|
}
|
||||||
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
||||||
return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs );
|
return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator != ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs );
|
return BinaryExpr<LhsT, RhsT const&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs );
|
||||||
}
|
}
|
||||||
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
||||||
return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs );
|
return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator > ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT&>( m_lhs > rhs, m_lhs, ">", rhs );
|
return BinaryExpr<LhsT, RhsT const&>( m_lhs > rhs, m_lhs, ">", rhs );
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator < ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT&>( m_lhs < rhs, m_lhs, "<", rhs );
|
return BinaryExpr<LhsT, RhsT const&>( m_lhs < rhs, m_lhs, "<", rhs );
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator >= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT&>( m_lhs >= rhs, m_lhs, ">=", rhs );
|
return BinaryExpr<LhsT, RhsT const&>( m_lhs >= rhs, m_lhs, ">=", rhs );
|
||||||
}
|
}
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
auto operator <= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
|
||||||
return BinaryExpr<LhsT, RhsT&>( m_lhs <= rhs, m_lhs, "<=", rhs );
|
return BinaryExpr<LhsT, RhsT const&>( m_lhs <= rhs, m_lhs, "<=", rhs );
|
||||||
}
|
}
|
||||||
|
|
||||||
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
||||||
@@ -150,10 +151,6 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Decomposer {
|
struct Decomposer {
|
||||||
template<typename T>
|
|
||||||
auto operator <= ( T& lhs ) -> ExprLhs<T&> {
|
|
||||||
return ExprLhs<T&>( lhs );
|
|
||||||
}
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
|
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
|
||||||
return ExprLhs<T const&>( lhs );
|
return ExprLhs<T const&>( lhs );
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_session.h"
|
||||||
|
|
||||||
#ifndef __OBJC__
|
#ifndef __OBJC__
|
||||||
|
|
||||||
#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
|
||||||
@@ -30,7 +32,7 @@ int main (int argc, char * const argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Catch::registerTestMethods();
|
Catch::registerTestMethods();
|
||||||
int result = Catch::Session().run( argc, (char* const*)argv );
|
int result = Catch::Session().run( argc, (char**)argv );
|
||||||
|
|
||||||
#if !CATCH_ARC_ENABLED
|
#if !CATCH_ARC_ENABLED
|
||||||
[pool drain];
|
[pool drain];
|
||||||
|
@@ -30,14 +30,14 @@ namespace Catch {
|
|||||||
return tryTranslators();
|
return tryTranslators();
|
||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (NSException *exception) {
|
||||||
return Catch::toString( [exception description] );
|
return Catch::Detail::stringify( [exception description] );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return tryTranslators();
|
return tryTranslators();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch( TestFailureException& ) {
|
catch( TestFailureException& ) {
|
||||||
throw;
|
std::rethrow_exception(std::current_exception());
|
||||||
}
|
}
|
||||||
catch( std::exception& ex ) {
|
catch( std::exception& ex ) {
|
||||||
return ex.what();
|
return ex.what();
|
||||||
@@ -55,7 +55,7 @@ namespace Catch {
|
|||||||
|
|
||||||
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
std::string ExceptionTranslatorRegistry::tryTranslators() const {
|
||||||
if( m_translators.empty() )
|
if( m_translators.empty() )
|
||||||
throw;
|
std::rethrow_exception(std::current_exception());
|
||||||
else
|
else
|
||||||
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
|
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED
|
||||||
|
|
||||||
#include "../reporters/catch_reporter_bases.hpp"
|
#include "../reporters/catch_reporter_bases.hpp"
|
||||||
|
#include "catch_console_colour.h"
|
||||||
#include "catch_reporter_registrars.hpp"
|
#include "catch_reporter_registrars.hpp"
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED
|
||||||
|
@@ -12,16 +12,12 @@
|
|||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_interfaces_capture.h"
|
#include "catch_interfaces_capture.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace {
|
||||||
|
|
||||||
// Report the error condition
|
// Report the error condition
|
||||||
void reportFatal( std::string const& message ) {
|
void reportFatal( char const * const message ) {
|
||||||
IContext& context = Catch::getCurrentContext();
|
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
|
||||||
IResultCapture* resultCapture = context.getResultCapture();
|
|
||||||
resultCapture->handleFatalErrorCondition( message );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // namespace Catch
|
|
||||||
|
|
||||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||||
|
|
||||||
@@ -39,7 +35,7 @@ namespace Catch {
|
|||||||
// There is no 1-1 mapping between signals and windows exceptions.
|
// There is no 1-1 mapping between signals and windows exceptions.
|
||||||
// Windows can easily distinguish between SO and SigSegV,
|
// Windows can easily distinguish between SO and SigSegV,
|
||||||
// but SigInt, SigTerm, etc are handled differently.
|
// but SigInt, SigTerm, etc are handled differently.
|
||||||
SignalDefs signalDefs[] = {
|
static SignalDefs signalDefs[] = {
|
||||||
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
|
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
|
||||||
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
|
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
|
||||||
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
|
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
|
||||||
@@ -111,7 +107,7 @@ namespace Catch {
|
|||||||
int id;
|
int id;
|
||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
SignalDefs signalDefs[] = {
|
static SignalDefs signalDefs[] = {
|
||||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||||
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
||||||
{ SIGFPE, "SIGFPE - Floating point error signal" },
|
{ SIGFPE, "SIGFPE - Floating point error signal" },
|
||||||
@@ -122,7 +118,7 @@ namespace Catch {
|
|||||||
|
|
||||||
|
|
||||||
void FatalConditionHandler::handleSignal( int sig ) {
|
void FatalConditionHandler::handleSignal( int sig ) {
|
||||||
std::string name = "<unknown signal>";
|
char const * name = "<unknown signal>";
|
||||||
for (auto const& def : signalDefs) {
|
for (auto const& def : signalDefs) {
|
||||||
if (sig == def.id) {
|
if (sig == def.id) {
|
||||||
name = def.name;
|
name = def.name;
|
||||||
|
@@ -13,12 +13,6 @@
|
|||||||
#include "catch_platform.h"
|
#include "catch_platform.h"
|
||||||
#include "catch_compiler_capabilities.h"
|
#include "catch_compiler_capabilities.h"
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
// Report the error condition
|
|
||||||
void reportFatal( std::string const& message );
|
|
||||||
|
|
||||||
} // namespace Catch
|
|
||||||
|
|
||||||
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||||
#include "catch_windows_h_proxy.h"
|
#include "catch_windows_h_proxy.h"
|
||||||
|
@@ -8,55 +8,22 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
|
||||||
|
|
||||||
// Collect all the implementation files together here
|
|
||||||
// These are the equivalent of what would usually be cpp files
|
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Keep these here for external reporters
|
||||||
|
#include "catch_test_spec.h"
|
||||||
|
#include "catch_test_case_tracker.h"
|
||||||
|
|
||||||
#include "internal/catch_notimplemented_exception.h"
|
#include "catch_leak_detector.h"
|
||||||
|
|
||||||
|
|
||||||
// Temporary hack to fix separately provided reporters
|
|
||||||
#include "../reporters/catch_reporter_bases.hpp"
|
|
||||||
#include "catch_reporter_registrars.hpp"
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "internal/catch_leak_detector.h"
|
|
||||||
|
|
||||||
|
|
||||||
#include "../catch_session.hpp"
|
|
||||||
#include "catch_test_spec.hpp"
|
|
||||||
#include "catch_test_case_tracker.hpp"
|
|
||||||
|
|
||||||
// Cpp files will be included in the single-header file here
|
// Cpp files will be included in the single-header file here
|
||||||
// ~*~* CATCH_CPP_STITCH_PLACE *~*~
|
// ~*~* CATCH_CPP_STITCH_PLACE *~*~
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
LeakDetector leakDetector;
|
LeakDetector leakDetector;
|
||||||
|
|
||||||
// These are all here to avoid warnings about not having any out of line
|
|
||||||
// virtual methods
|
|
||||||
NonCopyable::~NonCopyable() {}
|
|
||||||
IStream::~IStream() noexcept {}
|
|
||||||
FileStream::~FileStream() noexcept {}
|
|
||||||
CoutStream::~CoutStream() noexcept {}
|
|
||||||
DebugOutStream::~DebugOutStream() noexcept {}
|
|
||||||
StreamBufBase::~StreamBufBase() noexcept {}
|
|
||||||
IResultCapture::~IResultCapture() {}
|
|
||||||
ITestInvoker::~ITestInvoker() {}
|
|
||||||
ITestCaseRegistry::~ITestCaseRegistry() {}
|
|
||||||
IRegistryHub::~IRegistryHub() {}
|
|
||||||
IMutableRegistryHub::~IMutableRegistryHub() {}
|
|
||||||
IExceptionTranslator::~IExceptionTranslator() {}
|
|
||||||
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
|
|
||||||
IRunner::~IRunner() {}
|
|
||||||
IConfig::~IConfig() {}
|
|
||||||
|
|
||||||
void Config::dummy() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
|
5
include/internal/catch_interfaces_capture.cpp
Normal file
5
include/internal/catch_interfaces_capture.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "catch_interfaces_capture.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
IResultCapture::~IResultCapture() = default;
|
||||||
|
}
|
@@ -10,15 +10,15 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
class TestCase;
|
|
||||||
class AssertionResult;
|
class AssertionResult;
|
||||||
struct AssertionInfo;
|
struct AssertionInfo;
|
||||||
struct SectionInfo;
|
struct SectionInfo;
|
||||||
struct SectionEndInfo;
|
struct SectionEndInfo;
|
||||||
struct MessageInfo;
|
struct MessageInfo;
|
||||||
class ScopedMessageBuilder;
|
|
||||||
struct Counts;
|
struct Counts;
|
||||||
struct BenchmarkInfo;
|
struct BenchmarkInfo;
|
||||||
struct BenchmarkStats;
|
struct BenchmarkStats;
|
||||||
@@ -45,7 +45,7 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual void exceptionEarlyReported() = 0;
|
virtual void exceptionEarlyReported() = 0;
|
||||||
|
|
||||||
virtual void handleFatalErrorCondition( std::string const& message ) = 0;
|
virtual void handleFatalErrorCondition( StringRef message ) = 0;
|
||||||
|
|
||||||
virtual bool lastAssertionPassed() = 0;
|
virtual bool lastAssertionPassed() = 0;
|
||||||
virtual void assertionPassed() = 0;
|
virtual void assertionPassed() = 0;
|
||||||
|
5
include/internal/catch_interfaces_config.cpp
Normal file
5
include/internal/catch_interfaces_config.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "internal/catch_interfaces_config.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
IConfig::~IConfig() = default;
|
||||||
|
}
|
6
include/internal/catch_interfaces_exception.cpp
Normal file
6
include/internal/catch_interfaces_exception.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "internal/catch_interfaces_exception.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
IExceptionTranslator::~IExceptionTranslator() = default;
|
||||||
|
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
|
||||||
|
}
|
@@ -15,6 +15,7 @@
|
|||||||
static std::string translatorName( signature )
|
static std::string translatorName( signature )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ namespace Catch {
|
|||||||
std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
|
std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
|
||||||
try {
|
try {
|
||||||
if( it == itEnd )
|
if( it == itEnd )
|
||||||
throw;
|
std::rethrow_exception(std::current_exception());
|
||||||
else
|
else
|
||||||
return (*it)->translate( it+1, itEnd );
|
return (*it)->translate( it+1, itEnd );
|
||||||
}
|
}
|
||||||
|
6
include/internal/catch_interfaces_registry_hub.cpp
Normal file
6
include/internal/catch_interfaces_registry_hub.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "internal/catch_interfaces_registry_hub.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
IRegistryHub::~IRegistryHub() = default;
|
||||||
|
IMutableRegistryHub::~IMutableRegistryHub() = default;
|
||||||
|
}
|
@@ -50,6 +50,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssertionStats::~AssertionStats() = default;
|
||||||
|
|
||||||
SectionStats::SectionStats( SectionInfo const& _sectionInfo,
|
SectionStats::SectionStats( SectionInfo const& _sectionInfo,
|
||||||
Counts const& _assertions,
|
Counts const& _assertions,
|
||||||
double _durationInSeconds,
|
double _durationInSeconds,
|
||||||
@@ -60,6 +62,8 @@ namespace Catch {
|
|||||||
missingAssertions( _missingAssertions )
|
missingAssertions( _missingAssertions )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
SectionStats::~SectionStats() = default;
|
||||||
|
|
||||||
|
|
||||||
TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
|
TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
|
||||||
Totals const& _totals,
|
Totals const& _totals,
|
||||||
@@ -73,6 +77,8 @@ namespace Catch {
|
|||||||
aborting( _aborting )
|
aborting( _aborting )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
TestCaseStats::~TestCaseStats() = default;
|
||||||
|
|
||||||
|
|
||||||
TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
|
TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
|
||||||
Totals const& _totals,
|
Totals const& _totals,
|
||||||
@@ -87,6 +93,8 @@ namespace Catch {
|
|||||||
aborting( false )
|
aborting( false )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
TestGroupStats::~TestGroupStats() = default;
|
||||||
|
|
||||||
TestRunStats::TestRunStats( TestRunInfo const& _runInfo,
|
TestRunStats::TestRunStats( TestRunInfo const& _runInfo,
|
||||||
Totals const& _totals,
|
Totals const& _totals,
|
||||||
bool _aborting )
|
bool _aborting )
|
||||||
@@ -95,9 +103,14 @@ namespace Catch {
|
|||||||
aborting( _aborting )
|
aborting( _aborting )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
TestRunStats::~TestRunStats() = default;
|
||||||
|
|
||||||
|
void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
|
||||||
bool IStreamingReporter::isMulti() const { return false; }
|
bool IStreamingReporter::isMulti() const { return false; }
|
||||||
|
|
||||||
|
IReporterFactory::~IReporterFactory() = default;
|
||||||
|
IReporterRegistry::~IReporterRegistry() = default;
|
||||||
|
|
||||||
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
|
void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
|
||||||
|
|
||||||
if( !existingReporter ) {
|
if( !existingReporter ) {
|
||||||
|
@@ -11,11 +11,12 @@
|
|||||||
#include "catch_section_info.h"
|
#include "catch_section_info.h"
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
#include "catch_config.hpp"
|
#include "catch_config.hpp"
|
||||||
#include "catch_totals.hpp"
|
#include "catch_totals.h"
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
#include "catch_assertionresult.h"
|
#include "catch_assertionresult.h"
|
||||||
#include "catch_message.h"
|
#include "catch_message.h"
|
||||||
#include "catch_option.hpp"
|
#include "catch_option.hpp"
|
||||||
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -80,7 +81,7 @@ namespace Catch {
|
|||||||
AssertionStats( AssertionStats && ) = default;
|
AssertionStats( AssertionStats && ) = default;
|
||||||
AssertionStats& operator = ( AssertionStats const& ) = default;
|
AssertionStats& operator = ( AssertionStats const& ) = default;
|
||||||
AssertionStats& operator = ( AssertionStats && ) = default;
|
AssertionStats& operator = ( AssertionStats && ) = default;
|
||||||
virtual ~AssertionStats() = default;
|
virtual ~AssertionStats();
|
||||||
|
|
||||||
AssertionResult assertionResult;
|
AssertionResult assertionResult;
|
||||||
std::vector<MessageInfo> infoMessages;
|
std::vector<MessageInfo> infoMessages;
|
||||||
@@ -96,7 +97,7 @@ namespace Catch {
|
|||||||
SectionStats( SectionStats && ) = default;
|
SectionStats( SectionStats && ) = default;
|
||||||
SectionStats& operator = ( SectionStats const& ) = default;
|
SectionStats& operator = ( SectionStats const& ) = default;
|
||||||
SectionStats& operator = ( SectionStats && ) = default;
|
SectionStats& operator = ( SectionStats && ) = default;
|
||||||
virtual ~SectionStats() = default;
|
virtual ~SectionStats();
|
||||||
|
|
||||||
SectionInfo sectionInfo;
|
SectionInfo sectionInfo;
|
||||||
Counts assertions;
|
Counts assertions;
|
||||||
@@ -115,7 +116,7 @@ namespace Catch {
|
|||||||
TestCaseStats( TestCaseStats && ) = default;
|
TestCaseStats( TestCaseStats && ) = default;
|
||||||
TestCaseStats& operator = ( TestCaseStats const& ) = default;
|
TestCaseStats& operator = ( TestCaseStats const& ) = default;
|
||||||
TestCaseStats& operator = ( TestCaseStats && ) = default;
|
TestCaseStats& operator = ( TestCaseStats && ) = default;
|
||||||
virtual ~TestCaseStats() = default;
|
virtual ~TestCaseStats();
|
||||||
|
|
||||||
TestCaseInfo testInfo;
|
TestCaseInfo testInfo;
|
||||||
Totals totals;
|
Totals totals;
|
||||||
@@ -134,7 +135,7 @@ namespace Catch {
|
|||||||
TestGroupStats( TestGroupStats && ) = default;
|
TestGroupStats( TestGroupStats && ) = default;
|
||||||
TestGroupStats& operator = ( TestGroupStats const& ) = default;
|
TestGroupStats& operator = ( TestGroupStats const& ) = default;
|
||||||
TestGroupStats& operator = ( TestGroupStats && ) = default;
|
TestGroupStats& operator = ( TestGroupStats && ) = default;
|
||||||
virtual ~TestGroupStats() = default;
|
virtual ~TestGroupStats();
|
||||||
|
|
||||||
GroupInfo groupInfo;
|
GroupInfo groupInfo;
|
||||||
Totals totals;
|
Totals totals;
|
||||||
@@ -150,7 +151,7 @@ namespace Catch {
|
|||||||
TestRunStats( TestRunStats && ) = default;
|
TestRunStats( TestRunStats && ) = default;
|
||||||
TestRunStats& operator = ( TestRunStats const& ) = default;
|
TestRunStats& operator = ( TestRunStats const& ) = default;
|
||||||
TestRunStats& operator = ( TestRunStats && ) = default;
|
TestRunStats& operator = ( TestRunStats && ) = default;
|
||||||
virtual ~TestRunStats() = default;
|
virtual ~TestRunStats();
|
||||||
|
|
||||||
TestRunInfo runInfo;
|
TestRunInfo runInfo;
|
||||||
Totals totals;
|
Totals totals;
|
||||||
@@ -162,10 +163,9 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
struct BenchmarkStats {
|
struct BenchmarkStats {
|
||||||
BenchmarkInfo info;
|
BenchmarkInfo info;
|
||||||
size_t iterations;
|
std::size_t iterations;
|
||||||
uint64_t elapsedTimeInNanoseconds;
|
uint64_t elapsedTimeInNanoseconds;
|
||||||
};
|
};
|
||||||
class MultipleReporters;
|
|
||||||
|
|
||||||
struct IStreamingReporter {
|
struct IStreamingReporter {
|
||||||
virtual ~IStreamingReporter() = default;
|
virtual ~IStreamingReporter() = default;
|
||||||
@@ -202,12 +202,15 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
|
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
|
||||||
|
|
||||||
|
// Default empty implementation provided
|
||||||
|
virtual void fatalErrorEncountered( StringRef name );
|
||||||
|
|
||||||
virtual bool isMulti() const;
|
virtual bool isMulti() const;
|
||||||
};
|
};
|
||||||
using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
|
using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
|
||||||
|
|
||||||
struct IReporterFactory {
|
struct IReporterFactory {
|
||||||
virtual ~IReporterFactory() = default;
|
virtual ~IReporterFactory();
|
||||||
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
|
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
|
||||||
virtual std::string getDescription() const = 0;
|
virtual std::string getDescription() const = 0;
|
||||||
};
|
};
|
||||||
@@ -217,7 +220,7 @@ namespace Catch {
|
|||||||
using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
|
using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
|
||||||
using Listeners = std::vector<IReporterFactoryPtr>;
|
using Listeners = std::vector<IReporterFactoryPtr>;
|
||||||
|
|
||||||
virtual ~IReporterRegistry() = default;
|
virtual ~IReporterRegistry();
|
||||||
virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
|
virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
|
||||||
virtual FactoryMap const& getFactories() const = 0;
|
virtual FactoryMap const& getFactories() const = 0;
|
||||||
virtual Listeners const& getListeners() const = 0;
|
virtual Listeners const& getListeners() const = 0;
|
||||||
|
5
include/internal/catch_interfaces_runner.cpp
Normal file
5
include/internal/catch_interfaces_runner.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "internal/catch_interfaces_runner.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
IRunner::~IRunner() = default;
|
||||||
|
}
|
@@ -9,7 +9,6 @@
|
|||||||
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
class TestCase;
|
|
||||||
|
|
||||||
struct IRunner {
|
struct IRunner {
|
||||||
virtual ~IRunner();
|
virtual ~IRunner();
|
||||||
|
6
include/internal/catch_interfaces_testcase.cpp
Normal file
6
include/internal/catch_interfaces_testcase.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "internal/catch_interfaces_testcase.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
ITestInvoker::~ITestInvoker() = default;
|
||||||
|
ITestCaseRegistry::~ITestCaseRegistry() = default;
|
||||||
|
}
|
@@ -15,8 +15,8 @@
|
|||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_text.h"
|
#include "catch_text.h"
|
||||||
|
|
||||||
#include "catch_console_colour.hpp"
|
#include "catch_console_colour.h"
|
||||||
#include "catch_test_spec_parser.hpp"
|
#include "catch_test_spec_parser.h"
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_matchers.hpp"
|
#include "catch_matchers.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
@@ -17,6 +17,8 @@ namespace Matchers {
|
|||||||
return m_cachedToString;
|
return m_cachedToString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MatcherUntypedBase::~MatcherUntypedBase() = default;
|
||||||
|
|
||||||
} // namespace Impl
|
} // namespace Impl
|
||||||
} // namespace Matchers
|
} // namespace Matchers
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ namespace Matchers {
|
|||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~MatcherUntypedBase() = default;
|
virtual ~MatcherUntypedBase();
|
||||||
virtual std::string describe() const = 0;
|
virtual std::string describe() const = 0;
|
||||||
mutable std::string m_cachedToString;
|
mutable std::string m_cachedToString;
|
||||||
};
|
};
|
||||||
@@ -148,31 +148,6 @@ namespace Matchers {
|
|||||||
|
|
||||||
} // namespace Impl
|
} // namespace Impl
|
||||||
|
|
||||||
|
|
||||||
// The following functions create the actual matcher objects.
|
|
||||||
// This allows the types to be inferred
|
|
||||||
// - deprecated: prefer ||, && and !
|
|
||||||
template<typename T>
|
|
||||||
Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
|
|
||||||
return Impl::MatchNotOf<T>( underlyingMatcher );
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
|
|
||||||
return Impl::MatchAllOf<T>() && m1 && m2;
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
|
|
||||||
return Impl::MatchAllOf<T>() && m1 && m2 && m3;
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
|
|
||||||
return Impl::MatchAnyOf<T>() || m1 || m2;
|
|
||||||
}
|
|
||||||
template<typename T>
|
|
||||||
Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
|
|
||||||
return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Matchers
|
} // namespace Matchers
|
||||||
|
|
||||||
using namespace Matchers;
|
using namespace Matchers;
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_matchers.hpp"
|
#include "catch_matchers.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_matchers.hpp"
|
#include "catch_matchers.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
@@ -78,7 +78,7 @@ namespace Matchers {
|
|||||||
// - then just call that directly
|
// - then just call that directly
|
||||||
if (m_comparator.size() != v.size())
|
if (m_comparator.size() != v.size())
|
||||||
return false;
|
return false;
|
||||||
for (size_t i = 0; i < v.size(); ++i)
|
for (std::size_t i = 0; i < v.size(); ++i)
|
||||||
if (m_comparator[i] != v[i])
|
if (m_comparator[i] != v[i])
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
@@ -21,9 +21,9 @@ namespace Catch {
|
|||||||
ResultWas::OfType _type );
|
ResultWas::OfType _type );
|
||||||
|
|
||||||
std::string macroName;
|
std::string macroName;
|
||||||
|
std::string message;
|
||||||
SourceLineInfo lineInfo;
|
SourceLineInfo lineInfo;
|
||||||
ResultWas::OfType type;
|
ResultWas::OfType type;
|
||||||
std::string message;
|
|
||||||
unsigned int sequence;
|
unsigned int sequence;
|
||||||
|
|
||||||
bool operator == ( MessageInfo const& other ) const;
|
bool operator == ( MessageInfo const& other ) const;
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Created by Phil on 5/8/2012.
|
|
||||||
* Copyright 2012 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 "catch_notimplemented_exception.h"
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << lineInfo << ": function ";
|
|
||||||
oss << "not implemented";
|
|
||||||
m_what = oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* NotImplementedException::what() const noexcept {
|
|
||||||
return m_what.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace Catch
|
|
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Created by Phil on 5/8/2012.
|
|
||||||
* Copyright 2012 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_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
|
|
||||||
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
|
|
||||||
|
|
||||||
#include "catch_common.h"
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
class NotImplementedException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NotImplementedException( SourceLineInfo const& lineInfo );
|
|
||||||
|
|
||||||
virtual ~NotImplementedException() noexcept = default;
|
|
||||||
|
|
||||||
virtual const char* what() const noexcept override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_what;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace Catch
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
|
|
@@ -18,6 +18,8 @@
|
|||||||
// in catch.hpp first to make sure they are included by the single
|
// in catch.hpp first to make sure they are included by the single
|
||||||
// header for non obj-usage
|
// header for non obj-usage
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
|
#include "catch_string_manip.h"
|
||||||
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// This protocol is really only here for (self) documenting purposes, since
|
// This protocol is really only here for (self) documenting purposes, since
|
||||||
@@ -70,8 +72,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t registerTestMethods() {
|
inline std::size_t registerTestMethods() {
|
||||||
size_t noTestMethods = 0;
|
std::size_t noTestMethods = 0;
|
||||||
int noClasses = objc_getClassList( nullptr, 0 );
|
int noClasses = objc_getClassList( nullptr, 0 );
|
||||||
|
|
||||||
Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
|
Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
|
||||||
@@ -91,7 +93,7 @@ namespace Catch {
|
|||||||
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
|
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
|
||||||
const char* className = class_getName( cls );
|
const char* className = class_getName( cls );
|
||||||
|
|
||||||
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
|
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) );
|
||||||
noTestMethods++;
|
noTestMethods++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +120,7 @@ namespace Catch {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* m_substr;
|
NSString* CATCH_ARC_STRONG m_substr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Equals : StringHolder {
|
struct Equals : StringHolder {
|
||||||
@@ -130,7 +132,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string describe() const override {
|
std::string describe() const override {
|
||||||
return "equals string: " + Catch::toString( m_substr );
|
return "equals string: " + Catch::Detail::stringify( m_substr );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string describe() const override {
|
std::string describe() const override {
|
||||||
return "contains string: " + Catch::toString( m_substr );
|
return "contains string: " + Catch::Detail::stringify( m_substr );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -156,7 +158,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string describe() const override {
|
std::string describe() const override {
|
||||||
return "starts with: " + Catch::toString( m_substr );
|
return "starts with: " + Catch::Detail::stringify( m_substr );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct EndsWith : StringHolder {
|
struct EndsWith : StringHolder {
|
||||||
@@ -168,7 +170,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string describe() const override {
|
std::string describe() const override {
|
||||||
return "ends with: " + Catch::toString( m_substr );
|
return "ends with: " + Catch::Detail::stringify( m_substr );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -196,15 +198,18 @@ namespace Catch {
|
|||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define OC_TEST_CASE( name, desc )\
|
#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
|
||||||
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
|
#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
|
||||||
{\
|
+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
|
||||||
|
{ \
|
||||||
return @ name; \
|
return @ name; \
|
||||||
}\
|
} \
|
||||||
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
|
+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
|
||||||
{ \
|
{ \
|
||||||
return @ desc; \
|
return @ desc; \
|
||||||
} \
|
} \
|
||||||
-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
|
-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
|
||||||
|
|
||||||
|
#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
|
||||||
|
31
include/internal/catch_random_number_generator.cpp
Normal file
31
include/internal/catch_random_number_generator.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 30/08/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 "catch_random_number_generator.h"
|
||||||
|
#include "catch_context.h"
|
||||||
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
void seedRng( IConfig const& config ) {
|
||||||
|
if( config.rngSeed() != 0 )
|
||||||
|
std::srand( config.rngSeed() );
|
||||||
|
}
|
||||||
|
unsigned int rngSeed() {
|
||||||
|
return getCurrentContext().getConfig()->rngSeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const {
|
||||||
|
return std::rand() % n;
|
||||||
|
}
|
||||||
|
RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const {
|
||||||
|
return std::rand() % (max)();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
include/internal/catch_random_number_generator.h
Normal file
40
include/internal/catch_random_number_generator.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 30/08/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)
|
||||||
|
*/
|
||||||
|
#ifndef TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
struct IConfig;
|
||||||
|
|
||||||
|
void seedRng( IConfig const& config );
|
||||||
|
|
||||||
|
unsigned int rngSeed();
|
||||||
|
|
||||||
|
struct RandomNumberGenerator {
|
||||||
|
using result_type = unsigned int;
|
||||||
|
|
||||||
|
static constexpr result_type (min)() { return 0; }
|
||||||
|
static constexpr result_type (max)() { return 1000000; }
|
||||||
|
|
||||||
|
result_type operator()( result_type n ) const;
|
||||||
|
result_type operator()() const;
|
||||||
|
|
||||||
|
template<typename V>
|
||||||
|
static void shuffle( V& vector ) {
|
||||||
|
RandomNumberGenerator rng;
|
||||||
|
std::shuffle( vector.begin(), vector.end(), rng );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
|
@@ -9,8 +9,8 @@
|
|||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
|
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_test_case_registry_impl.hpp"
|
#include "catch_test_case_registry_impl.h"
|
||||||
#include "catch_reporter_registry.hpp"
|
#include "catch_reporter_registry.h"
|
||||||
#include "catch_exception_translator_registry.h"
|
#include "catch_exception_translator_registry.h"
|
||||||
#include "catch_tag_alias_registry.h"
|
#include "catch_tag_alias_registry.h"
|
||||||
#include "catch_startup_exception_registry.h"
|
#include "catch_startup_exception_registry.h"
|
||||||
@@ -23,8 +23,7 @@ namespace Catch {
|
|||||||
private NonCopyable {
|
private NonCopyable {
|
||||||
|
|
||||||
public: // IRegistryHub
|
public: // IRegistryHub
|
||||||
RegistryHub() {
|
RegistryHub() = default;
|
||||||
}
|
|
||||||
IReporterRegistry const& getReporterRegistry() const override {
|
IReporterRegistry const& getReporterRegistry() const override {
|
||||||
return m_reporterRegistry;
|
return m_reporterRegistry;
|
||||||
}
|
}
|
||||||
|
@@ -58,11 +58,14 @@ namespace Catch {
|
|||||||
#if !defined(CATCH_CONFIG_DISABLE)
|
#if !defined(CATCH_CONFIG_DISABLE)
|
||||||
|
|
||||||
#define CATCH_REGISTER_REPORTER( name, reporterType ) \
|
#define CATCH_REGISTER_REPORTER( name, reporterType ) \
|
||||||
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
|
||||||
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
#define CATCH_REGISTER_LISTENER( listenerType ) \
|
#define CATCH_REGISTER_LISTENER( listenerType ) \
|
||||||
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
|
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
|
||||||
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
#else // CATCH_CONFIG_DISABLE
|
#else // CATCH_CONFIG_DISABLE
|
||||||
|
|
||||||
#define CATCH_REGISTER_REPORTER(name, reporterType)
|
#define CATCH_REGISTER_REPORTER(name, reporterType)
|
||||||
|
34
include/internal/catch_reporter_registry.cpp
Normal file
34
include/internal/catch_reporter_registry.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 31/08/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 "catch_reporter_registry.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
ReporterRegistry::~ReporterRegistry() = default;
|
||||||
|
|
||||||
|
IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {
|
||||||
|
auto it = m_factories.find( name );
|
||||||
|
if( it == m_factories.end() )
|
||||||
|
return nullptr;
|
||||||
|
return it->second->create( ReporterConfig( config ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {
|
||||||
|
m_factories.emplace(name, factory);
|
||||||
|
}
|
||||||
|
void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {
|
||||||
|
m_listeners.push_back( factory );
|
||||||
|
}
|
||||||
|
|
||||||
|
IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {
|
||||||
|
return m_factories;
|
||||||
|
}
|
||||||
|
IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {
|
||||||
|
return m_listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
include/internal/catch_reporter_registry.h
Normal file
37
include/internal/catch_reporter_registry.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil on 29/10/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_CATCH_REPORTER_REGISTRY_H_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_H_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_interfaces_reporter.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
class ReporterRegistry : public IReporterRegistry {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
~ReporterRegistry() override;
|
||||||
|
|
||||||
|
IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;
|
||||||
|
|
||||||
|
void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );
|
||||||
|
void registerListener( IReporterFactoryPtr const& factory );
|
||||||
|
|
||||||
|
FactoryMap const& getFactories() const override;
|
||||||
|
Listeners const& getListeners() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FactoryMap m_factories;
|
||||||
|
Listeners m_listeners;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_H_INCLUDED
|
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Created by Phil on 29/10/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_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
|
|
||||||
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include "catch_interfaces_reporter.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
class ReporterRegistry : public IReporterRegistry {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
~ReporterRegistry() override {}
|
|
||||||
|
|
||||||
IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override {
|
|
||||||
auto it = m_factories.find( name );
|
|
||||||
if( it == m_factories.end() )
|
|
||||||
return nullptr;
|
|
||||||
return it->second->create( ReporterConfig( config ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {
|
|
||||||
m_factories.emplace(name, factory);
|
|
||||||
}
|
|
||||||
void registerListener( IReporterFactoryPtr const& factory ) {
|
|
||||||
m_listeners.push_back( factory );
|
|
||||||
}
|
|
||||||
|
|
||||||
FactoryMap const& getFactories() const override {
|
|
||||||
return m_factories;
|
|
||||||
}
|
|
||||||
Listeners const& getListeners() const override {
|
|
||||||
return m_listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FactoryMap m_factories;
|
|
||||||
Listeners m_listeners;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
|
|
@@ -1,6 +1,7 @@
|
|||||||
#include "catch_run_context.hpp"
|
#include "catch_run_context.h"
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -207,11 +208,13 @@ namespace Catch {
|
|||||||
m_shouldReportUnexpected = false;
|
m_shouldReportUnexpected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::handleFatalErrorCondition(std::string const & message) {
|
void RunContext::handleFatalErrorCondition( StringRef message ) {
|
||||||
|
// First notify reporter that bad things happened
|
||||||
|
m_reporter->fatalErrorEncountered(message);
|
||||||
|
|
||||||
// Don't rebuild the result -- the stringification itself can cause more fatal errors
|
// Don't rebuild the result -- the stringification itself can cause more fatal errors
|
||||||
// Instead, fake a result data.
|
// Instead, fake a result data.
|
||||||
AssertionResultData tempResult( ResultWas::Unknown, { false } );
|
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
|
||||||
tempResult.resultType = ResultWas::FatalErrorCondition;
|
|
||||||
tempResult.message = message;
|
tempResult.message = message;
|
||||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||||
|
|
||||||
@@ -220,7 +223,7 @@ namespace Catch {
|
|||||||
handleUnfinishedSections();
|
handleUnfinishedSections();
|
||||||
|
|
||||||
// Recreate section for test case (as we will lose the one that was in scope)
|
// Recreate section for test case (as we will lose the one that was in scope)
|
||||||
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
|
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
|
||||||
|
|
||||||
Counts assertions;
|
Counts assertions;
|
||||||
@@ -228,7 +231,7 @@ namespace Catch {
|
|||||||
SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
|
SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
|
||||||
m_reporter->sectionEnded(testCaseSectionStats);
|
m_reporter->sectionEnded(testCaseSectionStats);
|
||||||
|
|
||||||
TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
|
auto const& testInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
|
|
||||||
Totals deltaTotals;
|
Totals deltaTotals;
|
||||||
deltaTotals.testCases.failed = 1;
|
deltaTotals.testCases.failed = 1;
|
||||||
@@ -262,7 +265,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
|
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
|
||||||
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
|
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
|
||||||
m_reporter->sectionStarting(testCaseSection);
|
m_reporter->sectionStarting(testCaseSection);
|
||||||
Counts prevAssertions = m_totals.assertions;
|
Counts prevAssertions = m_totals.assertions;
|
||||||
@@ -324,7 +327,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IResultCapture& getResultCapture() {
|
IResultCapture& getResultCapture() {
|
||||||
if (IResultCapture* capture = getCurrentContext().getResultCapture())
|
if (auto* capture = getCurrentContext().getResultCapture())
|
||||||
return *capture;
|
return *capture;
|
||||||
else
|
else
|
||||||
CATCH_INTERNAL_ERROR("No result capture instance");
|
CATCH_INTERNAL_ERROR("No result capture instance");
|
||||||
|
@@ -12,12 +12,12 @@
|
|||||||
#include "catch_interfaces_reporter.h"
|
#include "catch_interfaces_reporter.h"
|
||||||
#include "catch_interfaces_exception.h"
|
#include "catch_interfaces_exception.h"
|
||||||
#include "catch_config.hpp"
|
#include "catch_config.hpp"
|
||||||
#include "catch_test_registry.hpp"
|
#include "catch_test_registry.h"
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
#include "catch_capture.hpp"
|
#include "catch_capture.hpp"
|
||||||
#include "catch_totals.hpp"
|
#include "catch_totals.h"
|
||||||
#include "catch_test_spec.hpp"
|
#include "catch_test_spec.h"
|
||||||
#include "catch_test_case_tracker.hpp"
|
#include "catch_test_case_tracker.h"
|
||||||
#include "catch_timer.h"
|
#include "catch_timer.h"
|
||||||
#include "catch_assertionhandler.h"
|
#include "catch_assertionhandler.h"
|
||||||
#include "catch_fatal_condition.h"
|
#include "catch_fatal_condition.h"
|
||||||
@@ -100,7 +100,7 @@ namespace Catch {
|
|||||||
|
|
||||||
void exceptionEarlyReported() override;
|
void exceptionEarlyReported() override;
|
||||||
|
|
||||||
void handleFatalErrorCondition(std::string const& message) override;
|
void handleFatalErrorCondition( StringRef message ) override;
|
||||||
|
|
||||||
bool lastAssertionPassed() override;
|
bool lastAssertionPassed() override;
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ namespace Catch {
|
|||||||
std::vector<SectionEndInfo> m_unfinishedSections;
|
std::vector<SectionEndInfo> m_unfinishedSections;
|
||||||
std::vector<ITracker*> m_activeSections;
|
std::vector<ITracker*> m_activeSections;
|
||||||
TrackerContext m_trackerContext;
|
TrackerContext m_trackerContext;
|
||||||
size_t m_prevPassed = 0;
|
std::size_t m_prevPassed = 0;
|
||||||
bool m_shouldReportUnexpected = true;
|
bool m_shouldReportUnexpected = true;
|
||||||
};
|
};
|
||||||
|
|
@@ -9,7 +9,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_section_info.h"
|
#include "catch_section_info.h"
|
||||||
#include "catch_totals.hpp"
|
#include "catch_totals.h"
|
||||||
#include "catch_timer.h"
|
#include "catch_timer.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
#include "catch_totals.hpp"
|
#include "catch_totals.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
276
include/internal/catch_session.cpp
Normal file
276
include/internal/catch_session.cpp
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 31/08/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 "catch_session.h"
|
||||||
|
#include "catch_commandline.h"
|
||||||
|
#include "catch_console_colour.h"
|
||||||
|
#include "catch_enforce.h"
|
||||||
|
#include "catch_list.h"
|
||||||
|
#include "catch_run_context.h"
|
||||||
|
#include "catch_stream.h"
|
||||||
|
#include "catch_test_spec.h"
|
||||||
|
#include "catch_version.h"
|
||||||
|
#include "catch_interfaces_reporter.h"
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
|
#include "catch_startup_exception_registry.h"
|
||||||
|
#include "catch_text.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const int MaxExitCode = 255;
|
||||||
|
using Catch::IStreamingReporterPtr;
|
||||||
|
using Catch::IConfigPtr;
|
||||||
|
using Catch::Config;
|
||||||
|
|
||||||
|
IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
|
||||||
|
auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
|
||||||
|
CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
|
||||||
|
|
||||||
|
return reporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CATCH_CONFIG_DEFAULT_REPORTER
|
||||||
|
#define CATCH_CONFIG_DEFAULT_REPORTER "console"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
|
||||||
|
auto const& reporterNames = config->getReporterNames();
|
||||||
|
if (reporterNames.empty())
|
||||||
|
return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
|
||||||
|
|
||||||
|
IStreamingReporterPtr reporter;
|
||||||
|
for (auto const& name : reporterNames)
|
||||||
|
addReporter(reporter, createReporter(name, config));
|
||||||
|
return reporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CATCH_CONFIG_DEFAULT_REPORTER
|
||||||
|
|
||||||
|
void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
|
||||||
|
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
|
||||||
|
for (auto const& listener : listeners)
|
||||||
|
addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Catch::Totals runTests(std::shared_ptr<Config> const& config) {
|
||||||
|
using namespace Catch;
|
||||||
|
IStreamingReporterPtr reporter = makeReporter(config);
|
||||||
|
addListeners(reporter, config);
|
||||||
|
|
||||||
|
RunContext context(config, std::move(reporter));
|
||||||
|
|
||||||
|
Totals totals;
|
||||||
|
|
||||||
|
context.testGroupStarting(config->name(), 1, 1);
|
||||||
|
|
||||||
|
TestSpec testSpec = config->testSpec();
|
||||||
|
if (!testSpec.hasFilters())
|
||||||
|
testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
|
||||||
|
|
||||||
|
auto const& allTestCases = getAllTestCasesSorted(*config);
|
||||||
|
for (auto const& testCase : allTestCases) {
|
||||||
|
if (!context.aborting() && matchTest(testCase, testSpec, *config))
|
||||||
|
totals += context.runTest(testCase);
|
||||||
|
else
|
||||||
|
context.reporter().skipTest(testCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.testGroupEnded(config->name(), totals, 1, 1);
|
||||||
|
return totals;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyFilenamesAsTags(Catch::IConfig const& config) {
|
||||||
|
using namespace Catch;
|
||||||
|
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
|
||||||
|
for (auto& testCase : tests) {
|
||||||
|
auto tags = testCase.tags;
|
||||||
|
|
||||||
|
std::string filename = testCase.lineInfo.file;
|
||||||
|
auto lastSlash = filename.find_last_of("\\/");
|
||||||
|
if (lastSlash != std::string::npos) {
|
||||||
|
filename.erase(0, lastSlash);
|
||||||
|
filename[0] = '#';
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lastDot = filename.find_last_of('.');
|
||||||
|
if (lastDot != std::string::npos) {
|
||||||
|
filename.erase(lastDot);
|
||||||
|
}
|
||||||
|
|
||||||
|
tags.push_back(std::move(filename));
|
||||||
|
setTags(testCase, tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
Session::Session() {
|
||||||
|
static bool alreadyInstantiated = false;
|
||||||
|
if( alreadyInstantiated ) {
|
||||||
|
try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
|
||||||
|
catch(...) { getMutableRegistryHub().registerStartupException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
|
||||||
|
if ( !exceptions.empty() ) {
|
||||||
|
m_startupExceptions = true;
|
||||||
|
Colour colourGuard( Colour::Red );
|
||||||
|
Catch::cerr() << "Errors occured during startup!" << '\n';
|
||||||
|
// iterate over all exceptions and notify user
|
||||||
|
for ( const auto& ex_ptr : exceptions ) {
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(ex_ptr);
|
||||||
|
} catch ( std::exception const& ex ) {
|
||||||
|
Catch::cerr() << Column( ex.what() ).indent(2) << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alreadyInstantiated = true;
|
||||||
|
m_cli = makeCommandLineParser( m_configData );
|
||||||
|
}
|
||||||
|
Session::~Session() {
|
||||||
|
Catch::cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::showHelp() const {
|
||||||
|
Catch::cout()
|
||||||
|
<< "\nCatch v" << libraryVersion() << "\n"
|
||||||
|
<< m_cli << std::endl
|
||||||
|
<< "For more detailed usage please see the project docs\n" << std::endl;
|
||||||
|
}
|
||||||
|
void Session::libIdentify() {
|
||||||
|
Catch::cout()
|
||||||
|
<< std::left << std::setw(16) << "description: " << "A Catch test executable\n"
|
||||||
|
<< std::left << std::setw(16) << "category: " << "testframework\n"
|
||||||
|
<< std::left << std::setw(16) << "framework: " << "Catch Test\n"
|
||||||
|
<< std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Session::applyCommandLine( int argc, char* argv[] ) {
|
||||||
|
if( m_startupExceptions )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
auto result = m_cli.parse( clara::Args( argc, argv ) );
|
||||||
|
if( !result ) {
|
||||||
|
Catch::cerr()
|
||||||
|
<< Colour( Colour::Red )
|
||||||
|
<< "\nError(s) in input:\n"
|
||||||
|
<< Column( result.errorMessage() ).indent( 2 )
|
||||||
|
<< "\n\n";
|
||||||
|
Catch::cerr() << "Run with -? for usage\n" << std::endl;
|
||||||
|
return MaxExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_configData.showHelp )
|
||||||
|
showHelp();
|
||||||
|
if( m_configData.libIdentify )
|
||||||
|
libIdentify();
|
||||||
|
m_config.reset();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::useConfigData( ConfigData const& configData ) {
|
||||||
|
m_configData = configData;
|
||||||
|
m_config.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Session::run( int argc, char* argv[] ) {
|
||||||
|
if( m_startupExceptions )
|
||||||
|
return 1;
|
||||||
|
int returnCode = applyCommandLine( argc, argv );
|
||||||
|
if( returnCode == 0 )
|
||||||
|
returnCode = run();
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WIN32) && defined(UNICODE)
|
||||||
|
int Session::run( int argc, wchar_t* const argv[] ) {
|
||||||
|
|
||||||
|
char **utf8Argv = new char *[ argc ];
|
||||||
|
|
||||||
|
for ( int i = 0; i < argc; ++i ) {
|
||||||
|
int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
|
||||||
|
|
||||||
|
utf8Argv[ i ] = new char[ bufSize ];
|
||||||
|
|
||||||
|
WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
int returnCode = run( argc, utf8Argv );
|
||||||
|
|
||||||
|
for ( int i = 0; i < argc; ++i )
|
||||||
|
delete [] utf8Argv[ i ];
|
||||||
|
|
||||||
|
delete [] utf8Argv;
|
||||||
|
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int Session::run() {
|
||||||
|
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
|
||||||
|
Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
|
||||||
|
static_cast<void>(std::getchar());
|
||||||
|
}
|
||||||
|
int exitCode = runInternal();
|
||||||
|
if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
|
||||||
|
Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
|
||||||
|
static_cast<void>(std::getchar());
|
||||||
|
}
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
clara::Parser const& Session::cli() const {
|
||||||
|
return m_cli;
|
||||||
|
}
|
||||||
|
void Session::cli( clara::Parser const& newParser ) {
|
||||||
|
m_cli = newParser;
|
||||||
|
}
|
||||||
|
ConfigData& Session::configData() {
|
||||||
|
return m_configData;
|
||||||
|
}
|
||||||
|
Config& Session::config() {
|
||||||
|
if( !m_config )
|
||||||
|
m_config = std::make_shared<Config>( m_configData );
|
||||||
|
return *m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Session::runInternal() {
|
||||||
|
if( m_startupExceptions )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if( m_configData.showHelp || m_configData.libIdentify )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config(); // Force config to be constructed
|
||||||
|
|
||||||
|
seedRng( *m_config );
|
||||||
|
|
||||||
|
if( m_configData.filenamesAsTags )
|
||||||
|
applyFilenamesAsTags( *m_config );
|
||||||
|
|
||||||
|
// Handle list request
|
||||||
|
if( Option<std::size_t> listed = list( config() ) )
|
||||||
|
return static_cast<int>( *listed );
|
||||||
|
|
||||||
|
return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
|
||||||
|
}
|
||||||
|
catch( std::exception& ex ) {
|
||||||
|
Catch::cerr() << ex.what() << std::endl;
|
||||||
|
return MaxExitCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Catch
|
53
include/internal/catch_session.h
Normal file
53
include/internal/catch_session.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Created by Phil on 31/10/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_CATCH_RUNNER_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_commandline.h"
|
||||||
|
#include "catch_config.hpp"
|
||||||
|
#include "catch_text.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
class Session : NonCopyable {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Session();
|
||||||
|
~Session() override;
|
||||||
|
|
||||||
|
void showHelp() const;
|
||||||
|
void libIdentify();
|
||||||
|
|
||||||
|
int applyCommandLine( int argc, char* argv[] );
|
||||||
|
|
||||||
|
void useConfigData( ConfigData const& configData );
|
||||||
|
|
||||||
|
int run( int argc, char* argv[] );
|
||||||
|
#if defined(WIN32) && defined(UNICODE)
|
||||||
|
int run( int argc, wchar_t* const argv[] );
|
||||||
|
#endif
|
||||||
|
int run();
|
||||||
|
|
||||||
|
clara::Parser const& cli() const;
|
||||||
|
void cli( clara::Parser const& newParser );
|
||||||
|
ConfigData& configData();
|
||||||
|
Config& config();
|
||||||
|
private:
|
||||||
|
int runInternal();
|
||||||
|
|
||||||
|
clara::Parser m_cli;
|
||||||
|
ConfigData m_configData;
|
||||||
|
std::shared_ptr<Config> m_config;
|
||||||
|
bool m_startupExceptions = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
|
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
template<typename WriterF, size_t bufferSize=256>
|
template<typename WriterF, std::size_t bufferSize=256>
|
||||||
class StreamBufImpl : public StreamBufBase {
|
class StreamBufImpl : public StreamBufBase {
|
||||||
char data[bufferSize];
|
char data[bufferSize];
|
||||||
WriterF m_writer;
|
WriterF m_writer;
|
||||||
@@ -57,6 +57,8 @@ namespace Catch {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
Catch::IStream::~IStream() = default;
|
||||||
|
|
||||||
FileStream::FileStream( std::string const& filename ) {
|
FileStream::FileStream( std::string const& filename ) {
|
||||||
m_ofs.open( filename.c_str() );
|
m_ofs.open( filename.c_str() );
|
||||||
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
|
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
|
||||||
|
@@ -24,7 +24,7 @@ namespace Catch {
|
|||||||
|
|
||||||
|
|
||||||
struct IStream {
|
struct IStream {
|
||||||
virtual ~IStream() noexcept;
|
virtual ~IStream();
|
||||||
virtual std::ostream& stream() const = 0;
|
virtual std::ostream& stream() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ namespace Catch {
|
|||||||
mutable std::ofstream m_ofs;
|
mutable std::ofstream m_ofs;
|
||||||
public:
|
public:
|
||||||
FileStream( std::string const& filename );
|
FileStream( std::string const& filename );
|
||||||
~FileStream() noexcept override;
|
~FileStream() override = default;
|
||||||
public: // IStream
|
public: // IStream
|
||||||
std::ostream& stream() const override;
|
std::ostream& stream() const override;
|
||||||
};
|
};
|
||||||
@@ -42,7 +42,7 @@ namespace Catch {
|
|||||||
mutable std::ostream m_os;
|
mutable std::ostream m_os;
|
||||||
public:
|
public:
|
||||||
CoutStream();
|
CoutStream();
|
||||||
~CoutStream() noexcept override;
|
~CoutStream() override = default;
|
||||||
|
|
||||||
public: // IStream
|
public: // IStream
|
||||||
std::ostream& stream() const override;
|
std::ostream& stream() const override;
|
||||||
@@ -54,7 +54,7 @@ namespace Catch {
|
|||||||
mutable std::ostream m_os;
|
mutable std::ostream m_os;
|
||||||
public:
|
public:
|
||||||
DebugOutStream();
|
DebugOutStream();
|
||||||
~DebugOutStream() noexcept override;
|
~DebugOutStream() override = default;
|
||||||
|
|
||||||
public: // IStream
|
public: // IStream
|
||||||
std::ostream& stream() const override;
|
std::ostream& stream() const override;
|
||||||
|
12
include/internal/catch_streambuf.cpp
Normal file
12
include/internal/catch_streambuf.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Created by Martin on 31/08/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 "catch_streambuf.h"
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
StreamBufBase::~StreamBufBase() = default;
|
||||||
|
}
|
@@ -8,15 +8,13 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_compiler_capabilities.h"
|
|
||||||
|
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
class StreamBufBase : public std::streambuf {
|
class StreamBufBase : public std::streambuf {
|
||||||
public:
|
public:
|
||||||
virtual ~StreamBufBase() noexcept;
|
virtual ~StreamBufBase();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,12 +5,20 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
auto getEmptyStringRef() -> StringRef {
|
auto getEmptyStringRef() -> StringRef {
|
||||||
@@ -160,3 +168,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
@@ -25,7 +25,7 @@ namespace Catch {
|
|||||||
class StringRef {
|
class StringRef {
|
||||||
friend struct StringRefTestAccess;
|
friend struct StringRefTestAccess;
|
||||||
|
|
||||||
using size_type = size_t;
|
using size_type = std::size_t;
|
||||||
|
|
||||||
char const* m_start;
|
char const* m_start;
|
||||||
size_type m_size;
|
size_type m_size;
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_tag_alias_registry.h"
|
#include "catch_tag_alias_registry.h"
|
||||||
#include "catch_console_colour.hpp"
|
#include "catch_console_colour.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_test_spec.hpp"
|
#include "catch_test_spec.h"
|
||||||
#include "catch_interfaces_testcase.h"
|
#include "catch_interfaces_testcase.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ namespace Catch {
|
|||||||
std::string TestCaseInfo::tagsAsString() const {
|
std::string TestCaseInfo::tagsAsString() const {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
// '[' and ']' per tag
|
// '[' and ']' per tag
|
||||||
size_t full_size = 2 * tags.size();
|
std::size_t full_size = 2 * tags.size();
|
||||||
for (const auto& tag : tags) {
|
for (const auto& tag : tags) {
|
||||||
full_size += tag.size();
|
full_size += tag.size();
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,12 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_test_case_registry_impl.hpp"
|
#include "catch_test_case_registry_impl.h"
|
||||||
|
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
|
#include "catch_random_number_generator.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
|
|
||||||
@@ -17,9 +18,6 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { return std::rand() % n; }
|
|
||||||
RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { return std::rand() % max(); }
|
|
||||||
|
|
||||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
|
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
|
||||||
|
|
||||||
std::vector<TestCase> sorted = unsortedTestCases;
|
std::vector<TestCase> sorted = unsortedTestCases;
|
||||||
|
@@ -8,8 +8,8 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_test_registry.hpp"
|
#include "catch_test_registry.h"
|
||||||
#include "catch_test_spec.hpp"
|
#include "catch_test_spec.h"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -22,21 +22,6 @@ namespace Catch {
|
|||||||
class TestCase;
|
class TestCase;
|
||||||
struct IConfig;
|
struct IConfig;
|
||||||
|
|
||||||
struct RandomNumberGenerator {
|
|
||||||
using result_type = std::ptrdiff_t;
|
|
||||||
|
|
||||||
result_type operator()( result_type n ) const;
|
|
||||||
|
|
||||||
static constexpr result_type min() { return 0; }
|
|
||||||
static constexpr result_type max() { return 1000000; }
|
|
||||||
result_type operator()() const;
|
|
||||||
template<typename V>
|
|
||||||
static void shuffle( V& vector ) {
|
|
||||||
RandomNumberGenerator rng;
|
|
||||||
std::shuffle( vector.begin(), vector.end(), rng );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
||||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||||
|
|
||||||
@@ -58,7 +43,7 @@ namespace Catch {
|
|||||||
std::vector<TestCase> m_functions;
|
std::vector<TestCase> m_functions;
|
||||||
mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
|
mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
|
||||||
mutable std::vector<TestCase> m_sortedFunctions;
|
mutable std::vector<TestCase> m_sortedFunctions;
|
||||||
size_t m_unnamedCount = 0;
|
std::size_t m_unnamedCount = 0;
|
||||||
std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
|
std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
|
||||||
};
|
};
|
||||||
|
|
@@ -5,7 +5,7 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_test_case_tracker.hpp"
|
#include "catch_test_case_tracker.h"
|
||||||
|
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
|
|
||||||
@@ -14,7 +14,10 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace TestCaseTracking {
|
namespace TestCaseTracking {
|
||||||
@@ -25,6 +28,8 @@ namespace TestCaseTracking {
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
ITracker::~ITracker() = default;
|
||||||
|
|
||||||
|
|
||||||
TrackerContext& TrackerContext::instance() {
|
TrackerContext& TrackerContext::instance() {
|
||||||
static TrackerContext s_instance;
|
static TrackerContext s_instance;
|
||||||
@@ -276,4 +281,6 @@ using TestCaseTracking::IndexTracker;
|
|||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace TestCaseTracking {
|
namespace TestCaseTracking {
|
||||||
|
|
||||||
@@ -32,7 +30,7 @@ namespace TestCaseTracking {
|
|||||||
using ITrackerPtr = std::shared_ptr<ITracker>;
|
using ITrackerPtr = std::shared_ptr<ITracker>;
|
||||||
|
|
||||||
struct ITracker {
|
struct ITracker {
|
||||||
virtual ~ITracker() = default;
|
virtual ~ITracker();
|
||||||
|
|
||||||
// static queries
|
// static queries
|
||||||
virtual NameAndLocation const& nameAndLocation() const = 0;
|
virtual NameAndLocation const& nameAndLocation() const = 0;
|
||||||
@@ -182,6 +180,4 @@ using TestCaseTracking::IndexTracker;
|
|||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
|
@@ -5,8 +5,8 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_test_registry.hpp"
|
#include "catch_test_registry.h"
|
||||||
#include "catch_test_case_registry_impl.hpp"
|
#include "catch_test_case_registry_impl.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@@ -32,4 +32,6 @@ namespace Catch {
|
|||||||
getMutableRegistryHub().registerStartupException();
|
getMutableRegistryHub().registerStartupException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoReg::~AutoReg() = default;
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,7 @@ struct NameAndTags {
|
|||||||
|
|
||||||
struct AutoReg : NonCopyable {
|
struct AutoReg : NonCopyable {
|
||||||
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
|
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
|
||||||
~AutoReg() = default;
|
~AutoReg();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
@@ -63,38 +63,38 @@ struct AutoReg : NonCopyable {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||||
static void TestName(); \
|
static void TestName(); \
|
||||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
static void TestName()
|
static void TestName()
|
||||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
|
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
||||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
|
||||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
namespace{ \
|
namespace{ \
|
||||||
struct TestName : ClassName{ \
|
struct TestName : ClassName{ \
|
||||||
void test(); \
|
void test(); \
|
||||||
}; \
|
}; \
|
||||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||||
} \
|
} \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
|
||||||
void TestName::test()
|
void TestName::test()
|
||||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
||||||
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
|
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
|
||||||
CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
|
||||||
CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
|
||||||
|
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
|
@@ -5,7 +5,7 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_test_spec.hpp"
|
#include "catch_test_spec.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -15,6 +15,11 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
TestSpec::Pattern::~Pattern() = default;
|
||||||
|
TestSpec::NamePattern::~NamePattern() = default;
|
||||||
|
TestSpec::TagPattern::~TagPattern() = default;
|
||||||
|
TestSpec::ExcludedPattern::~ExcludedPattern() = default;
|
||||||
|
|
||||||
TestSpec::NamePattern::NamePattern( std::string const& name )
|
TestSpec::NamePattern::NamePattern( std::string const& name )
|
||||||
: m_wildcardPattern( toLower( name ), CaseSensitive::No )
|
: m_wildcardPattern( toLower( name ), CaseSensitive::No )
|
||||||
{}
|
{}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
#pragma clang diagnostic ignored "-Wpadded"
|
#pragma clang diagnostic ignored "-Wpadded"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "catch_wildcard_pattern.hpp"
|
#include "catch_wildcard_pattern.h"
|
||||||
#include "catch_test_case_info.h"
|
#include "catch_test_case_info.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -24,7 +24,7 @@ namespace Catch {
|
|||||||
|
|
||||||
class TestSpec {
|
class TestSpec {
|
||||||
struct Pattern {
|
struct Pattern {
|
||||||
virtual ~Pattern() = default;
|
virtual ~Pattern();
|
||||||
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
|
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
|
||||||
};
|
};
|
||||||
using PatternPtr = std::shared_ptr<Pattern>;
|
using PatternPtr = std::shared_ptr<Pattern>;
|
||||||
@@ -32,7 +32,7 @@ namespace Catch {
|
|||||||
class NamePattern : public Pattern {
|
class NamePattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
NamePattern( std::string const& name );
|
NamePattern( std::string const& name );
|
||||||
virtual ~NamePattern() = default;
|
virtual ~NamePattern();
|
||||||
virtual bool matches( TestCaseInfo const& testCase ) const override;
|
virtual bool matches( TestCaseInfo const& testCase ) const override;
|
||||||
private:
|
private:
|
||||||
WildcardPattern m_wildcardPattern;
|
WildcardPattern m_wildcardPattern;
|
||||||
@@ -41,7 +41,7 @@ namespace Catch {
|
|||||||
class TagPattern : public Pattern {
|
class TagPattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
TagPattern( std::string const& tag );
|
TagPattern( std::string const& tag );
|
||||||
virtual ~TagPattern() = default;
|
virtual ~TagPattern();
|
||||||
virtual bool matches( TestCaseInfo const& testCase ) const override;
|
virtual bool matches( TestCaseInfo const& testCase ) const override;
|
||||||
private:
|
private:
|
||||||
std::string m_tag;
|
std::string m_tag;
|
||||||
@@ -50,7 +50,7 @@ namespace Catch {
|
|||||||
class ExcludedPattern : public Pattern {
|
class ExcludedPattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
ExcludedPattern( PatternPtr const& underlyingPattern );
|
ExcludedPattern( PatternPtr const& underlyingPattern );
|
||||||
virtual ~ExcludedPattern() = default;
|
virtual ~ExcludedPattern();
|
||||||
virtual bool matches( TestCaseInfo const& testCase ) const override;
|
virtual bool matches( TestCaseInfo const& testCase ) const override;
|
||||||
private:
|
private:
|
||||||
PatternPtr m_underlyingPattern;
|
PatternPtr m_underlyingPattern;
|
@@ -5,7 +5,7 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "catch_test_spec_parser.hpp"
|
#include "catch_test_spec_parser.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
#pragma clang diagnostic ignored "-Wpadded"
|
#pragma clang diagnostic ignored "-Wpadded"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "catch_test_spec.hpp"
|
#include "catch_test_spec.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
#include "catch_interfaces_tag_alias_registry.h"
|
#include "catch_interfaces_tag_alias_registry.h"
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ namespace Catch {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void addPattern() {
|
void addPattern() {
|
||||||
std::string token = subString();
|
std::string token = subString();
|
||||||
for( size_t i = 0; i < m_escapeChars.size(); ++i )
|
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
|
||||||
token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
|
token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
|
||||||
m_escapeChars.clear();
|
m_escapeChars.clear();
|
||||||
if( startsWith( token, "exclude:" ) ) {
|
if( startsWith( token, "exclude:" ) ) {
|
@@ -20,7 +20,7 @@ namespace Catch {
|
|||||||
uint64_t sum = 0;
|
uint64_t sum = 0;
|
||||||
static const uint64_t iterations = 1000000;
|
static const uint64_t iterations = 1000000;
|
||||||
|
|
||||||
for( size_t i = 0; i < iterations; ++i ) {
|
for( std::size_t i = 0; i < iterations; ++i ) {
|
||||||
|
|
||||||
uint64_t ticks;
|
uint64_t ticks;
|
||||||
uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
|
uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
|
||||||
|
@@ -6,6 +6,13 @@
|
|||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
# pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
#include "catch_interfaces_config.h"
|
#include "catch_interfaces_config.h"
|
||||||
#include "catch_context.h"
|
#include "catch_context.h"
|
||||||
@@ -210,20 +217,9 @@ std::string StringMaker<double>::convert(double value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __OBJC__
|
} // end namespace Catch
|
||||||
std::string StringMaker<NSString*>::convert(NSString* nsstring) {
|
|
||||||
if (!nsstring)
|
#if defined(__clang__)
|
||||||
return "nil";
|
# pragma clang diagnostic pop
|
||||||
return "@" + toString([nsstring UTF8String]);
|
|
||||||
}
|
|
||||||
std::string StringMaker<NSString * CATCH_ARC_STRONG>::convert(NSString* CATCH_ARC_STRONG nsstring) {
|
|
||||||
if (!nsstring)
|
|
||||||
return "nil";
|
|
||||||
return "@" + toString([nsstring UTF8String]);
|
|
||||||
}
|
|
||||||
std::string StringMaker<NSObject*>::convert(NSObject* nsObject) {
|
|
||||||
return ::Catch::Detail::stringify([nsObject description]);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // end namespace Catch
|
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -20,6 +19,11 @@
|
|||||||
#include "catch_objc_arc.hpp"
|
#include "catch_objc_arc.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// We need a dummy global operator<< so we can bring it into Catch namespace later
|
// We need a dummy global operator<< so we can bring it into Catch namespace later
|
||||||
struct Catch_global_namespace_dummy;
|
struct Catch_global_namespace_dummy;
|
||||||
@@ -236,7 +240,53 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// === Pair ===
|
template<typename T>
|
||||||
|
struct EnumStringMaker {
|
||||||
|
static std::string convert(const T& t) {
|
||||||
|
return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
template<>
|
||||||
|
struct StringMaker<NSString*> {
|
||||||
|
static std::string convert(NSString * nsstring) {
|
||||||
|
if (!nsstring)
|
||||||
|
return "nil";
|
||||||
|
return std::string("@") + [nsstring UTF8String];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct StringMaker<NSObject*> {
|
||||||
|
static std::string convert(NSObject* nsObject) {
|
||||||
|
return ::Catch::Detail::stringify([nsObject description]);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
namespace Detail {
|
||||||
|
inline std::string stringify( NSString* nsstring ) {
|
||||||
|
return StringMaker<NSString*>::convert( nsstring );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Detail
|
||||||
|
#endif // __OBJC__
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// Separate std-lib types stringification, so it can be selectively enabled
|
||||||
|
// This means that we do not bring in
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
|
||||||
|
# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||||
|
# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||||
|
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Separate std::pair specialization
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
|
||||||
|
#include <utility>
|
||||||
|
namespace Catch {
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct StringMaker<std::pair<T1, T2> > {
|
struct StringMaker<std::pair<T1, T2> > {
|
||||||
static std::string convert(const std::pair<T1, T2>& pair) {
|
static std::string convert(const std::pair<T1, T2>& pair) {
|
||||||
@@ -249,9 +299,13 @@ namespace Catch {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||||
|
|
||||||
|
// Separate std::tuple specialization
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
|
||||||
|
#include <tuple>
|
||||||
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
template<
|
template<
|
||||||
typename Tuple,
|
typename Tuple,
|
||||||
@@ -287,31 +341,129 @@ namespace Catch {
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
// Separate std::chrono::duration specialization
|
||||||
struct EnumStringMaker {
|
#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
|
||||||
static std::string convert(const T& t) {
|
#include <ctime>
|
||||||
return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
|
#include <ratio>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
template <class Ratio>
|
||||||
|
struct ratio_string {
|
||||||
|
static std::string symbol();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Ratio>
|
||||||
|
std::string ratio_string<Ratio>::symbol() {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << '[' << Ratio::num << '/'
|
||||||
|
<< Ratio::den << ']';
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::atto> {
|
||||||
|
static std::string symbol() { return "a"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::femto> {
|
||||||
|
static std::string symbol() { return "f"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::pico> {
|
||||||
|
static std::string symbol() { return "p"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::nano> {
|
||||||
|
static std::string symbol() { return "n"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::micro> {
|
||||||
|
static std::string symbol() { return "u"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::milli> {
|
||||||
|
static std::string symbol() { return "m"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
////////////
|
||||||
|
// std::chrono::duration specializations
|
||||||
|
template<typename Value, typename Ratio>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, Ratio>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Value>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << " s";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Value>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << " m";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Value>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << " h";
|
||||||
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __OBJC__
|
////////////
|
||||||
template<>
|
// std::chrono::time_point specialization
|
||||||
struct StringMaker<NSString*> {
|
// Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
|
||||||
static std::string convert(NSString* nsstring);
|
template<typename Clock, typename Duration>
|
||||||
};
|
struct StringMaker<std::chrono::time_point<Clock, Duration>> {
|
||||||
template<>
|
static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
|
||||||
struct StringMaker<NSString* CATCH_ARC_STRONG> {
|
return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
|
||||||
static std::string convert(NSString * CATCH_ARC_STRONG nsstring);
|
}
|
||||||
};
|
|
||||||
template<>
|
|
||||||
struct StringMaker<NSObject *> {
|
|
||||||
static std::string convert(NSObject* nsObject);
|
|
||||||
};
|
};
|
||||||
|
// std::chrono::time_point<system_clock> specialization
|
||||||
|
template<typename Duration>
|
||||||
|
struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
|
||||||
|
static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
|
||||||
|
auto converted = std::chrono::system_clock::to_time_t(time_point);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
std::tm timeInfo = {};
|
||||||
|
gmtime_s(&timeInfo, &converted);
|
||||||
|
#else
|
||||||
|
std::tm* timeInfo = std::gmtime(&converted);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
|
||||||
|
char timeStamp[timeStampSize];
|
||||||
|
const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
|
||||||
|
|
||||||
} // namespace Catch
|
#ifdef _MSC_VER
|
||||||
|
std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
|
||||||
|
#else
|
||||||
|
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
|
||||||
|
#endif
|
||||||
|
return std::string(timeStamp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user