BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslim_testutil.h
Go to the documentation of this file.
1/// @file bslim_testutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslim_testutil.h -*-C++-*-
8#ifndef INCLUDED_BSLIM_TESTUTIL
9#define INCLUDED_BSLIM_TESTUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslim_testutil bslim_testutil
15/// @brief Provide test utilities for components above `bsl`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslim
19/// @{
20/// @addtogroup bslim_testutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslim_testutil-purpose"> Purpose</a>
25/// * <a href="#bslim_testutil-classes"> Classes </a>
26/// * <a href="#bslim_testutil-macros"> Macros </a>
27/// * <a href="#bslim_testutil-description"> Description </a>
28///
29/// # Purpose {#bslim_testutil-purpose}
30/// Provide test utilities for components above `bsl`.
31///
32/// # Classes {#bslim_testutil-classes}
33///
34///
35/// # Macros {#bslim_testutil-macros}
36///
37/// - BSLIM_TESTUTIL_ASSERT(X): record and print error if `!X`
38/// - BSLIM_TESTUTIL_LOOP_ASSERT(I, X): print arguments if `!X`
39/// - BSLIM_TESTUTIL_LOOP2_ASSERT(I, J, X): print arguments if `!X`
40/// - BSLIM_TESTUTIL_LOOP3_ASSERT(I, J, K, X): print arguments if `!X`
41/// - BSLIM_TESTUTIL_LOOP4_ASSERT(I, J, K, L, X): print arguments if `!X`
42/// - BSLIM_TESTUTIL_LOOP5_ASSERT(I, J, K, L, M, X): print arguments if `!X`
43/// - BSLIM_TESTUTIL_LOOP6_ASSERT(I, J, K, L, M, N, X): print arguments if `!X`
44/// - BSLIM_TESTUTIL_LOOP7_ASSERT(I, J, K, L, M, N,O, X): print arguments if `!X`
45/// - BSLIM_TESTUTIL_LOOP8_ASSERT(I, J, K, L,M,N,O,V, X): print arguments if `!X`
46/// - BSLIM_TESTUTIL_ASSERTV(..., X): print generic arguments if `!X`
47/// - BSLIM_TESTUTIL_Q(X): quote identifier literally
48/// - BSLIM_TESTUTIL_P(X): print identifier and value
49/// - BSLIM_TESTUTIL_P_(X): print identifier and value without '\n'
50/// - BSLIM_TESTUTIL_L_: current line number
51/// - BSLIM_TESTUTIL_T_: print tab without '\n'
52///
53/// @see bsls_bsltestutil
54///
55/// # Description {#bslim_testutil-description}
56/// This component provides the standard print macros used in
57/// BDE-style test drivers (`ASSERT`, `LOOP_ASSERT`, `ASSERTV`, `P`, `Q`, `L`,
58/// and `T`) for components above the `bsl` package group.
59///
60/// This component also defines a set of overloads for the insertion operator
61/// (`<<`) to support the streaming of test types defined in the `bsltf`
62/// package. These overloads are required for test drivers above the `bsl`
63/// package group in order to print objects of the `bsltf` types to `bsl::cout`.
64///
65/// This component also defines a pair of methods, `setFunc` and `callFunc`,
66/// that allow a test driver to set and call a function by going through another
67/// compilation unit to preclude the optimizer from inlining the function call.
68/// @}
69/** @} */
70/** @} */
71
72/** @addtogroup bsl
73 * @{
74 */
75/** @addtogroup bslim
76 * @{
77 */
78/** @addtogroup bslim_testutil
79 * @{
80 */
81
82// Note that the 'bsltf' package resides below 'bsl+bslhdrs', in which
83// 'bsl::cout' is defined; therefore, the components in 'bsltf' cannot directly
84// define the overloads of the insertion operator to support printing the test
85// types. Instead, an alternate method supplied in @ref bsls_bsltestutil is used
86// for test drivers in the 'bsl' package group.
87//
88///Usage
89///-----
90// This section illustrates intended use of this component.
91//
92///Example 1: Writing a Test Driver
93/// - - - - - - - - - - - - - - - -
94// First, we write an elided component to test, which provides a utility class:
95//..
96// namespace bdlabc {
97//
98// struct ExampleUtil {
99// // This utility class provides sample functionality to demonstrate how
100// // a test driver might be written validating its only method.
101//
102// // CLASS METHODS
103// static int fortyTwo();
104// // Return the integer value 42.
105// };
106//
107// // CLASS METHODS
108// inline
109// int ExampleUtil::fortyTwo()
110// {
111// return 42;
112// }
113//
114// } // close package namespace
115//..
116// Then, we can write an elided test driver for this component. We start by
117// providing the standard BDE assert test macro:
118//..
119// //=========================================================================
120// // STANDARD BDE ASSERT TEST MACRO
121// //-------------------------------------------------------------------------
122// static int testStatus = 0;
123//
124// static void aSsErT(bool b, const char *s, int i)
125// {
126// if (b) {
127// printf("Error " __FILE__ "(%d): %s (failed)\n", i, s);
128// if (testStatus >= 0 && testStatus <= 100) ++testStatus;
129// }
130// }
131//..
132// Next, we define the standard print and 'LOOP_ASSERT' macros, as aliases to
133// the macros defined by this component:
134//..
135// //=========================================================================
136// // STANDARD BDE TEST DRIVER MACROS
137// //-------------------------------------------------------------------------
138//
139// #define ASSERT BSLIM_TESTUTIL_ASSERT
140// #define LOOP_ASSERT BSLIM_TESTUTIL_LOOP_ASSERT
141// #define LOOP0_ASSERT BSLIM_TESTUTIL_LOOP0_ASSERT
142// #define LOOP1_ASSERT BSLIM_TESTUTIL_LOOP1_ASSERT
143// #define LOOP2_ASSERT BSLIM_TESTUTIL_LOOP2_ASSERT
144// #define LOOP3_ASSERT BSLIM_TESTUTIL_LOOP3_ASSERT
145// #define LOOP4_ASSERT BSLIM_TESTUTIL_LOOP4_ASSERT
146// #define LOOP5_ASSERT BSLIM_TESTUTIL_LOOP5_ASSERT
147// #define LOOP6_ASSERT BSLIM_TESTUTIL_LOOP6_ASSERT
148// #define LOOP7_ASSERT BSLIM_TESTUTIL_LOOP7_ASSERT
149// #define LOOP8_ASSERT BSLIM_TESTUTIL_LOOP8_ASSERT
150// #define ASSERTV BSLIM_TESTUTIL_ASSERTV
151//
152// #define Q BSLIM_TESTUTIL_Q // Quote identifier literally.
153// #define P BSLIM_TESTUTIL_P // Print identifier and value.
154// #define P_ BSLIM_TESTUTIL_P_ // P(X) without '\n'.
155// #define T_ BSLIM_TESTUTIL_T_ // Print a tab (w/o newline).
156// #define L_ BSLIM_TESTUTIL_L_ // current Line number
157//..
158// Now, using the (standard) abbreviated macro names we have just defined, we
159// write a test function for the 'static' 'fortyTwo' method, to be called from
160// a test case in the test driver:
161//..
162// void testFortyTwo(bool verbose)
163// // Test 'bdlabc::ExampleUtil::fortyTwo' in the specified 'verbose'
164// // verbosity level.
165// {
166// const int value = bdlabc::ExampleUtil::fortyTwo();
167// if (verbose) P(value);
168// LOOP_ASSERT(value, 42 == value);
169// }
170//..
171// Finally, when 'testFortyTwo' is called from a test case in verbose mode we
172// observe the console output:
173//..
174// value = 42
175//..
176
177#include <bslscm_version.h>
178
179#include <bslmf_assert.h>
180
181#include <bsl_iostream.h>
182#include <bsl_string.h>
183
184#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
186#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
187
188 // =================
189 // Macro Definitions
190 // =================
191
192#define BSLIM_TESTUTIL_ASSERT(X) \
193 aSsErT(!(X), #X, __LINE__);
194
195#define BSLIM_TESTUTIL_DEBUG_REP(X) BloombergLP::bslim::TestUtil::debugRep(X)
196
197#define BSLIM_TESTUTIL_LOOP0_ASSERT \
198 BSLIM_TESTUTIL_ASSERT
199
200#define BSLIM_TESTUTIL_LOOP_ASSERT(I,X) \
201 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\n"; \
202 aSsErT(1, #X, __LINE__); }
203
204#define BSLIM_TESTUTIL_LOOP1_ASSERT \
205 BSLIM_TESTUTIL_LOOP_ASSERT
206
207#define BSLIM_TESTUTIL_LOOP2_ASSERT(I,J,X) \
208 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
209 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\n"; \
210 aSsErT(1, #X, __LINE__); }
211
212#define BSLIM_TESTUTIL_LOOP3_ASSERT(I,J,K,X) \
213 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
214 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\t" \
215 << #K ": " << BSLIM_TESTUTIL_DEBUG_REP(K) << "\n"; \
216 aSsErT(1, #X, __LINE__); }
217
218#define BSLIM_TESTUTIL_LOOP4_ASSERT(I,J,K,L,X) \
219 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
220 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\t" \
221 << #K ": " << BSLIM_TESTUTIL_DEBUG_REP(K) << "\t" \
222 << #L ": " << BSLIM_TESTUTIL_DEBUG_REP(L) << "\n"; \
223 aSsErT(1, #X, __LINE__); }
224
225#define BSLIM_TESTUTIL_LOOP5_ASSERT(I,J,K,L,M,X) \
226 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
227 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\t" \
228 << #K ": " << BSLIM_TESTUTIL_DEBUG_REP(K) << "\t" \
229 << #L ": " << BSLIM_TESTUTIL_DEBUG_REP(L) << "\t" \
230 << #M ": " << BSLIM_TESTUTIL_DEBUG_REP(M) << "\n"; \
231 aSsErT(1, #X, __LINE__); }
232
233#define BSLIM_TESTUTIL_LOOP6_ASSERT(I,J,K,L,M,N,X) \
234 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
235 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\t" \
236 << #K ": " << BSLIM_TESTUTIL_DEBUG_REP(K) << "\t" \
237 << #L ": " << BSLIM_TESTUTIL_DEBUG_REP(L) << "\t" \
238 << #M ": " << BSLIM_TESTUTIL_DEBUG_REP(M) << "\t" \
239 << #N ": " << BSLIM_TESTUTIL_DEBUG_REP(N) << "\n"; \
240 aSsErT(1, #X, __LINE__); }
241
242#define BSLIM_TESTUTIL_LOOP7_ASSERT(I,J,K,L,M,N,O,X) \
243 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
244 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\t" \
245 << #K ": " << BSLIM_TESTUTIL_DEBUG_REP(K) << "\t" \
246 << #L ": " << BSLIM_TESTUTIL_DEBUG_REP(L) << "\t" \
247 << #M ": " << BSLIM_TESTUTIL_DEBUG_REP(M) << "\t" \
248 << #N ": " << BSLIM_TESTUTIL_DEBUG_REP(N) << "\t" \
249 << #O ": " << BSLIM_TESTUTIL_DEBUG_REP(O) << "\n"; \
250 aSsErT(1, #X, __LINE__); }
251
252#define BSLIM_TESTUTIL_LOOP8_ASSERT(I,J,K,L,M,N,O,V,X) \
253 if (!(X)) { bsl::cout << #I ": " << BSLIM_TESTUTIL_DEBUG_REP(I) << "\t" \
254 << #J ": " << BSLIM_TESTUTIL_DEBUG_REP(J) << "\t" \
255 << #K ": " << BSLIM_TESTUTIL_DEBUG_REP(K) << "\t" \
256 << #L ": " << BSLIM_TESTUTIL_DEBUG_REP(L) << "\t" \
257 << #M ": " << BSLIM_TESTUTIL_DEBUG_REP(M) << "\t" \
258 << #N ": " << BSLIM_TESTUTIL_DEBUG_REP(N) << "\t" \
259 << #O ": " << BSLIM_TESTUTIL_DEBUG_REP(O) << "\t" \
260 << #V ": " << BSLIM_TESTUTIL_DEBUG_REP(V) << "\n"; \
261 aSsErT(1, #X, __LINE__); }
262
263// The 'BSLIM_TESTUTIL_EXPAND' macro is required to work around a preprocessor
264// issue on Windows that prevents '__VA_ARGS__' from being expanded in the
265// definition of 'BSLIM_TESTUTIL_NUM_ARGS'.
266
267#define BSLIM_TESTUTIL_EXPAND(X) \
268 X
269
270#define BSLIM_TESTUTIL_NUM_ARGS_IMPL(X8, X7, X6, X5, X4, X3, X2, X1, X0, \
271 N, ...) \
272 N
273
274#define BSLIM_TESTUTIL_NUM_ARGS(...) \
275 BSLIM_TESTUTIL_EXPAND(BSLIM_TESTUTIL_NUM_ARGS_IMPL( \
276 __VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0, ""))
277
278#define BSLIM_TESTUTIL_LOOPN_ASSERT_IMPL(N, ...) \
279 BSLIM_TESTUTIL_EXPAND(BSLIM_TESTUTIL_LOOP ## N ## _ASSERT(__VA_ARGS__))
280
281#define BSLIM_TESTUTIL_LOOPN_ASSERT(N, ...) \
282 BSLIM_TESTUTIL_LOOPN_ASSERT_IMPL(N, __VA_ARGS__)
283
284#define BSLIM_TESTUTIL_ASSERTV(...) \
285 BSLIM_TESTUTIL_LOOPN_ASSERT( \
286 BSLIM_TESTUTIL_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
287
288/// Quote identifier literally.
289#define BSLIM_TESTUTIL_Q(X) \
290 bsl::cout << "<| " #X " |>" << bsl::endl;
291
292/// Print identifier and its value.
293#define BSLIM_TESTUTIL_P(X) \
294 bsl::cout << #X " = " << BSLIM_TESTUTIL_DEBUG_REP(X) << bsl::endl;
295
296/// `P(X)` without '\n'
297#define BSLIM_TESTUTIL_P_(X) \
298 bsl::cout << #X " = " << BSLIM_TESTUTIL_DEBUG_REP(X) << ", " << bsl::flush;
299
300/// current Line number
301#define BSLIM_TESTUTIL_L_ \
302 __LINE__
303
304/// Print tab (w/o newline).
305#define BSLIM_TESTUTIL_T_ \
306 bsl::cout << "\t" << bsl::flush;
307
308
309namespace bslim {
310
311 // ==============
312 // class TestUtil
313 // ==============
314
315/// This `struct` provides a namespace for a suite of utility functions that
316/// facilitate the creation of BDE-style test drivers.
317struct TestUtil {
318
319 private:
320 // PRIVATE CLASS METHODS
321
322 /// Return `ptr` without modification. Note that this is NOT an inline
323 /// function, so that if the caller is not in the same module, the
324 /// compiler has no way of knowing that it's an identity transform.
325 static void *identityPtr(void *ptr);
326
327 public:
328 // CLASS METHODS
329
330 /// Return `true` if the specified `lhs` has the same value as the
331 /// specified `rhs`, and `false` otherwise. Optionally specify an
332 /// `errorStream` on which, if `lhs` and `rhs` are not the same', a
333 /// description of how the two strings differ will be written. If
334 /// `errorStream` is not supplied, `stdout` is used.
337 bsl::ostream& errorStream = bsl::cout);
338
339 /// Return the specified `functionPtr` (expected to be a static function
340 /// pointer) without modification. The value of `functionPtr` is
341 /// transformed through `identityPtr` so that if the caller is in a
342 /// different module, the compiler will have no way of knowing that this
343 /// is an identity transform and thus no way of inlining the call.
344 ///
345 /// Note: the Windows optimizer is still able to inline the call, it may
346 /// be comparing the result of this function with the argument and
347 /// branching to inline on equality and call on inequality, so the
348 /// Windows optimizer has to be turned off with
349 /// `# pragma optimize("", off)`.
350 ///
351 /// Also note that even with an optimizer that can't figure out that
352 /// this is an identity transform, there is still the possibility of
353 /// chaining the call.
354 template <class FUNCTION_PTR>
355 static FUNCTION_PTR makeFunctionCallNonInline(FUNCTION_PTR functionPtr);
356
357 template <class T>
358 static const T& debugRep(const T& arg) { return arg; }
359 static int debugRep(wchar_t arg) { return arg; }
360};
361
362// ============================================================================
363// INLINE FUNCTION DEFINITIONS
364// ============================================================================
365
366 // --------
367 // TestUtil
368 // --------
369
370template <class FUNCTION_PTR>
371inline
372FUNCTION_PTR TestUtil::makeFunctionCallNonInline(FUNCTION_PTR function)
373{
374 BSLMF_ASSERT(sizeof(FUNCTION_PTR) == sizeof(void *));
375
376 return reinterpret_cast<FUNCTION_PTR>(identityPtr(reinterpret_cast<void *>(
377 function)));
378}
379
380} // close package namespace
381
382
383#endif
384
385// ----------------------------------------------------------------------------
386// Copyright 2012 Bloomberg Finance L.P.
387//
388// Licensed under the Apache License, Version 2.0 (the "License");
389// you may not use this file except in compliance with the License.
390// You may obtain a copy of the License at
391//
392// http://www.apache.org/licenses/LICENSE-2.0
393//
394// Unless required by applicable law or agreed to in writing, software
395// distributed under the License is distributed on an "AS IS" BASIS,
396// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
397// See the License for the specific language governing permissions and
398// limitations under the License.
399// ----------------------------- END-OF-FILE ----------------------------------
400
401/** @} */
402/** @} */
403/** @} */
Definition bslstl_stringref.h:372
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslim_formatguard.h:120
Definition bslim_testutil.h:317
static int debugRep(wchar_t arg)
Definition bslim_testutil.h:359
static const T & debugRep(const T &arg)
Definition bslim_testutil.h:358
static FUNCTION_PTR makeFunctionCallNonInline(FUNCTION_PTR functionPtr)
Definition bslim_testutil.h:372
static bool compareText(bslstl::StringRef lhs, bslstl::StringRef rhs, bsl::ostream &errorStream=bsl::cout)