mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 21:36:11 +01:00
4565b826cf
This means that code such as ```cpp TEST_CASE() { SECTION("first") { SUCCEED(); } auto _ = GENERATE(1, 2); SECTION("second") { SUCCEED(); } } ``` will run and report 3 assertions, 1 from section "first" and 2 from section "second". This also applies for greater and potentially more confusing nesting, but fundamentally it is up to the user to avoid overly complex and confusing nestings, just as with `SECTION`s. The old behaviour of `GENERATE` as first thing in a `TEST_CASE`, `GENERATE` not followed by a `SECTION`, etc etc should be unchanged. Closes #1938
252 lines
7.5 KiB
C++
252 lines
7.5 KiB
C++
/*
|
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include <catch2/generators/catch_generators.hpp>
|
|
#include <catch2/internal/catch_test_case_tracker.hpp>
|
|
|
|
|
|
using namespace Catch;
|
|
|
|
namespace {
|
|
Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) {
|
|
return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) );
|
|
}
|
|
}
|
|
|
|
TEST_CASE( "Tracker" ) {
|
|
|
|
TrackerContext ctx;
|
|
ctx.startRun();
|
|
ctx.startCycle();
|
|
|
|
|
|
ITracker& testCase = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
REQUIRE( testCase.isOpen() );
|
|
|
|
ITracker& s1 = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
REQUIRE( s1.isOpen() );
|
|
|
|
SECTION( "successfully close one section" ) {
|
|
s1.close();
|
|
REQUIRE( s1.isSuccessfullyCompleted() );
|
|
REQUIRE( testCase.isComplete() == false );
|
|
|
|
testCase.close();
|
|
REQUIRE( ctx.completedCycle() );
|
|
REQUIRE( testCase.isSuccessfullyCompleted() );
|
|
}
|
|
|
|
SECTION( "fail one section" ) {
|
|
s1.fail();
|
|
REQUIRE( s1.isComplete() );
|
|
REQUIRE( s1.isSuccessfullyCompleted() == false );
|
|
REQUIRE( testCase.isComplete() == false );
|
|
|
|
testCase.close();
|
|
REQUIRE( ctx.completedCycle() );
|
|
REQUIRE( testCase.isSuccessfullyCompleted() == false );
|
|
|
|
SECTION( "re-enter after failed section" ) {
|
|
ctx.startCycle();
|
|
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
REQUIRE( testCase2.isOpen() );
|
|
|
|
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
REQUIRE( s1b.isOpen() == false );
|
|
|
|
testCase2.close();
|
|
REQUIRE( ctx.completedCycle() );
|
|
REQUIRE( testCase.isComplete() );
|
|
REQUIRE( testCase.isSuccessfullyCompleted() );
|
|
}
|
|
SECTION( "re-enter after failed section and find next section" ) {
|
|
ctx.startCycle();
|
|
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
REQUIRE( testCase2.isOpen() );
|
|
|
|
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
REQUIRE( s1b.isOpen() == false );
|
|
|
|
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
REQUIRE( s2.isOpen() );
|
|
|
|
s2.close();
|
|
REQUIRE( ctx.completedCycle() );
|
|
|
|
testCase2.close();
|
|
REQUIRE( testCase.isComplete() );
|
|
REQUIRE( testCase.isSuccessfullyCompleted() );
|
|
}
|
|
}
|
|
|
|
SECTION( "successfully close one section, then find another" ) {
|
|
s1.close();
|
|
|
|
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
REQUIRE( s2.isOpen() == false );
|
|
|
|
testCase.close();
|
|
REQUIRE( testCase.isComplete() == false );
|
|
|
|
SECTION( "Re-enter - skips S1 and enters S2" ) {
|
|
ctx.startCycle();
|
|
ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
REQUIRE( testCase2.isOpen() );
|
|
|
|
ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
REQUIRE( s1b.isOpen() == false );
|
|
|
|
ITracker& s2b = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
REQUIRE( s2b.isOpen() );
|
|
|
|
REQUIRE( ctx.completedCycle() == false );
|
|
|
|
SECTION ("Successfully close S2") {
|
|
s2b.close();
|
|
REQUIRE( ctx.completedCycle() );
|
|
|
|
REQUIRE( s2b.isSuccessfullyCompleted() );
|
|
REQUIRE( testCase2.isComplete() == false );
|
|
|
|
testCase2.close();
|
|
REQUIRE( testCase2.isSuccessfullyCompleted() );
|
|
}
|
|
SECTION ("fail S2") {
|
|
s2b.fail();
|
|
REQUIRE( ctx.completedCycle() );
|
|
|
|
REQUIRE( s2b.isComplete() );
|
|
REQUIRE( s2b.isSuccessfullyCompleted() == false );
|
|
|
|
testCase2.close();
|
|
REQUIRE( testCase2.isSuccessfullyCompleted() == false );
|
|
|
|
// Need a final cycle
|
|
ctx.startCycle();
|
|
ITracker& testCase3 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
|
|
REQUIRE( testCase3.isOpen() );
|
|
|
|
ITracker& s1c = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
|
|
REQUIRE( s1c.isOpen() == false );
|
|
|
|
ITracker& s2c = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
REQUIRE( s2c.isOpen() == false );
|
|
|
|
testCase3.close();
|
|
REQUIRE( testCase3.isSuccessfullyCompleted() );
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION( "open a nested section" ) {
|
|
ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
|
|
REQUIRE( s2.isOpen() );
|
|
|
|
s2.close();
|
|
REQUIRE( s2.isComplete() );
|
|
REQUIRE( s1.isComplete() == false );
|
|
|
|
s1.close();
|
|
REQUIRE( s1.isComplete() );
|
|
REQUIRE( testCase.isComplete() == false );
|
|
|
|
testCase.close();
|
|
REQUIRE( testCase.isComplete() );
|
|
}
|
|
}
|
|
|
|
static bool previouslyRun = false;
|
|
static bool previouslyRunNested = false;
|
|
|
|
TEST_CASE( "#1394", "[.][approvals][tracker]" ) {
|
|
// -- Don't re-run after specified section is done
|
|
REQUIRE(previouslyRun == false);
|
|
|
|
SECTION( "RunSection" ) {
|
|
previouslyRun = true;
|
|
}
|
|
SECTION( "SkipSection" ) {
|
|
// cause an error if this section is called because it shouldn't be
|
|
REQUIRE(1 == 0);
|
|
}
|
|
}
|
|
|
|
TEST_CASE( "#1394 nested", "[.][approvals][tracker]" ) {
|
|
REQUIRE(previouslyRunNested == false);
|
|
|
|
SECTION( "NestedRunSection" ) {
|
|
SECTION( "s1" ) {
|
|
previouslyRunNested = true;
|
|
}
|
|
}
|
|
SECTION( "NestedSkipSection" ) {
|
|
// cause an error if this section is called because it shouldn't be
|
|
REQUIRE(1 == 0);
|
|
}
|
|
}
|
|
|
|
// Selecting a "not last" section inside a test case via -c "section" would
|
|
// previously only run the first subsection, instead of running all of them.
|
|
// This allows us to check that `"#1670 regression check" -c A` leads to
|
|
// 2 successful assertions.
|
|
TEST_CASE("#1670 regression check", "[.approvals][tracker]") {
|
|
SECTION("A") {
|
|
SECTION("1") SUCCEED();
|
|
SECTION("2") SUCCEED();
|
|
}
|
|
SECTION("B") {
|
|
SECTION("1") SUCCEED();
|
|
SECTION("2") SUCCEED();
|
|
}
|
|
}
|
|
|
|
// #1938 required a rework on how generator tracking works, so that `GENERATE`
|
|
// supports being sandwiched between two `SECTION`s. The following tests check
|
|
// various other scenarios through checking output in approval tests.
|
|
TEST_CASE("#1938 - GENERATE after a section", "[.][regression][generators]") {
|
|
SECTION("A") {
|
|
SUCCEED("A");
|
|
}
|
|
auto m = GENERATE(1, 2, 3);
|
|
SECTION("B") {
|
|
REQUIRE(m);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("#1938 - flat generate", "[.][regression][generators]") {
|
|
auto m = GENERATE(1, 2, 3);
|
|
REQUIRE(m);
|
|
}
|
|
|
|
TEST_CASE("#1938 - nested generate", "[.][regression][generators]") {
|
|
auto m = GENERATE(1, 2, 3);
|
|
auto n = GENERATE(1, 2, 3);
|
|
REQUIRE(m);
|
|
REQUIRE(n);
|
|
}
|
|
|
|
TEST_CASE("#1938 - mixed sections and generates", "[.][regression][generators]") {
|
|
auto i = GENERATE(1, 2);
|
|
SECTION("A") {
|
|
SUCCEED("A");
|
|
}
|
|
auto j = GENERATE(3, 4);
|
|
SECTION("B") {
|
|
SUCCEED("B");
|
|
}
|
|
auto k = GENERATE(5, 6);
|
|
CAPTURE(i, j, k);
|
|
SUCCEED();
|
|
}
|
|
|
|
TEST_CASE("#1938 - Section followed by flat generate", "[.][regression][generators]") {
|
|
SECTION("A") {
|
|
REQUIRE(1);
|
|
}
|
|
auto m = GENERATE(2, 3);
|
|
REQUIRE(m);
|
|
}
|