aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/testkit/test_hook.cpp
blob: 5b618beb01b500a3ced88627fdac8363fdea666d (plain) (blame)
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