Skip to content

Commit

Permalink
Merge branch 'catchorg:devel' into TestCaseWithSetup
Browse files Browse the repository at this point in the history
  • Loading branch information
KStocky authored Aug 1, 2024
2 parents a6e06b0 + 33e24b1 commit 3c7920a
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 56 deletions.
8 changes: 1 addition & 7 deletions .github/workflows/mac-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ on: [push, pull_request]

jobs:
build:
# macos-12 updated to a toolchain that crashes when linking the
# test binary. This seems to be a known bug in that version,
# and will eventually get fixed in an update. After that, we can go
# back to newer macos images.
runs-on: macos-11
runs-on: macos-12
strategy:
matrix:
cxx:
Expand All @@ -29,8 +25,6 @@ jobs:
env:
CXX: ${{matrix.cxx}}
CXXFLAGS: ${{matrix.cxxflags}}
# Note: $GITHUB_WORKSPACE is distinct from ${{runner.workspace}}.
# This is important
run: |
cmake -Bbuild -H$GITHUB_WORKSPACE \
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module(name = "catch2")

bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "bazel_skylib", version = "1.7.1")
6 changes: 3 additions & 3 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "bazel_skylib",
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz",
],
)

Expand Down
36 changes: 27 additions & 9 deletions docs/matchers.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,36 @@ The other miscellaneous matcher utility is exception matching.

#### Matching exceptions

Catch2 provides a utility macro for asserting that an expression
throws exception of specific type, and that the exception has desired
properties. The macro is `REQUIRE_THROWS_MATCHES(expr, ExceptionType, Matcher)`.
Because exceptions are a bit special, Catch2 has a separate macro for them.


The basic form is

```
REQUIRE_THROWS_MATCHES(expr, ExceptionType, Matcher)
```

and it checks that the `expr` throws an exception, that exception is derived
from the `ExceptionType` type, and then `Matcher::match` is called on
the caught exception.

> `REQUIRE_THROWS_MATCHES` macro lives in `catch2/matchers/catch_matchers.hpp`
For one-off checks you can use the `Predicate` matcher above, e.g.

Catch2 currently provides two matchers for exceptions.
These are:
```cpp
REQUIRE_THROWS_MATCHES(parse(...),
parse_error,
Predicate<parse_error>([] (parse_error const& err) -> bool { return err.line() == 1; })
);
```

but if you intend to thoroughly test your error reporting, I recommend
defining a specialized matcher.


Catch2 also provides 2 built-in matchers for checking the error message
inside an exception (it must be derived from `std::exception`):
* `Message(std::string message)`.
* `MessageMatches(Matcher matcher)`.

Expand All @@ -236,10 +257,7 @@ REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("De
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, MessageMatches(StartsWith("DerivedException")));
```
Note that `DerivedException` in the example above has to derive from
`std::exception` for the example to work.
> the exception message matcher lives in `catch2/matchers/catch_matchers_exception.hpp`
> the exception message matchers live in `catch2/matchers/catch_matchers_exception.hpp`
### Generic range Matchers
Expand Down
20 changes: 15 additions & 5 deletions extras/Catch.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
test executable and when the tests are executed themselves. This requires
cmake/ctest >= 3.22.

``DL_FRAMEWORK_PATHS path...``
Specifies paths that need to be set for the dynamic linker to find libraries
packaged as frameworks on Apple platforms when running the test executable
(DYLD_FRAMEWORK_PATH). These paths will both be set when retrieving the list
of test cases from the test executable and when the tests are executed themselves.
This requires cmake/ctest >= 3.22.

`DISCOVERY_MODE mode``
Provides control over when ``catch_discover_tests`` performs test discovery.
By default, ``POST_BUILD`` sets up a post-build command to perform test discovery
Expand All @@ -146,7 +153,7 @@ function(catch_discover_tests TARGET)
""
""
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX;DISCOVERY_MODE"
"TEST_SPEC;EXTRA_ARGS;PROPERTIES;DL_PATHS"
"TEST_SPEC;EXTRA_ARGS;PROPERTIES;DL_PATHS;DL_FRAMEWORK_PATHS"
${ARGN}
)

