summaryrefslogtreecommitdiff
path: root/boost/test/framework.hpp
blob: 099c02969b85987d7d103aa10b1ed33691c1807b (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
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
//  (C) Copyright Gennadiy Rozental 2001.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief Defines Unit Test Framework mono-state interfaces.
//! The framework interfaces are based on Monostate design pattern.
// ***************************************************************************

#ifndef BOOST_TEST_FRAMEWORK_HPP_020805GER
#define BOOST_TEST_FRAMEWORK_HPP_020805GER

// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/detail/throw_exception.hpp>

#include <boost/test/utils/trivial_singleton.hpp>

#include <boost/test/detail/suppress_warnings.hpp>

// STL
#include <stdexcept>

//____________________________________________________________________________//

namespace boost {

/// Main namespace for the Unit Test Framework interfaces and implementation
namespace unit_test {

// ************************************************************************** //
// **************              init_unit_test_func             ************** //
// ************************************************************************** //

/// Test module initialization routine signature

/// Different depending on whether BOOST_TEST_ALTERNATIVE_INIT_API is defined or not
#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
typedef bool        (*init_unit_test_func)();
#else
typedef test_suite* (*init_unit_test_func)( int, char* [] );
#endif

// ************************************************************************** //
// **************                   framework                  ************** //
// ************************************************************************** //

/// Namespace of the Unit Test Framework mono-state
namespace framework {

/// @name Unit Test Framework initialization and shutdown
/// @{

/// @brief This function performs initialization of the framework mono-state.
///
/// It needs to be called every time before the test is started.
/// @param[in] init_func test module initialization routine
/// @param[in] argc command line arguments collection
/// @param[in] argv command line arguments collection
BOOST_TEST_DECL void                init( init_unit_test_func init_func, int argc, char* argv[] );

/// This function applies all the decorators and figures out default run status. This argument facilitates an
/// ability of the test cases to prepare some other test units (primarily used internally for self testing).
/// @param[in] tu Optional id of the test unit representing root of test tree. If absent, master test suite is used
BOOST_TEST_DECL void                finalize_setup_phase( test_unit_id tu = INV_TEST_UNIT_ID);

/// This function returns true when testing is in progress (setup is finished).
BOOST_TEST_DECL bool                test_in_progress();

/// This function shuts down the framework and clears up its mono-state.
///
/// It needs to be at the very end of test module execution
BOOST_TEST_DECL void                shutdown();
/// @}

/// @name Test unit registration
/// @{

/// Provides both read and write access to current "leaf" auto test suite during the test unit registration phase.
///
/// During auto-registration phase the framework maintain a FIFO queue of test units being registered. New test units become children
/// of the current "leaf" test suite and if this is test suite it is pushed back into queue and becomes a new leaf.
/// When test suite registration is completed, a test suite is popped from the back of the queue. Only automatically registered test suites
/// should be added to this queue. Master test suite is always a zero element in this queue, so if no other test suites are registered
/// all test cases are added to master test suite.

/// This function facilitates all three possible actions:
///    - if no argument are provided it returns the current queue leaf test suite
///    - if test suite is provided and no second argument are set, test suite is added to the queue
///    - if no test suite are provided and last argument is false, the semantic of this function is similar to queue pop: last element is popped from the queue
/// @param[in] ts test suite to push back to the queue
/// @param[in] push_or_pop should we push ts to the queue or pop leaf test suite instead
/// @returns a reference to the currently active/"leaf" test suite
BOOST_TEST_DECL test_suite&         current_auto_test_suite( test_suite* ts = 0, bool push_or_pop = true );

/// This function add new test case into the global collection of test units the framework aware of.

/// This function also assignes unique test unit id for every test case. Later on one can use this id to locate
/// the test case if necessary. This is the way for the framework to maintain weak references between test units.
/// @param[in]  tc  test case to register
BOOST_TEST_DECL void                register_test_unit( test_case* tc );

/// This function add new test suite into the global collection of test units the framework aware of.

/// This function also assignes unique test unit id for every test suite. Later on one can use this id to locate
/// the test case if necessary. This is the way for the framework to maintain weak references between test units.
/// @param[in]  ts  test suite to register
BOOST_TEST_DECL void                register_test_unit( test_suite* ts );

/// This function removes the test unit from the collection of known test units and destroys the test unit object.

/// This function also assigns unique test unit id for every test case. Later on one can use this id to located
/// the test case if necessary. This is the way for the framework to maintain weak references between test units.
/// @param[in]  tu  test unit to deregister
BOOST_TEST_DECL void                deregister_test_unit( test_unit* tu );

// This function clears up the framework mono-state.

/// After this call the framework can be reinitialized to perform a second test run during the same program lifetime.
BOOST_TEST_DECL void                clear();
/// @}

/// @name Test observer registration
/// @{
/// Adds new test execution observer object into the framework's list of test observers.

/// Observer lifetime should exceed the the testing execution timeframe
/// @param[in]  to  test observer object to add
BOOST_TEST_DECL void                register_observer( test_observer& to );

/// Excludes the observer object form the framework's list of test observers
/// @param[in]  to  test observer object to exclude
BOOST_TEST_DECL void                deregister_observer( test_observer& to );

/// @}

/// @name Global fixtures registration
/// @{

/// Adds a new global fixture to be setup before any other tests starts and tore down after
/// any other tests finished.
/// Test unit fixture lifetime should exceed the testing execution timeframe
/// @param[in]  tuf  fixture to add
BOOST_TEST_DECL void                register_global_fixture( test_unit_fixture& tuf );

/// Removes a test global fixture from the framework
///
/// Test unit fixture lifetime should exceed the testing execution timeframe
/// @param[in]  tuf  fixture to remove
BOOST_TEST_DECL void                deregister_global_fixture( test_unit_fixture& tuf );
/// @}

/// @name Assertion/uncaught exception context support
/// @{
/// Context accessor
struct BOOST_TEST_DECL context_generator {
    context_generator() : m_curr_frame( 0 ) {}

    /// Is there any context?
    bool            is_empty() const;

    /// Give me next frame; empty - last frame
    const_string    next() const;

private:
    // Data members
    mutable unsigned m_curr_frame;
};

/// Records context frame message.

/// Some context frames are sticky - they can only explicitly cleared by specifying context id. Other (non sticky) context frames cleared after every assertion.
/// @param[in] context_descr context frame message
/// @param[in] sticky is this sticky frame or not
/// @returns id of the newly created frame
BOOST_TEST_DECL int                 add_context( lazy_ostream const& context_descr, bool sticky );
/// Erases context frame (when test exits context scope)

/// If context_id is passed clears that specific context frame identified by this id, otherwise clears all non sticky contexts.
BOOST_TEST_DECL void                clear_context( int context_id = -1 );
/// Produces an instance of small "delegate" object, which facilitates access to collected context.
BOOST_TEST_DECL context_generator   get_context();
/// @}

/// @name Access to registered test units.
/// @{
/// This function provides access to the master test suite.

/// There is only only master test suite per test module.
/// @returns a reference the master test suite instance
BOOST_TEST_DECL master_test_suite_t& master_test_suite();

/// This function provides an access to the test unit currently being executed.

/// The difference with current_test_case is about the time between a test-suite
/// is being set up or torn down (fixtures) and when the test-cases of that suite start.

/// This function is only valid during test execution phase.
/// @see current_test_case_id, current_test_case
BOOST_TEST_DECL test_unit const&    current_test_unit();

/// This function provides an access to the test case currently being executed.

/// This function is only valid during test execution phase.
/// @see current_test_case_id
BOOST_TEST_DECL test_case const&    current_test_case();

/// This function provides an access to an id of the test case currently being executed.

/// This function safer than current_test_case, cause if wont throw if no test case is being executed.
/// @see current_test_case
BOOST_TEST_DECL test_unit_id        current_test_case_id(); /* safe version of above */

/// This function provides access to a test unit by id and type combination. It will throw if no test unit located.
/// @param[in]  tu_id    id of a test unit to locate
/// @param[in]  tu_type  type of a test unit to locate
/// @returns located test unit
BOOST_TEST_DECL test_unit&          get( test_unit_id tu_id, test_unit_type tu_type );

/// This function template provides access to a typed test unit by id

/// It will throw if you specify incorrect test unit type
/// @tparam UnitType compile time type of test unit to get (test_suite or test_case)
/// @param  id id of test unit to get
template<typename UnitType>
inline UnitType&                    get( test_unit_id id )
{
    return static_cast<UnitType&>( get( id, static_cast<test_unit_type>(UnitType::type) ) );
}
///@}

/// @name Test initiation interface
/// @{

/// Initiates test execution

/// This function is used to start the test execution from a specific "root" test unit.
/// If no root provided, test is started from master test suite. This second argument facilitates an ability of the test cases to
/// start some other test units (primarily used internally for self testing).
/// @param[in] tu Optional id of the test unit or test unit itself from which the test is started. If absent, master test suite is used
/// @param[in] continue_test true == continue test if it was already started, false == restart the test from scratch regardless
BOOST_TEST_DECL void                run( test_unit_id tu = INV_TEST_UNIT_ID, bool continue_test = true );
/// Initiates test execution. Same as other overload
BOOST_TEST_DECL void                run( test_unit const* tu, bool continue_test = true );
/// @}

/// @name Test events dispatchers
/// @{
/// Reports results of assertion to all test observers
BOOST_TEST_DECL void                assertion_result( unit_test::assertion_result ar );
/// Reports uncaught exception to all test observers
BOOST_TEST_DECL void                exception_caught( execution_exception const& );
/// Reports aborted test unit to all test observers
BOOST_TEST_DECL void                test_unit_aborted( test_unit const& );
/// Reports aborted test module to all test observers
BOOST_TEST_DECL void                test_aborted( );
/// @}

namespace impl {
// exclusively for self test
BOOST_TEST_DECL void                setup_for_execution( test_unit const& );
BOOST_TEST_DECL void                setup_loggers( );
} // namespace impl

// ************************************************************************** //
// **************                framework errors              ************** //
// ************************************************************************** //

/// This exception type is used to report internal Boost.Test framework errors.
struct BOOST_TEST_DECL internal_error : public std::runtime_error {
    internal_error( const_string m ) : std::runtime_error( std::string( m.begin(), m.size() ) ) {}
};

//____________________________________________________________________________//

/// This exception type is used to report test module setup errors.
struct BOOST_TEST_DECL setup_error : public std::runtime_error {
    setup_error( const_string m ) : std::runtime_error( std::string( m.begin(), m.size() ) ) {}
};

#define BOOST_TEST_SETUP_ASSERT( cond, msg ) BOOST_TEST_I_ASSRT( cond, unit_test::framework::setup_error( msg ) )

//____________________________________________________________________________//

struct nothing_to_test {
    explicit    nothing_to_test( int rc ) : m_result_code( rc ) {}

    int         m_result_code;
};

//____________________________________________________________________________//

} // namespace framework
} // unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_FRAMEWORK_HPP_020805GER