aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/testing/hook/hook.h
blob: 1287e946c0e4b73a20288ea57f8908d6ebb7b35a (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
#pragma once 
 
namespace NTesting { 
    /** 
     * Hook class and registration system. 
     * 
     * Default implementation of the `main` function for G_BENCHMARK and GTEST calls these hooks when executing. 
     * This is a useful feature if you want to customize behaviour of the `main` function, 
     * but you don't want to write `main` yourself. 
     * 
     * Hooks form an intrusive linked list that's built at application startup. Note that hooks execute 
     * in arbitrary order. 
     * 
     * Use macros below to define hooks. 
     */ 
    struct THook { 
        using TFn = void (*)(); 
 
        TFn Fn = nullptr; 
        THook* Next = nullptr; 
 
        static void RegisterBeforeInit(THook* hook) noexcept; 
 
        static void CallBeforeInit(); 
 
        struct TRegisterBeforeInit { 
            explicit TRegisterBeforeInit(THook* hook) noexcept { 
                THook::RegisterBeforeInit(hook); 
            } 
        }; 
 
        static void RegisterBeforeRun(THook* hook) noexcept; 
 
        static void CallBeforeRun(); 
 
        struct TRegisterBeforeRun { 
            explicit TRegisterBeforeRun(THook* hook) noexcept { 
                THook::RegisterBeforeRun(hook); 
            } 
        }; 
 
        static void RegisterAfterRun(THook* hook) noexcept; 
 
        static void CallAfterRun(); 
 
        struct TRegisterAfterRun { 
            explicit TRegisterAfterRun(THook* hook) noexcept { 
                THook::RegisterAfterRun(hook); 
            } 
        }; 
    }; 
 
    /** 
     * Called right before initializing test programm 
     * 
     * This hook is intended for setting up default parameters. If you're doing initialization, consider 
     * using `Y_TEST_HOOK_BEFORE_RUN` instead. 
     * 
     * *Note:* hooks execute in arbitrary order. 
     * 
     * 
     * # Usage 
     * 
     * Instantiate this class in a cpp file. Pass a unique name for your hook, 
     * implement body right after macro instantiation: 
     * 
     * ``` 
     * Y_TEST_HOOK_BEFORE_INIT(SetupParams) { 
     *     // hook code 
     * } 
     * ``` 
     */ 
#define Y_TEST_HOOK_BEFORE_INIT(N)                                                 \ 
        void N();                                                                  \ 
        ::NTesting::THook N##Hook{&N, nullptr};                                    \ 
        ::NTesting::THook::TRegisterBeforeInit N##HookReg{&N##Hook};               \ 
        void N() 
 
    /** 
     * Called right before launching tests. 
     * 
     * Hooks execute in arbitrary order. As such, we recommend using this hook to set up an event listener, 
     * and performing initialization and cleanup in the corresponding event handlers. This is better than performing 
     * initialization and cleanup directly in the hook's code because it gives more control over 
     * order in which initialization is performed. 
     * 
     * 
     * # Usage 
     * 
     * Instantiate this class in a cpp file. Pass a unique name for your hook, 
     * implement body right after macro instantiation: 
     * 
     * ``` 
     * Y_TEST_HOOK_BEFORE_RUN(InitMyApp) { 
     *     // hook code 
     * } 
     * ``` 
     */ 
#define Y_TEST_HOOK_BEFORE_RUN(N)                                                  \ 
        void N();                                                                  \ 
        ::NTesting::THook N##Hook{&N, nullptr};                                    \ 
        ::NTesting::THook::TRegisterBeforeRun N##HookReg{&N##Hook};                \ 
        void N() 
 
    /** 
     * Called after all tests has finished, just before program exit. 
     * 
     * This hook is intended for simple cleanup routines that don't care about order in which hooks are executed. 
     * For more complex cases, we recommend using `Y_TEST_HOOK_BEFORE_RUN`. 
     * 
     * 
     * # Usage 
     * 
     * Instantiate this class in a cpp file. Pass a unique name for your hook, 
     * implement body right after macro instantiation: 
     * 
     * ``` 
     * Y_TEST_HOOK_AFTER_RUN(StopMyApp) { 
     *     // hook code 
     * } 
     * ``` 
     */ 
#define Y_TEST_HOOK_AFTER_RUN(N)                                             \ 
        void N();                                                            \ 
        ::NTesting::THook N##Hook{&N, nullptr};                              \ 
        ::NTesting::THook::TRegisterAfterRun N##HookReg{&N##Hook};           \ 
        void N() 
}