summaryrefslogtreecommitdiff
path: root/indra/test/chained_callback.h
blob: 984e2f1dbcff707c4c2238fae4bfc12914513d5b (plain)
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
/**
 * @file   chained_callback.h
 * @author Nat Goodspeed
 * @date   2020-01-03
 * @brief  Subclass of tut::callback used for chaining callbacks.
 *
 * $LicenseInfo:firstyear=2020&license=viewerlgpl$
 * Copyright (c) 2020, Linden Research, Inc.
 * $/LicenseInfo$
 */

#if ! defined(LL_CHAINED_CALLBACK_H)
#define LL_CHAINED_CALLBACK_H

#include "lltut.h"

/**
 * Derive your TUT callback from chained_callback instead of tut::callback to
 * ensure that multiple such callbacks can coexist in a given test executable.
 * The relevant callback method will be called for each callback instance in
 * reverse order of the instance's link() methods being called: the most
 * recently link()ed callback will be called first, then the previous, and so
 * forth.
 *
 * Obviously, for this to work, all relevant callbacks must be derived from
 * chained_callback instead of tut::callback. Given that, control should reach
 * each of them regardless of their construction order. The chain is
 * guaranteed to stop because the first link() call will link to test_runner's
 * default_callback, which is simply an instance of the callback() base class.
 *
 * The rule for deriving from chained_callback is that you may override any of
 * its virtual methods, but your override must at some point call the
 * corresponding chained_callback method.
 */
class chained_callback: public tut::callback
{
public:
    /**
     * Instead of calling tut::test_runner::set_callback(&your_callback), call
     * your_callback.link();
     * This uses the canonical instance of tut::test_runner.
     */
    void link()
    {
        link(tut::runner.get());
    }

    /**
     * If for some reason you have a different instance of test_runner...
     */
    void link(tut::test_runner& runner)
    {
        // Since test_runner's constructor sets a default callback,
        // get_callback() will always return a reference to a valid callback
        // instance.
        mPrev = &runner.get_callback();
        runner.set_callback(this);
    }

    /**
     * Called when new test run started.
     */
    virtual void run_started()
    {
        mPrev->run_started();
    }

    /**
     * Called when a group started
     * @param name Name of the group
     */
    virtual void group_started(const std::string& name)
    {
        mPrev->group_started(name);
    }

    /**
     * Called when a test finished.
     * @param tr Test results.
     */
    virtual void test_completed(const tut::test_result& tr)
    {
        mPrev->test_completed(tr);
    }

    /**
     * Called when a group is completed
     * @param name Name of the group
     */
    virtual void group_completed(const std::string& name)
    {
        mPrev->group_completed(name);
    }

    /**
     * Called when all tests in run completed.
     */
    virtual void run_completed()
    {
        mPrev->run_completed();
    }

private:
    tut::callback* mPrev;
};

#endif /* ! defined(LL_CHAINED_CALLBACK_H) */