summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoronqtam <vik.kirilov@gmail.com>2019-09-22 17:34:50 +0300
committeronqtam <vik.kirilov@gmail.com>2019-09-22 21:14:41 +0300
commitdca8b66f8785683097a3c0136c57941505d0adce (patch)
tree4bc76cf2394e8f49bb800acd4399d995899bc770
parent5856bb93a63c43c6562eb2773d9a3d4d6f677f15 (diff)
fixed #282
-rw-r--r--doctest/doctest.h59
-rw-r--r--doctest/parts/doctest.cpp54
-rw-r--r--doctest/parts/doctest_fwd.h5
-rw-r--r--examples/all_features/subcases.cpp24
-rw-r--r--examples/all_features/test_output/filter_2.txt2
-rw-r--r--examples/all_features/test_output/filter_2_xml.txt3
-rw-r--r--examples/all_features/test_output/filter_3.txt2
-rw-r--r--examples/all_features/test_output/filter_3_xml.txt5
-rw-r--r--examples/all_features/test_output/subcases.cpp.txt4
-rw-r--r--examples/all_features/test_output/subcases.cpp_xml.txt23
-rw-r--r--scripts/coverage_maxout.cpp2
11 files changed, 110 insertions, 73 deletions
diff --git a/doctest/doctest.h b/doctest/doctest.h
index 037dd56..59fcd65 100644
--- a/doctest/doctest.h
+++ b/doctest/doctest.h
@@ -701,12 +701,7 @@ struct DOCTEST_INTERFACE SubcaseSignature
const char* m_file;
int m_line;
- SubcaseSignature(const char* name, const char* file, int line);
-
bool operator<(const SubcaseSignature& other) const;
-
- DOCTEST_DECLARE_DEFAULTS(SubcaseSignature);
- DOCTEST_DECLARE_COPIES(SubcaseSignature);
};
struct DOCTEST_INTERFACE IContextScope
@@ -2992,10 +2987,10 @@ namespace detail {
std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
// stuff for subcases
- std::set<SubcaseSignature> subcasesPassed;
- std::set<int> subcasesEnteredLevels;
- int subcasesCurrentLevel;
- bool should_reenter;
+ std::vector<SubcaseSignature> subcaseStack;
+ std::set<decltype(subcaseStack)> subcasesPassed;
+ int subcasesCurrentMaxLevel;
+ bool should_reenter;
void resetRunData() {
numTestCases = 0;
@@ -3336,14 +3331,6 @@ DOCTEST_DEFINE_DEFAULTS(AssertData);
DOCTEST_DEFINE_DEFAULTS(MessageData);
-SubcaseSignature::SubcaseSignature(const char* name, const char* file, int line)
- : m_name(name)
- , m_file(file)
- , m_line(line) {}
-
-DOCTEST_DEFINE_DEFAULTS(SubcaseSignature);
-DOCTEST_DEFINE_COPIES(SubcaseSignature);
-
bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
if(m_line != other.m_line)
return m_line < other.m_line;
@@ -3592,28 +3579,33 @@ namespace {
namespace detail {
Subcase::Subcase(const char* name, const char* file, int line)
- : m_signature(name, file, line) {
+ : m_signature({name, file, line}) {
ContextState* s = g_cs;
- // if we have already completed it
- if(s->subcasesPassed.count(m_signature) != 0)
- return;
-
// check subcase filters
- if(s->subcasesCurrentLevel < s->subcase_filter_levels) {
+ if(s->subcaseStack.size() < size_t(s->subcase_filter_levels)) {
if(!matchesAny(m_signature.m_name, s->filters[6], true, s->case_sensitive))
return;
if(matchesAny(m_signature.m_name, s->filters[7], false, s->case_sensitive))
return;
}
-
+
// if a Subcase on the same level has already been entered
- if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) {
+ if(s->subcaseStack.size() < size_t(s->subcasesCurrentMaxLevel)) {
s->should_reenter = true;
return;
}
- s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++);
+ // push the current signature to the stack so we can check if the
+ // current stack + the current new subcase have been traversed
+ s->subcaseStack.push_back(m_signature);
+ if(s->subcasesPassed.count(s->subcaseStack) != 0) {
+ // pop - revert to previous stack since we've already passed this
+ s->subcaseStack.pop_back();
+ return;
+ }
+
+ s->subcasesCurrentMaxLevel = s->subcaseStack.size();
m_entered = true;
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
@@ -3623,10 +3615,11 @@ namespace detail {
if(m_entered) {
ContextState* s = g_cs;
- s->subcasesCurrentLevel--;
// only mark the subcase as passed if no subcases have been skipped
if(s->should_reenter == false)
- s->subcasesPassed.insert(m_signature);
+ s->subcasesPassed.insert(s->subcaseStack);
+
+ s->subcaseStack.pop_back();
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
}
@@ -4165,8 +4158,10 @@ namespace {
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
- while(g_cs->subcasesCurrentLevel--)
+ while(g_cs->subcaseStack.size()) {
+ g_cs->subcaseStack.pop_back();
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
+ }
g_cs->finalizeTestCaseData();
@@ -5907,9 +5902,9 @@ int Context::run() {
do {
// reset some of the fields for subcases (except for the set of fully passed ones)
- p->should_reenter = false;
- p->subcasesCurrentLevel = 0;
- p->subcasesEnteredLevels.clear();
+ p->should_reenter = false;
+ p->subcasesCurrentMaxLevel = 0;
+ p->subcaseStack.clear();
// reset stuff for logging with INFO()
p->stringifiedContexts.clear();
diff --git a/doctest/parts/doctest.cpp b/doctest/parts/doctest.cpp
index ab9df2e..4187884 100644
--- a/doctest/parts/doctest.cpp
+++ b/doctest/parts/doctest.cpp
@@ -315,10 +315,10 @@ namespace detail {
std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
// stuff for subcases
- std::set<SubcaseSignature> subcasesPassed;
- std::set<int> subcasesEnteredLevels;
- int subcasesCurrentLevel;
- bool should_reenter;
+ std::vector<SubcaseSignature> subcaseStack;
+ std::set<decltype(subcaseStack)> subcasesPassed;
+ int subcasesCurrentMaxLevel;
+ bool should_reenter;
void resetRunData() {
numTestCases = 0;
@@ -659,14 +659,6 @@ DOCTEST_DEFINE_DEFAULTS(AssertData);
DOCTEST_DEFINE_DEFAULTS(MessageData);
-SubcaseSignature::SubcaseSignature(const char* name, const char* file, int line)
- : m_name(name)
- , m_file(file)
- , m_line(line) {}
-
-DOCTEST_DEFINE_DEFAULTS(SubcaseSignature);
-DOCTEST_DEFINE_COPIES(SubcaseSignature);
-
bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
if(m_line != other.m_line)
return m_line < other.m_line;
@@ -915,28 +907,33 @@ namespace {
namespace detail {
Subcase::Subcase(const char* name, const char* file, int line)
- : m_signature(name, file, line) {
+ : m_signature({name, file, line}) {
ContextState* s = g_cs;
- // if we have already completed it
- if(s->subcasesPassed.count(m_signature) != 0)
- return;
-
// check subcase filters
- if(s->subcasesCurrentLevel < s->subcase_filter_levels) {
+ if(s->subcaseStack.size() < size_t(s->subcase_filter_levels)) {
if(!matchesAny(m_signature.m_name, s->filters[6], true, s->case_sensitive))
return;
if(matchesAny(m_signature.m_name, s->filters[7], false, s->case_sensitive))
return;
}
-
+
// if a Subcase on the same level has already been entered
- if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) {
+ if(s->subcaseStack.size() < size_t(s->subcasesCurrentMaxLevel)) {
s->should_reenter = true;
return;
}
- s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++);
+ // push the current signature to the stack so we can check if the
+ // current stack + the current new subcase have been traversed
+ s->subcaseStack.push_back(m_signature);
+ if(s->subcasesPassed.count(s->subcaseStack) != 0) {
+ // pop - revert to previous stack since we've already passed this
+ s->subcaseStack.pop_back();
+ return;
+ }
+
+ s->subcasesCurrentMaxLevel = s->subcaseStack.size();
m_entered = true;
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
@@ -946,10 +943,11 @@ namespace detail {
if(m_entered) {
ContextState* s = g_cs;
- s->subcasesCurrentLevel--;
// only mark the subcase as passed if no subcases have been skipped
if(s->should_reenter == false)
- s->subcasesPassed.insert(m_signature);
+ s->subcasesPassed.insert(s->subcaseStack);
+
+ s->subcaseStack.pop_back();
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
}
@@ -1488,8 +1486,10 @@ namespace {
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
- while(g_cs->subcasesCurrentLevel--)
+ while(g_cs->subcaseStack.size()) {
+ g_cs->subcaseStack.pop_back();
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
+ }
g_cs->finalizeTestCaseData();
@@ -3230,9 +3230,9 @@ int Context::run() {
do {
// reset some of the fields for subcases (except for the set of fully passed ones)
- p->should_reenter = false;
- p->subcasesCurrentLevel = 0;
- p->subcasesEnteredLevels.clear();
+ p->should_reenter = false;
+ p->subcasesCurrentMaxLevel = 0;
+ p->subcaseStack.clear();
// reset stuff for logging with INFO()
p->stringifiedContexts.clear();
diff --git a/doctest/parts/doctest_fwd.h b/doctest/parts/doctest_fwd.h
index 0e9938e..ad8345d 100644
--- a/doctest/parts/doctest_fwd.h
+++ b/doctest/parts/doctest_fwd.h
@@ -698,12 +698,7 @@ struct DOCTEST_INTERFACE SubcaseSignature
const char* m_file;
int m_line;
- SubcaseSignature(const char* name, const char* file, int line);
-
bool operator<(const SubcaseSignature& other) const;
-
- DOCTEST_DECLARE_DEFAULTS(SubcaseSignature);
- DOCTEST_DECLARE_COPIES(SubcaseSignature);
};
struct DOCTEST_INTERFACE IContextScope
diff --git a/examples/all_features/subcases.cpp b/examples/all_features/subcases.cpp
index 8fb49a9..8becba0 100644
--- a/examples/all_features/subcases.cpp
+++ b/examples/all_features/subcases.cpp
@@ -113,3 +113,27 @@ TEST_CASE("fails from an exception but gets re-entered to traverse all subcases"
throw_if(true, "failure... but the show must go on!");
}
}
+
+static void checks(int data)
+{
+ DOCTEST_SUBCASE("check data 1") { REQUIRE(data % 2 == 0); }
+ DOCTEST_SUBCASE("check data 2") { REQUIRE(data % 4 == 0); }
+}
+
+TEST_CASE("Nested - related to https://github.com/onqtam/doctest/issues/282")
+{
+ DOCTEST_SUBCASE("generate data variant 1")
+ {
+ int data(44);
+
+ // checks
+ checks(data);
+ }
+ DOCTEST_SUBCASE("generate data variant 1")
+ {
+ int data(80);
+
+ // checks (identical in both variants)
+ checks(data);
+ }
+}
diff --git a/examples/all_features/test_output/filter_2.txt b/examples/all_features/test_output/filter_2.txt
index 2c565bb..bb80ff8 100644
--- a/examples/all_features/test_output/filter_2.txt
+++ b/examples/all_features/test_output/filter_2.txt
@@ -1,6 +1,6 @@
[doctest] run with "--help" for options
===============================================================================
-[doctest] test cases: 0 | 0 passed | 0 failed | 76 skipped
+[doctest] test cases: 0 | 0 passed | 0 failed | 77 skipped
[doctest] assertions: 0 | 0 passed | 0 failed |
[doctest] Status: SUCCESS!
Program code.
diff --git a/examples/all_features/test_output/filter_2_xml.txt b/examples/all_features/test_output/filter_2_xml.txt
index 4a6a03a..8539325 100644
--- a/examples/all_features/test_output/filter_2_xml.txt
+++ b/examples/all_features/test_output/filter_2_xml.txt
@@ -4,6 +4,7 @@
<TestSuite>
<TestCase name=" Scenario: vectors can be sized and resized" filename="subcases.cpp" line="0" skipped="true"/>
<TestCase name="CHECK level of asserts fail the test case but don't abort it" filename="assertion_macros.cpp" line="0" skipped="true"/>
+ <TestCase name="Nested - related to https://github.com/onqtam/doctest/issues/282" filename="subcases.cpp" line="0" skipped="true"/>
<TestCase name="REQUIRE level of asserts fail and abort the test case - 1" filename="assertion_macros.cpp" line="0" skipped="true"/>
<TestCase name="REQUIRE level of asserts fail and abort the test case - 10" filename="assertion_macros.cpp" line="0" skipped="true"/>
<TestCase name="REQUIRE level of asserts fail and abort the test case - 11" filename="assertion_macros.cpp" line="0" skipped="true"/>
@@ -114,6 +115,6 @@
<TestCase name="will end from an unknown exception" filename="coverage_maxout.cpp" line="0" skipped="true"/>
</TestSuite>
<OverallResultsAsserts successes="0" failures="0"/>
- <OverallResultsTestCases successes="0" failures="0" skipped="76"/>
+ <OverallResultsTestCases successes="0" failures="0" skipped="77"/>
</doctest>
Program code.
diff --git a/examples/all_features/test_output/filter_3.txt b/examples/all_features/test_output/filter_3.txt
index f61eb82..c0cb430 100644
--- a/examples/all_features/test_output/filter_3.txt
+++ b/examples/all_features/test_output/filter_3.txt
@@ -23,7 +23,7 @@ TEST CASE: subcases can be used in a separate function as well
subcases.cpp(0): MESSAGE: lala
===============================================================================
-[doctest] test cases: 5 | 5 passed | 0 failed |
+[doctest] test cases: 6 | 6 passed | 0 failed |
[doctest] assertions: 0 | 0 passed | 0 failed |
[doctest] Status: SUCCESS!
Program code.
diff --git a/examples/all_features/test_output/filter_3_xml.txt b/examples/all_features/test_output/filter_3_xml.txt
index c363fa4..3e56aa9 100644
--- a/examples/all_features/test_output/filter_3_xml.txt
+++ b/examples/all_features/test_output/filter_3_xml.txt
@@ -38,8 +38,11 @@ root
<TestCase name="fails from an exception but gets re-entered to traverse all subcases" filename="subcases.cpp" line="0">
<OverallResultsAsserts successes="0" failures="0"/>
</TestCase>
+ <TestCase name="Nested - related to https://github.com/onqtam/doctest/issues/282" filename="subcases.cpp" line="0">
+ <OverallResultsAsserts successes="0" failures="0"/>
+ </TestCase>
</TestSuite>
<OverallResultsAsserts successes="0" failures="0"/>
- <OverallResultsTestCases successes="5" failures="0"/>
+ <OverallResultsTestCases successes="6" failures="0"/>
</doctest>
Program code.
diff --git a/examples/all_features/test_output/subcases.cpp.txt b/examples/all_features/test_output/subcases.cpp.txt
index 9204383..89151c3 100644
--- a/examples/all_features/test_output/subcases.cpp.txt
+++ b/examples/all_features/test_output/subcases.cpp.txt
@@ -117,7 +117,7 @@ TEST CASE: fails from an exception but gets re-entered to traverse all subcases
subcases.cpp(0): ERROR: test case THREW exception: failure... but the show must go on!
===============================================================================
-[doctest] test cases: 5 | 1 passed | 4 failed |
-[doctest] assertions: 21 | 15 passed | 6 failed |
+[doctest] test cases: 6 | 2 passed | 4 failed |
+[doctest] assertions: 25 | 19 passed | 6 failed |
[doctest] Status: FAILURE!
Program code.
diff --git a/examples/all_features/test_output/subcases.cpp_xml.txt b/examples/all_features/test_output/subcases.cpp_xml.txt
index c5a5b94..95bbd7f 100644
--- a/examples/all_features/test_output/subcases.cpp_xml.txt
+++ b/examples/all_features/test_output/subcases.cpp_xml.txt
@@ -163,8 +163,27 @@ root
</Exception>
<OverallResultsAsserts successes="0" failures="2"/>
</TestCase>
+ <TestCase name="Nested - related to https://github.com/onqtam/doctest/issues/282" filename="subcases.cpp" line="0">
+ <SubCase name="generate data variant 1" filename="subcases.cpp" line="0">
+ <SubCase name="check data 1" filename="subcases.cpp" line="0">
+ </SubCase>
+ </SubCase>
+ <SubCase name="generate data variant 1" filename="subcases.cpp" line="0">
+ <SubCase name="check data 2" filename="subcases.cpp" line="0">
+ </SubCase>
+ </SubCase>
+ <SubCase name="generate data variant 1" filename="subcases.cpp" line="0">
+ <SubCase name="check data 1" filename="subcases.cpp" line="0">
+ </SubCase>
+ </SubCase>
+ <SubCase name="generate data variant 1" filename="subcases.cpp" line="0">
+ <SubCase name="check data 2" filename="subcases.cpp" line="0">
+ </SubCase>
+ </SubCase>
+ <OverallResultsAsserts successes="4" failures="0"/>
+ </TestCase>
</TestSuite>
- <OverallResultsAsserts successes="15" failures="6"/>
- <OverallResultsTestCases successes="1" failures="4"/>
+ <OverallResultsAsserts successes="19" failures="6"/>
+ <OverallResultsTestCases successes="2" failures="4"/>
</doctest>
Program code.
diff --git a/scripts/coverage_maxout.cpp b/scripts/coverage_maxout.cpp
index 6cf7ed8..ed3b4fb 100644
--- a/scripts/coverage_maxout.cpp
+++ b/scripts/coverage_maxout.cpp
@@ -27,7 +27,7 @@ TEST_CASE("exercising tricky code paths of doctest") {
using namespace doctest;
// trigger code path for comparing the file in "operator<" of SubcaseSignature
- CHECK(SubcaseSignature("", "a.cpp", 0) < SubcaseSignature("", "b.cpp", 0));
+ CHECK(SubcaseSignature{"", "a.cpp", 0} < SubcaseSignature{"", "b.cpp", 0});
// same for String
CHECK(String("a.cpp") < String("b.cpp"));