Skip to content

Commit 9833b6c

Browse files
committed
Add compile-only test for static analysis mode
The expansions in this mode use symbols that are left undefined on purpose, so the file is compiled but never linked, and compiling it is the test.
1 parent 9088896 commit 9833b6c

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

tests/ExtraTests/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,20 @@ set_tests_properties(CompileConfiguration::FastCompile
539539
PASS_REGULAR_EXPRESSION "test cases: 6 \\| 1 passed \\| 1 failed \\| 4 failed as expected\nassertions: 13 \\| 6 passed \\| 2 failed \\| 5 failed as expected"
540540
)
541541

542+
# The static analysis mode is not runnable, so compiling
543+
# this one is the whole test. GCC cannot compile the mode at all.
544+
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
545+
add_library(StaticAnalysisSupport OBJECT ${TESTS_DIR}/X08-StaticAnalysisSupport.cpp)
546+
target_link_libraries(StaticAnalysisSupport PRIVATE Catch2::Catch2WithMain)
547+
target_compile_definitions(StaticAnalysisSupport
548+
PRIVATE
549+
CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
550+
)
551+
# The mode's `TEST_CASE` expansion uses `[[maybe_unused]]`, which is
552+
# a C++17 extension in C++14, and the build compiles with -Wpedantic.
553+
target_compile_features(StaticAnalysisSupport PRIVATE cxx_std_17)
554+
endif()
555+
542556
# This sets up a one-off executable that compiles against the amalgamated
543557
# files, and then runs it for a super simple check that the amalgamated
544558
# files are usable.
@@ -654,6 +668,10 @@ set(EXTRA_TEST_BINARIES
654668
# DebugBreakMacros
655669
)
656670

671+
if(TARGET StaticAnalysisSupport)
672+
list(APPEND EXTRA_TEST_BINARIES StaticAnalysisSupport)
673+
endif()
674+
657675
# Notice that we are modifying EXTRA_TEST_BINARIES destructively, do not
658676
# use it after this point!
659677
list(FILTER EXTRA_TEST_BINARIES EXCLUDE REGEX "DisabledExceptions.*")
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
2+
// Copyright Catch2 Authors
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE.txt or copy at
5+
// https://www.boost.org/LICENSE_1_0.txt)
6+
7+
// SPDX-License-Identifier: BSL-1.0
8+
9+
/**\file
10+
* Test that the macros compile with
11+
* `CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT`.
12+
*
13+
* The expansions in this mode are meant to be scanned, not run, and use
14+
* symbols that are left undefined on purpose.
15+
*
16+
* The compilation itself is the test.
17+
*/
18+
19+
#include <catch2/catch_test_macros.hpp>
20+
#include <catch2/matchers/catch_matchers_exception.hpp>
21+
#include <catch2/matchers/catch_matchers_string.hpp>
22+
23+
#include <stdexcept>
24+
#include <string>
25+
26+
// Left undefined on purpose. Their results are opaque to the compiler.
27+
int const* make_pointer();
28+
std::string make_string();
29+
30+
namespace {
31+
32+
[[noreturn]]
33+
void throws() {
34+
throw std::runtime_error( "some exception" );
35+
}
36+
void doesnt_throw() {}
37+
38+
} // namespace
39+
40+
TEST_CASE( "REQUIRE and CHECK" ) {
41+
int const* const ptr = make_pointer();
42+
43+
REQUIRE( ptr );
44+
CHECK( *ptr == 42 );
45+
46+
REQUIRE_FALSE( ptr == nullptr );
47+
CHECK_FALSE( ptr == nullptr );
48+
CHECK_NOFAIL( *ptr == 42 );
49+
}
50+
51+
TEST_CASE( "CHECKED_IF and CHECKED_ELSE" ) {
52+
int const* const ptr = make_pointer();
53+
54+
CHECKED_IF( ptr ) {
55+
CHECK( *ptr == 42 );
56+
}
57+
CHECKED_ELSE( ptr ) {
58+
CHECK_FALSE( ptr );
59+
}
60+
}
61+
62+
TEST_CASE( "Exception assertions" ) {
63+
REQUIRE_NOTHROW( doesnt_throw() );
64+
CHECK_NOTHROW( doesnt_throw() );
65+
66+
REQUIRE_THROWS( throws() );
67+
CHECK_THROWS( throws() );
68+
69+
REQUIRE_THROWS_AS( throws(), std::runtime_error );
70+
CHECK_THROWS_AS( throws(), std::runtime_error );
71+
}
72+
73+
// The matcher-based assertions are not modelled for static analysis atm,
74+
// but they still have to compile in this mode.
75+
TEST_CASE( "Matcher assertions" ) {
76+
using namespace Catch::Matchers;
77+
78+
REQUIRE_THAT( make_string(), StartsWith( "some" ) );
79+
CHECK_THAT( make_string(), Equals( "some string" ) );
80+
81+
REQUIRE_THROWS_WITH( throws(), "some exception" );
82+
CHECK_THROWS_WITH( throws(), ContainsSubstring( "exception" ) );
83+
84+
REQUIRE_THROWS_MATCHES(
85+
throws(), std::runtime_error, Message( "some exception" ) );
86+
CHECK_THROWS_MATCHES(
87+
throws(), std::runtime_error, Message( "some exception" ) );
88+
}
89+
90+
TEST_CASE( "Non-assertion macros" ) {
91+
STATIC_REQUIRE( 1 + 1 == 2 );
92+
STATIC_REQUIRE_FALSE( 1 + 1 == 3 );
93+
STATIC_CHECK( 1 + 1 == 2 );
94+
STATIC_CHECK_FALSE( 1 + 1 == 3 );
95+
96+
SUCCEED( "succeeded" );
97+
98+
if ( make_pointer() ) {
99+
FAIL( "failed" );
100+
}
101+
SKIP( "skipped" );
102+
}

0 commit comments

Comments
 (0)