BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_testutil.h
Go to the documentation of this file.
1/// @file bslmt_testutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_testutil.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_TESTUTIL
9#define INCLUDED_BSLMT_TESTUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_testutil bslmt_testutil
15/// @brief Provide thread-safe test utilities for multithreaded components.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_testutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_testutil-purpose"> Purpose</a>
25/// * <a href="#bslmt_testutil-classes"> Classes </a>
26/// * <a href="#bslmt_testutil-macros"> Macros </a>
27/// * <a href="#bslmt_testutil-description"> Description </a>
28/// * <a href="#bslmt_testutil-simple-output-macros"> Simple Output Macros </a>
29/// * <a href="#bslmt_testutil-guarded-stream-output"> Guarded Stream Output </a>
30/// * <a href="#bslmt_testutil-assertion-macros"> Assertion Macros </a>
31/// * <a href="#bslmt_testutil-infrastructure-for-the-assertion-macros"> Infrastructure for the Assertion Macros </a>
32/// * <a href="#bslmt_testutil-guarding-critical-sections"> Guarding Critical Sections </a>
33/// * <a href="#bslmt_testutil-usage"> Usage </a>
34/// * <a href="#bslmt_testutil-example-1-use-of-thread-safe-asserts-and-guard-in-a-test-driver"> Example 1: Use of Thread-Safe Asserts and Guard in a Test Driver </a>
35///
36/// # Purpose {#bslmt_testutil-purpose}
37/// Provide thread-safe test utilities for multithreaded components.
38///
39/// # Classes {#bslmt_testutil-classes}
40///
41/// - bslmt::TestUtil: namespace class for multi-threaded utility functions.
42///
43/// # Macros {#bslmt_testutil-macros}
44///
45/// - BSLMT_TESTUTIL_ASSERT(X): record and print message if `!X`
46/// - BSLMT_TESTUTIL_ASSERTV(..., X): record and print args and message if `!X`
47/// - BSLMT_TESTUTIL_Q(X): quote identifier literally
48/// - BSLMT_TESTUTIL_P(X): print identifier and value
49/// - BSLMT_TESTUTIL_P_(X): print identifier and value without '\n'
50/// - BSLMT_TESTUTIL_L_: current line number
51/// - BSLMT_TESTUTIL_T_: print tab without '\n'
52/// - BSLMT_TESTUTIL_GUARD: create a lock guard on the singleton mutex
53/// - BSLMT_TESTUTIL_GUARDED_STREAM(STREAM): guarded access to `STREAM`
54/// - BSLMT_TESTUTIL_COUT: thread-safe access to `bsl::cout`
55/// - BSLMT_TESTUTIL_CERR: thread-safe access to `bsl::cerr`
56/// - ---
57/// - BSLMT_TESTUTIL_LOOP_ASSERT
58/// - BSLMT_TESTUTIL_LOOP2_ASSERT
59/// - BSLMT_TESTUTIL_LOOP3_ASSERT
60/// - BSLMT_TESTUTIL_LOOP4_ASSERT
61/// - BSLMT_TESTUTIL_LOOP5_ASSERT
62/// - BSLMT_TESTUTIL_LOOP6_ASSERT
63/// - // - Discouraged: use `ASSERTV`. Provided for the sake of ease of
64/// - // - migration of test drivers from using @ref bsls_bsltestutil or
65/// - // - @ref bslim_testutil .
66/// - ---
67/// - BSLMT_TESTUTIL_OUTPUT_GUARD
68/// - // - **DEPRECATED**: use BSLMT_TESTUTIL_GUARD
69/// - ---
70/// - BSLMT_TESTUTIL_NESTED_OUTPUT_GUARD
71/// - // - **DEPRECATED**: use BSLMT_TESTUTIL_GUARD
72///
73/// @see bslim_testutil, bsls_bsltestutil
74///
75/// # Description {#bslmt_testutil-description}
76/// This component provides a set of macros for the standard BDE
77/// test driver assert and print facilities (see the macros defined in
78/// @ref bsls_bsltestutil and @ref bslim_testutil ) that are suitable for use in
79/// multi-threaded test drivers. This component also provides a utility
80/// `struct`, `bslmt::TestUtil`, that defines a namespace for types and
81/// functions that are helpful in multi-threaded test drivers.
82///
83/// ## Simple Output Macros {#bslmt_testutil-simple-output-macros}
84///
85///
86/// * `BSLMT_TESTUTIL_Q(X)`
87/// * `BSLMT_TESTUTIL_P(X)`
88/// * `BSLMT_TESTUTIL_P_(X)`
89/// * `BSLMT_TESTUTIL_L_`
90/// * `BSLMT_TESTUTIL_T_`
91///
92/// These macros guarantee:
93///
94/// 1. The entire output message is not interleaved with those of other threads
95/// using these macros.
96/// 2. The output stream (e.g., `bsl::cout`) is not corrupted. (Since
97/// `bsl::cout` itself was not made thread-safe until C++11 this is a concern
98/// on some of our supported platforms.)
99///
100/// ## Guarded Stream Output {#bslmt_testutil-guarded-stream-output}
101///
102///
103/// This component also defines several additions to the set of standard test
104/// macros:
105/// * `BSLMT_TESTUTIL_GUARDED_STREAM(STREAM)`
106/// * `BSLMT_TESTUTIL_COUT`
107/// * `BSLMT_TESTUTIL_CERR`
108///
109/// These macros guarantee atomicity of the output for the entire statement up
110/// to the terminating semi-colon. For example, if one thread executes:
111/// @code
112/// int value = 42;
113/// BSLMT_TESTUTIL_COUT << "The value is " << value << "." << bsl::endl;
114/// @endcode
115/// and another thread executes;
116/// @code
117/// bsl::string name("Barbara");
118/// BSLMT_TESTUTIL_COUT << "Hello " << name << "." << bsl::endl;
119/// @endcode
120/// The output will be either:
121/// @code
122/// Hello Barbara.
123/// The value is 42.
124/// @endcode
125/// or
126/// @code
127/// The value is 42.
128/// Hello Barbara.
129/// @endcode
130/// but, despite six separate operations on `bsl::cout`, the lines will not be
131/// interleaved.
132///
133/// As with the "ASSERT" macros above, these macros do not guarantee thread-safe
134/// evaluation of any expressions in the output statement. Thus, if one thread
135/// is executing:
136/// @code
137/// BSLMT_TESTUTIL_COUT << "The value is " << f() << "." << bsl::endl;
138/// @endcode
139/// and some other thread is executing:
140/// @code
141/// BSLMT_TESTUTIL_COUT << "There are " << g() << " cases." << bsl::endl;
142/// @endcode
143/// the two output statements are evaluated serially, but the evaluation of the
144/// `f` and `g` functions may require their own synchronization (if they are
145/// accessing values that may be in the process of unguarded modification by
146/// other threads).
147///
148/// ## Assertion Macros {#bslmt_testutil-assertion-macros}
149///
150///
151/// The macros:
152///
153/// * BSLMT_TESTUTIL_ASSERT
154/// * BSLMT_TESTUTIL_ASSERTV, and
155/// * BSLMT_TESTUTIL_LOOP*_ASSERT
156///
157/// work like their counterparts in @ref bsls_bsltestutil and @ref bslim_testutil ,
158/// except that all output by a given assert is guaranteed not to be interleaved
159/// with output from other macros in this component.
160///
161/// These macros provide no synchronization until *after* failure is detected.
162/// If the boolean expression being evaluated is not thread-safe, the caller of
163/// the macro must provide synchronization around the macro call.
164///
165/// The `LOOP*_ASSERT` macros are considered obsolete and are provided to
166/// facilitate the multi-threading of test drivers written using macros from
167/// @ref bsls_bsltestutil and @ref bslim_testutil . Use `BSLMT_TESTUTIL_ASSERTV`
168/// instead.
169///
170/// ### Infrastructure for the Assertion Macros {#bslmt_testutil-infrastructure-for-the-assertion-macros}
171///
172///
173/// Similarly to the macros defined in @ref bsls_bsltestutil and
174/// @ref bslim_testutil , the assert macros defined here assume that the user has
175/// defined a global integer variable named `testStatus` and has defined a
176/// function:
177/// @code
178/// void aSsErT(int c, const char *assertionAsString, int lineNumber);
179/// @endcode
180/// that outputs the conventional error message and update `testStatus` when `c`
181/// is non-zero. If all access to `testStatus` is through the "ASSERT" macros,
182/// `testStatus` can be an ordinary (non-atomic) `int` and `aSsErT` need not be
183/// thread-safe.
184///
185/// ## Guarding Critical Sections {#bslmt_testutil-guarding-critical-sections}
186///
187///
188/// This component also provides a (macro-wrapped) guard object:
189///
190/// * `BSLMT_TESTUTIL_GUARD`
191///
192/// which does no output, but rather prevents the interleaving of output from
193/// the other macros until the guard goes out of scope. This feature is useful
194/// in the common situation in which one wants to prevent interleaving of
195/// several separate uses of the macros.
196///
197/// For example, assuming the conventional shorthand for the standard test
198/// macros:
199/// @code
200/// #define P BSLMT_TESTUTIL_P
201/// #define P_ BSLMT_TESTUTIL_P_
202/// #define T_ BSLMT_TESTUTIL_T_
203///
204/// #define COUT BSLMT_TESTUTIL_COUT
205/// @endcode
206/// and
207/// @code
208/// #define GUARD BSLMT_TESTUTIL_GUARD
209/// @endcode
210/// consider two threads, one of which executes:
211/// @code
212/// int a = 4 * 5, b = 7 / 2, c = 5;
213///
214/// T_ P_(a); P_(b); P(c * 2);
215/// @endcode
216/// while the other thread executes:
217/// @code
218/// int x = 3 * 7, y = 45, z = 103;
219///
220/// T_ P_(x); P_(y); P(z * 2);
221/// @endcode
222/// In total, there are eight output operations on `bsl::cout`. Though the
223/// order of outputs within each thread is guaranteed, there is no guarantee
224/// that the entire line of output of either thread will be finished before the
225/// other begins. One possible result (among other myriad possibilities) is:
226/// @code
227/// x = 21, a = 20, b = 3, y = 45, z = 206
228/// c * 2 = 10
229///
230/// @endcode
231/// Clearly, such output is difficult to interpret. Fortunately, we have a
232/// remedy.
233///
234/// The two sets of output operation can be serialized by requiring the creation
235/// of a `GUARD` object before each set of output operations, and destroying
236/// that object afterwards. The existence of a guard object on the stack of one
237/// thread blocks the construction of guard objects by *other* threads until the
238/// existing guard object is destroyed.
239///
240/// The behavior is undefined if guard objects are created anywhere but on the
241/// stack (i.e., automatic variables).
242///
243/// Our revised (guarded) code can be written this way in one thread:
244/// @code
245/// int a = 4 * 5, b = 7 / 2, c = 5;
246/// {
247/// GUARD;
248///
249/// T_ P_(a); P_(b); P(c * 2);
250/// }
251/// @endcode
252/// and this way in the other thread:
253/// @code
254/// int x = 3 * 7, y = 45, z = 103;
255/// {
256/// GUARD;
257///
258/// T_ P_(x); P_(y); P(z * 2);
259/// }
260/// @endcode
261/// Now, possibility of the two threads interleaving this output has been
262/// eliminated and the output will appear in either this order:
263/// @code
264/// a = 20, b = 3, c * 2 = 10
265/// x = 21, y = 45, z * 2 = 206
266/// @endcode
267/// or this order:
268/// @code
269/// x = 21, y = 45, z * 2 = 206
270/// a = 20, b = 3, c * 2 = 10
271/// @endcode
272/// Note that each *individual* thread can own several guard objects at a given
273/// time. (Recall the constructor blocks if guards exist on *other* threads).
274/// Thus, guarded sections can call, without fear of deadlock, functions that
275/// may create their own guard objects.
276///
277/// If a guard exists in a thread, more guards can be created in the same thread
278/// with no effect. Guards cannot be created in another thread until all of the
279/// guards have been destroyed. So the above example could have been:
280/// @code
281/// int a = 4 * 5, b = 7 / 2, c = 5;
282/// {
283/// GUARD;
284/// GUARD;
285/// GUARD;
286/// GUARD;
287///
288/// T_ P_(a); P_(b); P(c * 2);
289/// }
290/// @endcode
291/// and in the other thread:
292/// @code
293/// int x = 3 * 7, y = 45, z = 103;
294/// {
295/// GUARD;
296///
297/// T_ P_(x);
298///
299/// {
300/// GUARD;
301///
302/// P_(y); P(z * 2);
303/// }
304/// }
305/// @endcode
306/// and the result would have been EXACTLY the same.
307///
308/// ## Usage {#bslmt_testutil-usage}
309///
310///
311/// This section illustrates intended use of this component.
312///
313/// ### Example 1: Use of Thread-Safe Asserts and Guard in a Test Driver {#bslmt_testutil-example-1-use-of-thread-safe-asserts-and-guard-in-a-test-driver}
314///
315///
316/// First, we write a function, `sumOfSquares`, to test:
317/// @code
318/// namespace xyzde {
319///
320/// /// This utility class provides sample functionality to demonstrate how
321/// /// a multi-threaded test driver might be written.
322/// struct SumUtil {
323///
324/// // CLASS METHODS
325///
326/// /// Return the sum of the squares of one to 4 arguments, the
327/// /// specified `a` and the optionally specified `b`, `c`, and `d`.
328/// static double sumOfSquares(double a,
329/// double b = 0,
330/// double c = 0,
331/// double d = 0);
332/// };
333///
334/// // CLASS METHODS
335/// inline
336/// double SumUtil::sumOfSquares(double a,
337/// double b,
338/// double c,
339/// double d)
340/// {
341/// // Note that there is a bug here in that we have added the cube, rather
342/// // than the square, of 'd'.
343///
344/// double ret = a * a;
345/// ret += b * b;
346/// ret += c * c;
347/// ret += d * d * d;
348/// return ret;
349/// }
350///
351/// } // close namespace xyzde
352/// @endcode
353/// Then, we can write a test driver for this component. We start by providing
354/// the standard BDE `ASSERT` test macro, which is not thread-safe, and is the
355/// same as it is for a test driver using @ref bslim_testutil . The macros in
356/// @ref bslmt_testutil ensure that any time this function is called, the global
357/// mutex has been acquired.
358/// @code
359/// // ========================================================================
360/// // STANDARD BDE ASSERT TEST FUNCTION
361/// // ------------------------------------------------------------------------
362/// int testStatus = 0;
363///
364/// void aSsErT(int c, const char *s, int i)
365/// {
366/// if (c) {
367/// bsl::cout << "Error " << __FILE__ << "(" << i << "): " << s
368/// << " (failed)" << bsl::endl;
369/// if (testStatus >= 0 && testStatus <= 100) ++testStatus;
370/// }
371/// }
372/// @endcode
373/// Next, we define the standard output and `ASSERT*` macros, as aliases to the
374/// macros defined by this component:
375/// @code
376/// // ========================================================================
377/// // STANDARD BDE TEST DRIVER MACROS
378/// // ------------------------------------------------------------------------
379///
380/// #define ASSERT BSLMT_TESTUTIL_ASSERT
381/// #define ASSERTV BSLMT_TESTUTIL_ASSERTV
382///
383/// #define LOOP_ASSERT BSLMT_TESTUTIL_LOOP_ASSERT
384/// #define LOOP2_ASSERT BSLMT_TESTUTIL_LOOP2_ASSERT
385/// #define LOOP3_ASSERT BSLMT_TESTUTIL_LOOP3_ASSERT
386/// #define LOOP4_ASSERT BSLMT_TESTUTIL_LOOP4_ASSERT
387/// #define LOOP5_ASSERT BSLMT_TESTUTIL_LOOP5_ASSERT
388/// #define LOOP6_ASSERT BSLMT_TESTUTIL_LOOP6_ASSERT
389///
390/// #define GUARD BSLMT_TESTUTIL_GUARD
391///
392/// #define Q BSLMT_TESTUTIL_Q
393/// #define P BSLMT_TESTUTIL_P
394/// #define P_ BSLMT_TESTUTIL_P_
395/// #define T_ BSLMT_TESTUTIL_T_
396/// #define L_ BSLMT_TESTUTIL_L_
397///
398/// #define GUARDED_STREAM(STREAM) BSLMT_TESTUTIL_GUARDED_STREAM(STREAM)
399/// #define COUT BSLMT_TESTUTIL_COUT
400/// #define CERR BSLMT_TESTUTIL_CERR
401/// @endcode
402/// Then, we define global verbosity flags to be used for controlling debug
403/// traces. The flags will be set by elided code at the beginning of `main` to
404/// determine the level of output verbosity the client wants:
405/// @code
406/// // ========================================================================
407/// // GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
408/// // ------------------------------------------------------------------------
409///
410/// bool verbose;
411/// bool veryVerbose;
412/// bool veryVeryVerbose;
413/// bool veryVeryVeryVerbose;
414/// @endcode
415/// Next begin the usage test case, defining a `typedef` and some `enum`s used
416/// by this test case:
417/// @code
418/// // ---------------
419/// // Usage Test Case
420/// // ---------------
421///
422/// typedef xyzde::SumUtil SU;
423///
424/// enum { k_NUM_THREADS = 5,
425/// k_HI_LIMIT_X = 100,
426/// k_LO_LIMIT_X = -100 };
427/// @endcode
428/// Then, using our test macros, we write our test functor that can be run
429/// concurrently to test the static function:
430/// @code
431/// struct SumUtilTest {
432/// /// Test `TestUtil::sumOfSquares` with a variety of randomly
433/// /// generated arguments.
434/// void operator()()
435/// {
436/// int threadIdx;
437/// double x[4]; // randomly-generated test values
438/// @endcode
439/// Next, we use the `GUARD` macro to serialize the initialization of
440/// `threadIdx` and the `x` array. We call `bsl::srand` and `bsl::rand`, which
441/// are not thread-safe, so the calls to them must be mutex-guarded. Because
442/// all access to `mainThreadIdx` is guarded by the `GUARD` call, it does not
443/// need to be an atomic variable.
444/// @code
445/// {
446/// GUARD;
447///
448/// static int mainThreadIdx = 0;
449/// threadIdx = mainThreadIdx++;
450///
451/// unsigned randSeed = (1234567891 + threadIdx) * 3333333333U;
452/// bsl::srand(randSeed);
453///
454/// for (int ii = 0; ii < 4; ++ii) {
455/// // Note that 'bsl::rand' always returns a non-negative
456/// // value.
457///
458/// const double characteristic = bsl::rand() % k_HI_LIMIT_X;
459/// const double mantissa =
460/// static_cast<double>(bsl::rand() % 1024) / 1024;
461/// const int sign = (bsl::rand() & 1) ? +1 : -1;
462///
463/// // Note that it is safe to use 'ASSERTV', which redundantly
464/// // locks the mutex, even though the mutex has already been
465/// // acquired by the 'GUARD' call above.
466///
467/// ASSERTV(threadIdx,ii, characteristic, 0 <= characteristic);
468/// ASSERTV(threadIdx,ii, characteristic,
469/// characteristic < k_HI_LIMIT_X);
470/// ASSERTV(threadIdx,ii, mantissa, 0 <= mantissa);
471/// ASSERTV(threadIdx,ii, mantissa, mantissa < 1);
472///
473/// x[ii] = sign * (characteristic + mantissa / 1000);
474/// }
475/// @endcode
476/// Then we close the block, allowing other threads to do output with the
477/// `BSLMT_TESTUTIL_*` macros or enter sections guarded by `GUARD`s. Now, if we
478/// want to do output, we have to acquire the critical section again, which we
479/// can do by using the `COUT` (aliased to `BSLMT_TESTUTIL_COUT`) macro:
480/// @code
481/// }
482///
483/// if (veryVerbose) COUT << "threadIdx: " << threadIdx <<
484/// ", x[] = { " << x[0] << ", " << x[1] << ", " << x[2] <<
485/// ", " << x[3] <<" }\n";
486/// @endcode
487/// Next, if any of the `ASSERTV`s following this point fail with no `GUARD`
488/// call in scope, they will lock the mutex before doing output. Note that the
489/// `ASSERTV`s do not lock the mutex while checking to see if the predicate
490/// passed to them is `false`.
491/// @code
492/// for (int ii = 0; ii < 4; ++ii) {
493/// ASSERTV(threadIdx, ii, x[ii], x[ii] < k_HI_LIMIT_X);
494/// ASSERTV(threadIdx, ii, x[ii], k_LO_LIMIT_X < x[ii]);
495/// }
496///
497/// double exp = x[0] * x[0];
498/// ASSERTV(x[0], exp, SU::sumOfSquares(x[0]),
499/// exp == SU::sumOfSquares(x[0]));
500///
501/// exp += x[1] * x[1];
502/// ASSERTV(x[0], x[1], exp, SU::sumOfSquares(x[0], x[1]),
503/// exp == SU::sumOfSquares(x[0], x[1]));
504///
505/// exp += x[2] * x[2];
506/// ASSERTV(x[0], x[1], x[2], exp, SU::sumOfSquares(x[0], x[1], x[2]),
507/// exp == SU::sumOfSquares(x[0], x[1], x[2]));
508///
509/// exp += x[3] * x[3];
510/// ASSERTV(x[0], x[1], x[2], x[3], exp,
511/// SU::sumOfSquares(x[0], x[1], x[2], x[3]),
512/// exp == SU::sumOfSquares(x[0], x[1], x[2], x[3]));
513/// @endcode
514/// Then, if we want to do any more output, since the mutex has not been
515/// acquired at this point, we have to re-acquire it. We have a choice between
516/// using `COUT` again, as we did above, or by using `GUARD` and `bsl::cout`:
517/// @code
518/// if (veryVerbose) {
519/// GUARD;
520///
521/// bsl::cout << "Thread number " << threadIdx << " finishing.\n";
522/// }
523/// }
524/// };
525/// @endcode
526/// Next, in `main`, we spawn our threads and let them run:
527/// @code
528/// int main()
529/// {
530/// // ..
531///
532/// using namespace BloombergLP;
533///
534/// bslmt::ThreadGroup tg;
535/// tg.addThreads(SumUtilTest(), k_NUM_THREADS);
536/// @endcode
537/// Then, we join the threads:
538/// @code
539/// tg.joinAll();
540/// @endcode
541/// Now, we observe output something like this (tabs eliminated, long lines
542/// wrapped). Note that each of the five test threads reported a failure:
543/// @code
544/// x[0]: 24.0005 x[1]: 80.0001 x[2]: 14.0009 x[3]: 3.00029 exp: 7181.07
545/// SU::sumOfSquares(x[0], x[1], x[2], x[3]): 7199.08
546/// Error ../../bde/groups/bsl/bslmt/bslmt_testutil.t.cpp(380):
547/// exp == SU::sumOfSquares(x[0], x[1], x[2], x[3]) (failed)
548/// x[0]: -81.0006 x[1]: -82.0009 x[2]: 36.0009 x[3]: -59.0002
549/// exp: 18062.3 SU::sumOfSquares(x[0], x[1], x[2], x[3]): -190799
550/// Error ../../bde/groups/bsl/bslmt/bslmt_testutil.t.cpp(380):
551/// exp == SU::sumOfSquares(x[0], x[1], x[2], x[3]) (failed)
552/// x[0]: 46.0001 x[1]: -62.0004 x[2]: 75.0006 x[3]: -66.0008 exp: 15941.3
553/// SU::sumOfSquares(x[0], x[1], x[2], x[3]): -275921
554/// Error ../../bde/groups/bsl/bslmt/bslmt_testutil.t.cpp(380):
555/// exp == SU::sumOfSquares(x[0], x[1], x[2], x[3]) (failed)
556/// x[0]: -18.0003 x[1]: -84.0006 x[2]: 79.0004 x[3]: 76.0007 exp: 19397.3
557/// SU::sumOfSquares(x[0], x[1], x[2], x[3]): 452609
558/// Error ../../bde/groups/bsl/bslmt/bslmt_testutil.t.cpp(380):
559/// exp == SU::sumOfSquares(x[0], x[1], x[2], x[3]) (failed)
560/// x[0]: -55.0006 x[1]: 35.0004 x[2]: 54.0009 x[3]: -45.0002 exp: 9191.21
561/// SU::sumOfSquares(x[0], x[1], x[2], x[3]): -83960.1
562/// Error ../../bde/groups/bsl/bslmt/bslmt_testutil.t.cpp(380):
563/// exp == SU::sumOfSquares(x[0], x[1], x[2], x[3]) (failed)
564/// @endcode
565/// Finally, at the end of `main` examine `testStatus`. If it's greater than 0,
566/// report that the test failed. Note that since there is a bug in
567/// `SU::sumOfSquares` with 4 args, we expect the last assert in
568/// `SumUtil::operator()` to fail 5 times, so the following message will report
569/// `test status = 5`.
570/// @code
571///
572/// if (testStatus > 0) {
573/// bsl::cerr << "Error, non-zero test status = " << testStatus << "."
574/// << bsl::endl;
575/// }
576///
577/// return testStatus;
578/// }
579/// @endcode
580/// @}
581/** @} */
582/** @} */
583
584/** @addtogroup bsl
585 * @{
586 */
587/** @addtogroup bslmt
588 * @{
589 */
590/** @addtogroup bslmt_testutil
591 * @{
592 */
593
594#include <bslscm_version.h>
595
596#include <bslmt_recursivemutex.h>
597
598#include <bslmf_assert.h>
599
600#include <bsls_keyword.h>
601#include <bsls_unspecifiedbool.h>
602
603#include <bsl_iostream.h>
604#include <bsl_string.h>
605
606 // =================
607 // Macro Definitions
608 // =================
609
610#define BSLMT_TESTUTIL_GUARD_NAME_IMPL \
611 bloomberglp_bslmt_tEsTuTiL_GuArD_ ## __LINE__
612
613/// Acquire the critical section, and release it when the macro call goes
614/// out of scope. If the critical section is already held by the current
615/// thread, this can still be used with no additional effect.
616#define BSLMT_TESTUTIL_GUARD \
617 BloombergLP::bslmt::TestUtil_Guard BSLMT_TESTUTIL_GUARD_NAME_IMPL
618
619#define BSLMT_TESTUTIL_OUTPUT_GUARD BSLMT_TESTUTIL_GUARD
620#define BSLMT_TESTUTIL_NESTED_OUTPUT_GUARD BSLMT_TESTUTIL_GUARD
621
622/// Enable output to the specified `STREAM` that will not be interleaved
623/// with output from @ref bslmt_testutil macros done by other threads.
624/// `STREAM` is expected to be a `bsl::ostream` object, and this macro call
625/// can be output to with the C++ `<<` operator with all output until the
626/// terminating `;` occurring as one non-interleaved block.
627#define BSLMT_TESTUTIL_GUARDED_STREAM(STREAM) \
628 for (BSLMT_TESTUTIL_GUARD; BSLMT_TESTUTIL_GUARD_NAME_IMPL; \
629 BSLMT_TESTUTIL_GUARD_NAME_IMPL = false) \
630 (STREAM)
631
632/// Equivalent to call to `bsl::cout` guarded by a `BSLMT_TESTUTIL_GUARD`
633/// whose scope ends at the end of the statement.
634#define BSLMT_TESTUTIL_COUT BSLMT_TESTUTIL_GUARDED_STREAM(bsl::cout)
635
636/// Equivalent to call to `bsl::cerr` guarded by a `BSLMT_TESTUTIL_GUARD`
637/// whose scope ends at the end of the statement.
638#define BSLMT_TESTUTIL_CERR BSLMT_TESTUTIL_GUARDED_STREAM(bsl::cerr)
639
640#define BSLMT_TESTUTIL_LOOP0_ASSERT(X) \
641 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
642 aSsErT(1, #X, __LINE__); } while (false)
643
644#define BSLMT_TESTUTIL_ASSERT(X) BSLMT_TESTUTIL_LOOP0_ASSERT(X)
645
646#define BSLMT_TESTUTIL_LOOP1_ASSERT(I,X) \
647 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
648 bsl::cout << #I << ": " << (I) << "\n"; \
649 aSsErT(1, #X, __LINE__); } while (false)
650
651#define BSLMT_TESTUTIL_LOOP_ASSERT(X) BSLMT_TESTUTIL_LOOP1_ASSERT(X)
652
653#define BSLMT_TESTUTIL_LOOP2_ASSERT(I,J,X) \
654 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
655 bsl::cout << #I << ": " << (I) << "\t" \
656 << #J << ": " << (J) << "\n"; \
657 aSsErT(1, #X, __LINE__); } while (false)
658
659#define BSLMT_TESTUTIL_LOOP3_ASSERT(I,J,K,X) \
660 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
661 bsl::cout << #I << ": " << (I) << "\t" \
662 << #J << ": " << (J) << "\t" \
663 << #K << ": " << (K) << "\n"; \
664 aSsErT(1, #X, __LINE__); } while (false)
665
666#define BSLMT_TESTUTIL_LOOP4_ASSERT(I,J,K,L,X) \
667 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
668 bsl::cout << #I << ": " << (I) << "\t" \
669 << #J << ": " << (J) << "\t" \
670 << #K << ": " << (K) << "\t" \
671 << #L << ": " << (L) << "\n"; \
672 aSsErT(1, #X, __LINE__); } while (false)
673
674#define BSLMT_TESTUTIL_LOOP5_ASSERT(I,J,K,L,M,X) \
675 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
676 bsl::cout << #I << ": " << (I) << "\t" \
677 << #J << ": " << (J) << "\t" \
678 << #K << ": " << (K) << "\t" \
679 << #L << ": " << (L) << "\t" \
680 << #M << ": " << (M) << "\n"; \
681 aSsErT(1, #X, __LINE__); } while (false)
682
683#define BSLMT_TESTUTIL_LOOP6_ASSERT(I,J,K,L,M,N,X) \
684 if (X) ; else do { BSLMT_TESTUTIL_GUARD; \
685 bsl::cout << #I << ": " << (I) << "\t" \
686 << #J << ": " << (J) << "\t" \
687 << #K << ": " << (K) << "\t" \
688 << #L << ": " << (L) << "\t" \
689 << #M << ": " << (M) << "\t" \
690 << #N << ": " << (N) << "\n"; \
691 aSsErT(1, #X, __LINE__); } while (false)
692
693// The 'BSLMT_TESTUTIL_EXPAND' macro is required to work around a preprocessor
694// issue on Windows that prevents '__VA_ARGS__' from being expanded in the
695// definition of 'BSLMT_TESTUTIL_NUM_ARGS'.
696
697#define BSLMT_TESTUTIL_EXPAND(X) \
698 X
699
700#define BSLMT_TESTUTIL_NUM_ARGS_IMPL(X6, X5, X4, X3, X2, X1, X0, N, ...) \
701 N
702
703#define BSLMT_TESTUTIL_NUM_ARGS(...) \
704 BSLMT_TESTUTIL_EXPAND(BSLMT_TESTUTIL_NUM_ARGS_IMPL( \
705 __VA_ARGS__, 6, 5, 4, 3, 2, 1, 0, ""))
706
707#define BSLMT_TESTUTIL_LOOPN_ASSERT_IMPL(N, ...) \
708 BSLMT_TESTUTIL_EXPAND(BSLMT_TESTUTIL_LOOP ## N ## _ASSERT(__VA_ARGS__))
709
710#define BSLMT_TESTUTIL_LOOPN_ASSERT(N, ...) \
711 BSLMT_TESTUTIL_LOOPN_ASSERT_IMPL(N, __VA_ARGS__)
712
713#define BSLMT_TESTUTIL_ASSERTV(...) BSLMT_TESTUTIL_LOOPN_ASSERT( \
714 BSLMT_TESTUTIL_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
715
716// The following four macros guarantee atomicity of their output by implicitly
717// creating a GUARD objects. As with the other macros, these macros can be
718// used within the scope of another GUARD object.
719
720/// Quote identifier literally.
721#define BSLMT_TESTUTIL_Q(X) \
722 BSLMT_TESTUTIL_COUT << "<| " #X " |>" << bsl::endl
723
724/// Print identifier and its value.
725#define BSLMT_TESTUTIL_P(X) \
726 BSLMT_TESTUTIL_COUT << #X " = " << (X) << bsl::endl
727
728/// `P(X)` without '\n'
729#define BSLMT_TESTUTIL_P_(X) \
730 BSLMT_TESTUTIL_COUT << #X " = " << (X) << ", " << bsl::flush
731
732/// Print tab (w/o newline). Do not put in a `do {} while(false)`, as this
733/// macro is intended to be called without a terminating `;`.
734#define BSLMT_TESTUTIL_T_ \
735 BSLMT_TESTUTIL_COUT << "\t" << bsl::flush;
736
737/// current Line number
738#define BSLMT_TESTUTIL_L_ \
739 __LINE__
740
741
742
743namespace bslmt {
744
745 // ===============
746 // struct TestUtil
747 // ===============
748
749/// This `struct` provides a namespace for a suite of utility functions that
750/// facilitate the creation of BDE-style test drivers.
751///
752/// The `callFunc` function, because it's out-of-line implementation is in
753/// the `.cpp` file, can be used to prevent unwanted inlining in test
754/// drivers, particularly useful when testing the stack trace functionality.
755struct TestUtil {
756
757 private:
758 // PRIVATE CLASS METHODS
759
760 /// Return `ptr` without modification. Note that this is NOT an inline
761 /// function, so that if the caller is not in the same module, the
762 /// compiler has no way of knowing that it's an identity transform.
763 static void *identityPtr(void *ptr);
764
765 public:
766 // CLASS METHODS
767
768 /// Return the specified `functionPtr` (expected to be a static function
769 /// pointer) without modification. The value of `functionPtr` is
770 /// transformed through `identityPtr` so that if the caller is in a
771 /// different module, the compiler will have no way of knowing that this
772 /// is an identity function and thus no way of inlining the call.
773 template <class FUNCTION_PTR>
774 static FUNCTION_PTR makeFunctionCallNonInline(FUNCTION_PTR functionPtr);
775};
776
777 // ====================
778 // class TestUtil_Guard
779 // ====================
780
781/// This `class` defines an object that provides exclusive access to the
782/// critical sections defined by this component's macros. Multiple `Guard`
783/// objects can exist at once, but only in the same thread -- if an attempt
784/// is made to construct a `Guard` while any `Guard`s exist in other
785/// threads, the constructor will block until all `Guard` objects in other
786/// threads are destroyed. The behavior is undefined if a `Guard` object is
787/// anywhere but on the stack.
788///
789/// See @ref bslmt_testutil
791
792 // PRIVATE TYPE
794
795 public:
796 // PUBLIC TYPE
798
799 private:
800 // DATA
801 RecursiveMutex *d_mutex_p;
802 bool d_boolState; // boolean state assignable by 'operator='
803 // and observable by casting the object to
804 // 'bool'.
805
806 // PRIVATE CLASS METHOD
807
808 /// Return a non-`const` reference to the recursive mutex created by the
809 /// singleton.
810 static RecursiveMutex& singletonMutex();
811
812 private:
813 // NOT IMPLEMENTED
816
817 public:
818 // CREATORS
819
820 /// Create a guard that locks the mutex in the singleton and saves the
821 /// address of the singleton mutex.
823
824 /// Unlock the recursive mutex that was locked by the constructor.
826
827 // MANIPULATOR
828
829 /// Set the boolean state of this object to the specified `rhs`.
830 void operator=(bool rhs);
831
832 // ACCESSOR
833
834 /// Return the boolean state of this `TestUtil_Guard` object.
835 operator BoolType() const;
836};
837
838// ============================================================================
839// INLINE FUNCTION DEFINITIONS
840// ============================================================================
841
842 // --------
843 // TestUtil
844 // --------
845
846template <class FUNCTION_PTR>
847inline
848FUNCTION_PTR TestUtil::makeFunctionCallNonInline(FUNCTION_PTR functionPtr)
849{
850 BSLMF_ASSERT(sizeof(FUNCTION_PTR) == sizeof(void *));
851
852 return reinterpret_cast<FUNCTION_PTR>(
853 identityPtr(reinterpret_cast<void *>(functionPtr)));
854}
855
856 // --------------------
857 // class TestUtil_Guard
858 // --------------------
859
860inline
862: d_boolState(true)
863{
864 (d_mutex_p = &singletonMutex())->lock();
865}
866
867inline
869{
870 d_mutex_p->unlock();
871}
872
873inline
874void TestUtil_Guard::operator=(bool rhs)
875{
876 d_boolState = rhs;
877}
878
879inline
880TestUtil_Guard::operator TestUtil_Guard::BoolType() const
881{
882 return UnspecifiedBool::makeValue(d_boolState);
883}
884
885} // close package namespace
886
887
888#endif
889
890// ----------------------------------------------------------------------------
891// Copyright 2018 Bloomberg Finance L.P.
892//
893// Licensed under the Apache License, Version 2.0 (the "License");
894// you may not use this file except in compliance with the License.
895// You may obtain a copy of the License at
896//
897// http://www.apache.org/licenses/LICENSE-2.0
898//
899// Unless required by applicable law or agreed to in writing, software
900// distributed under the License is distributed on an "AS IS" BASIS,
901// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
902// See the License for the specific language governing permissions and
903// limitations under the License.
904// ----------------------------- END-OF-FILE ----------------------------------
905
906/** @} */
907/** @} */
908/** @} */
Definition bslmt_recursivemutex.h:130
void unlock()
Definition bslmt_recursivemutex.h:206
Definition bslmt_testutil.h:790
TestUtil_Guard()
Definition bslmt_testutil.h:861
~TestUtil_Guard()
Unlock the recursive mutex that was locked by the constructor.
Definition bslmt_testutil.h:868
UnspecifiedBool::BoolType BoolType
Definition bslmt_testutil.h:797
Definition bsls_unspecifiedbool.h:177
int UnspecifiedBool::* BoolType
Definition bsls_unspecifiedbool.h:190
static BoolType makeValue(bool predicate)
Definition bsls_unspecifiedbool.h:231
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
Definition bslmt_barrier.h:344
Definition bslmt_testutil.h:755
static FUNCTION_PTR makeFunctionCallNonInline(FUNCTION_PTR functionPtr)
Definition bslmt_testutil.h:848