Expand All @@ -156,10 +163,11 @@ function(catch_discover_tests TARGET)
if(NOT _TEST_LIST)
set(_TEST_LIST ${TARGET}_TESTS)
endif()
if (_DL_PATHS)
if(${CMAKE_VERSION} VERSION_LESS "3.22.0")
message(FATAL_ERROR "The DL_PATHS option requires at least cmake 3.22")
endif()
if(_DL_PATHS AND ${CMAKE_VERSION} VERSION_LESS "3.22.0")
message(FATAL_ERROR "The DL_PATHS option requires at least cmake 3.22")
endif()
if(_DL_FRAMEWORK_PATHS AND ${CMAKE_VERSION} VERSION_LESS "3.22.0")
message(FATAL_ERROR "The DL_FRAMEWORK_PATHS option requires at least cmake 3.22")
endif()
if(NOT _DISCOVERY_MODE)
if(NOT CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE)
Expand Down Expand Up @@ -205,6 +213,7 @@ function(catch_discover_tests TARGET)
-D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}"
-D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}"
-D "TEST_DL_PATHS=${_DL_PATHS}"
-D "TEST_DL_FRAMEWORK_PATHS=${_DL_FRAMEWORK_PATHS}"
-D "CTEST_FILE=${ctest_tests_file}"
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
VERBATIM
Expand Down Expand Up @@ -250,6 +259,7 @@ function(catch_discover_tests TARGET)
" TEST_OUTPUT_SUFFIX" " [==[" "${_OUTPUT_SUFFIX}" "]==]" "\n"
" CTEST_FILE" " [==[" "${ctest_tests_file}" "]==]" "\n"
" TEST_DL_PATHS" " [==[" "${_DL_PATHS}" "]==]" "\n"
" TEST_DL_FRAMEWORK_PATHS" " [==[" "${_DL_FRAMEWORK_PATHS}" "]==]" "\n"
" CTEST_FILE" " [==[" "${CTEST_FILE}" "]==]" "\n"
" )" "\n"
" endif()" "\n"
Expand Down
16 changes: 15 additions & 1 deletion extras/CatchAddTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function(catch_discover_tests_impl)
""
""
"TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_OUTPUT_DIR;TEST_OUTPUT_PREFIX;TEST_OUTPUT_SUFFIX;TEST_PREFIX;TEST_REPORTER;TEST_SPEC;TEST_SUFFIX;TEST_LIST;CTEST_FILE"
"TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR;TEST_DL_PATHS"
"TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR;TEST_DL_PATHS;TEST_DL_FRAMEWORK_PATHS"
${ARGN}
)

Expand All @@ -36,6 +36,7 @@ function(catch_discover_tests_impl)
set(output_prefix ${_TEST_OUTPUT_PREFIX})
set(output_suffix ${_TEST_OUTPUT_SUFFIX})
set(dl_paths ${_TEST_DL_PATHS})
set(dl_framework_paths ${_TEST_DL_FRAMEWORK_PATHS})
set(script)
set(suite)
set(tests)
Expand All @@ -60,6 +61,11 @@ function(catch_discover_tests_impl)
set(ENV{${dl_paths_variable_name}} "${paths}")
endif()

if(APPLE AND dl_framework_paths)
cmake_path(CONVERT "${dl_framework_paths}" TO_NATIVE_PATH_LIST paths)
set(ENV{DYLD_FRAMEWORK_PATH} "${paths}")
endif()

execute_process(
COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --verbosity quiet
OUTPUT_VARIABLE output
Expand Down Expand Up @@ -121,6 +127,13 @@ function(catch_discover_tests_impl)
endforeach()
endif()

if(APPLE AND dl_framework_paths)
foreach(path ${dl_framework_paths})
cmake_path(NATIVE_PATH path native_path)
list(APPEND environment_modifications "DYLD_FRAMEWORK_PATH=path_list_prepend:${native_path}")
endforeach()
endif()

# Parse output
foreach(line ${output})
set(test "${line}")
Expand Down Expand Up @@ -187,6 +200,7 @@ if(CMAKE_SCRIPT_MODE_FILE)
TEST_OUTPUT_PREFIX ${TEST_OUTPUT_PREFIX}
TEST_OUTPUT_SUFFIX ${TEST_OUTPUT_SUFFIX}
TEST_DL_PATHS ${TEST_DL_PATHS}
TEST_DL_FRAMEWORK_PATHS ${TEST_DL_FRAMEWORK_PATHS}
CTEST_FILE ${CTEST_FILE}
)
endif()
4 changes: 2 additions & 2 deletions src/catch2/benchmark/catch_benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ namespace Catch {
: fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}

