aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/testkit/test_master.h
blob: 40ce9be3dc6b43a002429ffc83100d6688b3d01a (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include <string>
#include <vector>
#include <memory>
#include <mutex>

namespace vespalib {

class Barrier;

#ifndef IAM_DOXYGEN
/**
 * The master of testing.
 **/
class TestMaster
{
private:
    TestMaster(const TestMaster &);
    TestMaster &operator=(const TestMaster &);

public:
    struct Progress {
        size_t passCnt;
        size_t failCnt;
        Progress(size_t pass, size_t fail) : passCnt(pass), failCnt(fail) {}
    };

    struct Unwind {};

    static TestMaster master;

    struct TraceItem {
        std::string file;
        uint32_t    line;
        std::string msg;
        TraceItem(const std::string &file_in, uint32_t line_in, const std::string &msg_in);
        TraceItem(TraceItem &&) noexcept;
        TraceItem & operator=(TraceItem &&) noexcept;
        TraceItem(const TraceItem &);
        TraceItem & operator=(const TraceItem &);
        ~TraceItem();
    };

private:
    struct ThreadState {
        std::string            name;
        bool                   unwind;
        size_t                 passCnt;
        size_t                 failCnt;
        bool                   ignore;
        size_t                 preIgnoreFailCnt;
        std::vector<TraceItem> traceStack;
        Barrier               *barrier;
        ThreadState(const std::string &n)
            : name(n), unwind(false), passCnt(0),
              failCnt(0), ignore(false), preIgnoreFailCnt(0), traceStack(),
              barrier(0) {}
    };
    static __thread ThreadState *_threadState;

    struct SharedState {
        size_t         passCnt;
        size_t         failCnt;
        FILE          *lhsFile;
        FILE          *rhsFile;
        SharedState() : passCnt(0), failCnt(0),
                        lhsFile(0), rhsFile(0) {}
    };

private:
    std::mutex                                     _lock;
    std::string                                    _name;
    std::string                                    _path_prefix;
    SharedState                                    _state;
    std::vector<std::unique_ptr<ThreadState> > _threadStorage;
    using lock_guard = std::lock_guard<std::mutex>;

private:
    ThreadState &threadState(const lock_guard &);
    ThreadState &threadState();
    void checkFailed(const lock_guard &,
                     const char *file, uint32_t line, const char *str);
    void printDiff(const lock_guard &,
                   const std::string &text, const std::string &file, uint32_t line,
                   const std::string &lhs, const std::string &rhs);
    void handleFailure(const lock_guard &, bool do_abort);
    void closeDebugFiles(const lock_guard &);
    void importThreads(const lock_guard &);
    bool reportConclusion(const lock_guard &);

private:
    TestMaster();

public:
    void init(const char *name);
    std::string getName();
    std::string get_path(const std::string &local_file);
    void setThreadName(const char *name);
    const char *getThreadName();
    void setThreadUnwind(bool unwind);
    void setThreadIgnore(bool ignore);
    void setThreadBarrier(Barrier *barrier);
    void awaitThreadBarrier(const char *file, uint32_t line);
    std::vector<TraceItem> getThreadTraceStack();
    void setThreadTraceStack(const std::vector<TraceItem> &traceStack);
    size_t getThreadFailCnt();
    Progress getProgress();
    void openDebugFiles(const std::string &lhsFile, const std::string &rhsFile);
    void pushState(const char *file, uint32_t line, const char *msg);
    void popState();
    bool check(bool rc, const char *file, uint32_t line,
               const char *str, bool fatal);
    template<class A, class B, class OP>
    bool compare(const char *file, uint32_t line,
                 const char *aName, const char *bName, const char *opText,
                 const A &a, const B &b, const OP &op, bool fatal);
    void flush(const char *file, uint32_t line);
    void trace(const char *file, uint32_t line);
    bool discardFailedChecks(size_t failCnt);
    bool fini();
};
#endif

} // namespace vespalib

#include "test_master.hpp"