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
103
104
105
106
107
108
109
110
111
112
113
114
115
|
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "test_hook.h"
#include <vespa/vespalib/util/stringfmt.h>
#include <vespa/vespalib/util/size_literals.h>
#include <regex>
namespace vespalib {
void
TestThreadWrapper::threadEntry()
{
TestMaster &master = TestMaster::master;
std::string oldThreadName = master.getThreadName();
std::vector<TestMaster::TraceItem> oldTraceStack = master.getThreadTraceStack();
master.setThreadName(make_string("%zu(%zu)", _fixture.thread_id, _fixture.num_threads).c_str());
master.setThreadTraceStack(_traceStack);
size_t preThreadFailCnt = master.getThreadFailCnt();
master.setThreadIgnore(_ignore);
master.setThreadUnwind(true);
master.setThreadBarrier(&_barrier);
_barrier.await();
try {
_fixture.test_entry_point();
} catch (TestMaster::Unwind &) {
} catch (std::exception &e) {
master.check(false, __FILE__, __LINE__, e.what(), false);
} catch (...) {
master.check(false, __FILE__, __LINE__, "test threw stuff", false);
}
_barrier.destroy();
master.setThreadBarrier(0);
bool fail = (master.getThreadFailCnt() > preThreadFailCnt);
master.setThreadUnwind(false);
master.setThreadIgnore(false);
_result = !fail;
_latch.countDown();
master.setThreadTraceStack(oldTraceStack);
master.setThreadName(oldThreadName.c_str());
}
TestHook *TestHook::_head = 0;
TestHook *TestHook::_tail = 0;
TestHook::TestHook(const std::string &file, const std::string &name, bool ignore)
: _next(0),
_name(name),
_tag(make_string("%s:%s", file.c_str(), name.c_str())),
_ignore(ignore)
{
if (_head == 0) {
assert(_tail == 0);
_head = this;
_tail = this;
} else {
assert(_tail != 0);
assert(_tail->_next == 0);
_tail->_next = this;
_tail = this;
}
}
const char *lookup_subset_pattern(const std::string &name) {
const char *pattern = getenv("TEST_SUBSET");
if (pattern != 0) {
fprintf(stderr, "%s: info: only running tests matching '%s'\n",
name.c_str(), pattern);
} else {
pattern = "";
}
return pattern;
}
void
TestHook::runAll()
{
std::string name = TestMaster::master.getName();
std::regex pattern(lookup_subset_pattern(name));
size_t testsPassed = 0;
size_t testsFailed = 0;
size_t testsIgnored = 0;
size_t testsSkipped = 0;
for (TestHook *test = _head; test != 0; test = test->_next) {
if (std::regex_search(test->_tag, pattern)) {
bool ignored = test->_ignore;
bool failed = !test->run();
if (ignored) {
++testsIgnored;
} else if (failed) {
++testsFailed;
} else {
++testsPassed;
}
const char *level = ignored ? "Warn: " : failed ? "ERROR:" : "info: ";
fprintf(stderr, "%s: %s status_for_test '%s': %s%s\n",
name.c_str(), level, test->_name.c_str(),
failed ? "FAIL" : "PASS",
ignored ? " (ignored)" : "");
} else {
++testsSkipped;
}
}
fprintf(stderr, "%s: info: test summary --- %zu test(s) passed --- %zu test(s) failed\n",
name.c_str(), testsPassed, testsFailed);
if (testsSkipped > 0) {
fprintf(stderr, "%s: info: test summary --- %zu test(s) skipped\n",
name.c_str(), testsSkipped);
}
if (testsIgnored > 0) {
fprintf(stderr, "%s: Warn: test summary --- %zu test(s) ignored\n",
name.c_str(), testsIgnored);
}
}
} // namespace vespalib
|