template <typename Clock>
ExecutionPlan prepare(const IConfig &cfg, Environment env) const {
ExecutionPlan prepare(const IConfig &cfg, Environment env) {
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), CATCH_MOVE(fun), std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
}

template <typename Clock = default_clock>
Expand Down
6 changes: 6 additions & 0 deletions src/catch2/benchmark/detail/catch_benchmark_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
namespace Catch {
namespace Benchmark {
namespace Detail {
struct do_nothing {
void operator()() const {}
};

BenchmarkFunction::callable::~callable() = default;
BenchmarkFunction::BenchmarkFunction():
f( new model<do_nothing>{ {} } ){}
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
25 changes: 3 additions & 22 deletions src/catch2/benchmark/detail/catch_benchmark_function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,17 @@ namespace Catch {
private:
struct callable {
virtual void call(Chronometer meter) const = 0;
virtual Catch::Detail::unique_ptr<callable> clone() const = 0;
virtual ~callable(); // = default;

callable() = default;
callable(callable const&) = default;
callable& operator=(callable const&) = default;
callable(callable&&) = default;
callable& operator=(callable&&) = default;
};
template <typename Fun>
struct model : public callable {
model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
model(Fun const& fun_) : fun(fun_) {}

Catch::Detail::unique_ptr<callable> clone() const override {
return Catch::Detail::make_unique<model<Fun>>( *this );
}

void call(Chronometer meter) const override {
call(meter, is_callable<Fun(Chronometer)>());
}
Expand All @@ -64,14 +59,8 @@ namespace Catch {
Fun fun;
};

struct do_nothing { void operator()() const {} };

template <typename T>
BenchmarkFunction(model<T>* c) : f(c) {}

public:
BenchmarkFunction()
: f(new model<do_nothing>{ {} }) {}
BenchmarkFunction();

template <typename Fun,
std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
Expand All @@ -81,20 +70,12 @@ namespace Catch {
BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
f( CATCH_MOVE( that.f ) ) {}

BenchmarkFunction(BenchmarkFunction const& that)
: f(that.f->clone()) {}

BenchmarkFunction&
operator=( BenchmarkFunction&& that ) noexcept {
f = CATCH_MOVE( that.f );
return *this;
}

BenchmarkFunction& operator=(BenchmarkFunction const& that) {
f = that.f->clone();
return *this;
}

void operator()(Chronometer meter) const { f->call(meter); }

private:
Expand Down
12 changes: 7 additions & 5 deletions src/catch2/benchmark/detail/catch_estimate_clock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ namespace Catch {
namespace Detail {
template <typename Clock>
std::vector<double> resolution(int k) {
std::vector<TimePoint<Clock>> times;
times.reserve(static_cast<size_t>(k + 1));
for ( int i = 0; i < k + 1; ++i ) {
times.push_back( Clock::now() );
const size_t points = static_cast<size_t>( k + 1 );
// To avoid overhead from the branch inside vector::push_back,
// we allocate them all and then overwrite.
std::vector<TimePoint<Clock>> times(points);
for ( auto& time : times ) {
time = Clock::now();
}

std::vector<double> deltas;
deltas.reserve(static_cast<size_t>(k));
for ( size_t idx = 1; idx < times.size(); ++idx ) {
for ( size_t idx = 1; idx < points; ++idx ) {
deltas.push_back( static_cast<double>(
( times[idx] - times[idx - 1] ).count() ) );
}
Expand Down
2 changes: 1 addition & 1 deletion src/catch2/benchmark/detail/catch_measure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Catch {
template <typename Clock, typename Fun, typename... Args>
TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
auto start = Clock::now();
auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...);
auto&& r = Detail::complete_invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
auto end = Clock::now();
auto delta = end - start;
return { delta, CATCH_FORWARD(r), 1 };
Expand Down
1 change: 1 addition & 0 deletions src/catch2/catch_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ namespace Catch {
m_messages.back().message += " := ";
start = pos;
}
break;
default:; // noop
}
}
Expand Down

0 comments on commit 3c7920a

Please sign in to comment.