-
Notifications
You must be signed in to change notification settings - Fork 9
/
snitch_section.cpp
102 lines (85 loc) · 3.73 KB
/
snitch_section.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "snitch/snitch_section.hpp"
#include "snitch/snitch_console.hpp"
#include "snitch/snitch_registry.hpp"
#if SNITCH_WITH_EXCEPTIONS
# include <exception>
#endif
namespace snitch::impl {
section_entry_checker::~section_entry_checker() {
if (entered) {
#if SNITCH_WITH_EXCEPTIONS
if (std::uncaught_exceptions() > 0) {
// We are unwinding the stack because an exception has been thrown;
// avoid touching the section state since we will want to report where
// the exception was thrown.
return;
}
#endif
pop_location(state);
if (state.sections.depth == state.sections.levels.size()) {
// We just entered this section, and there was no child section in it.
// This is a leaf; flag that a leaf has been executed so that no other leaf
// is executed in this run.
// Note: don't pop this level from the section state yet, it may have siblings
// that we don't know about yet. Popping will be done when we exit from the parent,
// since then we will know if there is any sibling.
state.sections.leaf_executed = true;
} else {
// Check if there is any child section left to execute, at any depth below this one.
bool no_child_section_left = true;
for (std::size_t c = state.sections.depth; c < state.sections.levels.size(); ++c) {
auto& child = state.sections.levels[c];
if (child.previous_section_id != child.max_section_id) {
no_child_section_left = false;
break;
}
}
if (no_child_section_left) {
// No more children, we can pop this level and never go back.
state.sections.levels.pop_back();
}
}
state.sections.current_section.pop_back();
}
--state.sections.depth;
}
section_entry_checker::operator bool() {
if (state.sections.depth >= state.sections.levels.size()) {
if (state.sections.depth >= max_nested_sections) {
using namespace snitch::impl;
state.reg.print(
make_colored("error:", state.reg.with_color, color::fail),
" max number of nested sections reached; "
"please increase 'SNITCH_MAX_NESTED_SECTIONS' (currently ",
max_nested_sections, ")\n.");
assertion_failed("max number of nested sections reached");
}
state.sections.levels.push_back({});
}
++state.sections.depth;
auto& level = state.sections.levels[state.sections.depth - 1];
++level.current_section_id;
if (level.current_section_id > level.max_section_id) {
level.max_section_id = level.current_section_id;
}
if (state.sections.leaf_executed) {
// We have already executed another leaf section; can't execute more
// on this run, so don't bother going inside this one now.
return false;
}
// Only enter this section if:
// - The section entered in the previous run was its immediate previous sibling, or
// - This section was already entered in the previous run, and child sections exist in it.
if (level.current_section_id == level.previous_section_id + 1 ||
(level.current_section_id == level.previous_section_id &&
state.sections.depth < state.sections.levels.size())) {
level.previous_section_id = level.current_section_id;
state.sections.current_section.push_back(data);
push_location(
state, {data.location.file, data.location.line, location_type::section_scope});
entered = true;
return true;
}
return false;
}
} // namespace snitch::impl