aboutsummaryrefslogtreecommitdiffstats
path: root/searchsummary/src/tests/juniper/test.h
blob: f0234beddd7a38340e459d6ced8c662b3bfc7369 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**************************************************************************
 * Author: Bård Kvalheim
 *
 * The test class of the testsuite. Written by Chuck Allison.
 * http://www.cuj.com/archive/1809/feature.html
 *
 * Apart for a trick the usage of the test class is very simple:
 *
 * mytest.h:
 * ----
 * #include <iosfwd>
 * #include <vespa/fastlib/testsuite/test.h>
 *
 * class MyTest : public Test
 * {
 * public:
 *   virtual void Run() {
 *     // do the tests _test is ok if the argument are true
 *     _test(expr);
 *   }
 *
 * };
 *
 * class MyTestApp
 * {
 * public:
 *   int Main();
 * };
 *
 *
 * ----
 *
 *
 * mytest.cpp:
 * ----
 * #include "mytest.h"
 *
 * int MyTestApp::Main()
 * {
 *   MyTest mt;
 *   mt.SetStream(&std::cout);
 *   mt.Run();
 *   mt.Report();
 *
 *   return 0;
 * }
 *
 *
 * ----
 *
 * The trick is that the all the code except the main function is in
 * the .h file. The reason for this is that it is simpler to integerate
 * the single test into a suite of tests.
 *
 *************************************************************************/

#pragma once

#include <string>
#include <iostream>
#include <typeinfo>
#include <vector>
#include <algorithm>
#include <iterator>

// The following have underscores because they are macros
// (and it's impolite to usurp other users' functions!).
// For consistency, _succeed() also has an underscore.
#define _test(cond) do_test((cond), #cond, __FILE__, __LINE__)
#define _test_equal(lhs, rhs)                                   \
    do_equality_test((lhs), (rhs),  #lhs, __FILE__, __LINE__)
#define _fail(str) do_fail((str), __FILE__, __LINE__)

namespace fast::testsuite {

class Test
{
public:
    explicit Test(std::ostream* osptr = 0, const char *name = NULL);
    explicit Test(const char *name);
    virtual ~Test(){}
    virtual void Run() = 0;

    const char *get_name() const;
    static const std::string& GetSourceDirectory();
    long GetNumPassed() const;
    long GetNumFailed() const;
    const std::ostream* GetStream() const;
    void SetStream(std::ostream* osptr);

    void _Succeed();
    long Report(int padSpaces = 1) const;
    virtual void Reset();

    void PushDesc(const std::string& desc);
    void PopDesc();

protected:
    std::ostream* m_osptr;
    const char *name_;

    bool do_test(bool cond, const std::string& lbl,
                 const char* fname, long lineno);
    bool do_fail(const std::string& lbl, const char* fname, long lineno,
                 bool addEndl = true);
    template <typename t1, typename t2>
    bool do_equality_test(const t1& lhs, const t2& rhs,
                          const char* lbl, const char* fname, long lineno);
    virtual void print_progress();

private:
    long m_nPass;
    long m_nFail;
    int m_index;
    char m_pchar[4];

    std::vector<std::string> m_description;

    size_t print_desc() const;

    // Disallowed:
    Test(const Test&);
    Test& operator=(const Test&);
};

template <typename t1, typename t2>
bool Test::do_equality_test(const t1& lhs, const t2& rhs, const char* lbl,
                            const char* fname, long lineno)
{
    if (lhs == rhs) {
        _Succeed();
        print_progress();
        return true;
    }
    do_fail(std::string(lbl), fname, lineno, false);
    if (m_osptr) {
        *m_osptr << "Equality test failed: "
                 << "Expected '" << rhs
                 << "' got '" << lhs << "'"
                 << std::endl;
        if (print_desc() > 0)
            *m_osptr << std::endl << std::endl;
    }
    return false;
}

}

using fast::testsuite::Test;