BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsls_bsltestutil.h
Go to the documentation of this file.
1/// @file bsls_bsltestutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_bsltestutil.h -*-C++-*-
8#ifndef INCLUDED_BSLS_BSLTESTUTIL
9#define INCLUDED_BSLS_BSLTESTUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_bsltestutil bsls_bsltestutil
15/// @brief Provide test utilities for `bsl` that do not use <iostream>.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_bsltestutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_bsltestutil-purpose"> Purpose</a>
25/// * <a href="#bsls_bsltestutil-classes"> Classes </a>
26/// * <a href="#bsls_bsltestutil-macros"> Macros </a>
27/// * <a href="#bsls_bsltestutil-description"> Description </a>
28/// * <a href="#bsls_bsltestutil-usage"> Usage </a>
29/// * <a href="#bsls_bsltestutil-example-1-writing-a-test-driver"> Example 1: Writing a Test Driver </a>
30/// * <a href="#bsls_bsltestutil-define-assert-}"> define ASSERT(X) { aSsErT(!(X), #X, __LINE__); } </a>
31/// * <a href="#bsls_bsltestutil-example-2-adding-support-for-a-new-user-defined-type"> Example 2: Adding Support For A New User-Defined Type </a>
32/// * <a href="#bsls_bsltestutil-example-3-printing-unusual-types-with-printf"> Example 3: Printing Unusual Types with printf </a>
33///
34/// # Purpose {#bsls_bsltestutil-purpose}
35/// Provide test utilities for `bsl` that do not use <iostream>.
36///
37/// # Classes {#bsls_bsltestutil-classes}
38///
39/// - bsls::BslTestUtil: utilities to aid writing `bsl` test drivers
40///
41/// # Macros {#bsls_bsltestutil-macros}
42///
43/// - BSLS_BSLTESTUTIL_ASSERT(X): record and print error if `!X`
44/// - BSLS_BSLTESTUTIL_LOOP_ASSERT(I, X): print args if `!X`
45/// - BSLS_BSLTESTUTIL_LOOP2_ASSERT(I, J, X): print args if `!X`
46/// - BSLS_BSLTESTUTIL_LOOP3_ASSERT(I, J, K, X): print args if `!X`
47/// - BSLS_BSLTESTUTIL_LOOP4_ASSERT(I, J, K, L, X): print args if `!X`
48/// - BSLS_BSLTESTUTIL_LOOP5_ASSERT(I, J, K, L, M, X): print args if `!X`
49/// - BSLS_BSLTESTUTIL_LOOP6_ASSERT(I, J, K, L, M, N, X): print args if `!X`
50/// - BSLS_BSLTESTUTIL_LOOP7_ASSERT(I, J, K, L, M, N, O, X): print args if `!X`
51/// - BSLS_BSLTESTUTIL_LOOP8_ASSERT(I, J, K, L, M, N, O,V, X): print args if `!X`
52///
53/// BSLS_BSLTESTUTIL_Q(X) : quote identifier literally
54/// BSLS_BSLTESTUTIL_P(X) : print identifier and value
55/// BSLS_BSLTESTUTIL_P_(X): print identifier and value without '\n'
56/// BSLS_BSLTESTUTIL_L_ : current line number
57/// BSLS_BSLTESTUTIL_T_ : print tab without '\n'
58///
59/// BSLS_BSLTESTUTIL_FORMAT_ZU : `printf` format for `size_t`
60/// BSLS_BSLTESTUTIL_FORMAT_TD : `printf` format for `ptrdiff_t`
61/// BSLS_BSLTESTUTIL_FORMAT_I64: `printf` format for unsigned 64-bit integers
62/// BSLS_BSLTESTUTIL_FORMAT_U64: `printf` format for signed 64-bit integers
63/// BSLS_BSLTESTUTIL_FORMAT_PTR: `printf` format for `uintptr_t`
64///
65/// # Description {#bsls_bsltestutil-description}
66/// This component provides standard facilities for components in
67/// the `bsl` package group to produce test driver output, including the
68/// standard printing macros used in BDE-style test drivers (`ASSERT`,
69/// `LOOP_ASSERT`, `ASSERTV`, `P`, `Q`, `L`, and `T`), and a suite of
70/// cross-platform format strings for printing C++ or BDE-specific types with
71/// `printf`.
72///
73/// Many components in the `bsl` package group reside below the standard
74/// library; therefore, hierarchical design dictates that the test driver for
75/// these components shall not use `iostream` (which is part of the standard
76/// library), and instead they shall only rely on the `printf` function to print
77/// objects' values. Using `printf` over `iostream` has the following
78/// disadvantages:
79///
80/// * The `printf` function requires a format string to specify the way to
81/// print an object; so, unlike `iostream`, printing different types of
82/// objects using `printf` requires different syntaxes due to the need for
83/// different format strings.
84/// * While the format strings for built-in types can be included as part of
85/// the standard boiler plate code of the test driver, printing a
86/// user-defined type often requires additional code that is not part of the
87/// standard boilerplate.
88///
89/// This component provides solutions to these issues by (1) encapsulating all
90/// the standard printing macros in a single place, (2) providing a way to
91/// extend the supplied macros to support user-defined types, and (3) providing
92/// macros that resolve the correct `printf` format strings for types that do
93/// not have standard, cross-platform format strings of their own.
94///
95/// The macros in this component use a class method template,
96/// `BslTestUtil::callDebugprint`, to print the value of an object of the
97/// parameterized type, along with an optional leading string and an optional
98/// trailing string, to the console. The value of the object of the
99/// parameterized type will be printed using a free function named `debugprint`.
100///
101/// The macros defined in this component natively support built-in types through
102/// the `debugprint` function overloads for these types defined in this
103/// component. The macros can be extended support additional user-defined types
104/// by defining function overloads for `debugprint` that takes a single
105/// parameter of each user-defined type, in the same namespace in which the
106/// user-defined type is defined. See the second usage example for more
107/// details.
108///
109/// ## Usage {#bsls_bsltestutil-usage}
110///
111///
112/// This section illustrates intended use of this component.
113///
114/// ### Example 1: Writing a Test Driver {#bsls_bsltestutil-example-1-writing-a-test-driver}
115///
116///
117/// First, we write a component to test, which provides a utility class:
118/// @code
119/// namespace bslabc {
120///
121/// struct BslExampleUtil {
122/// // This utility class provides sample functionality to demonstrate how
123/// // a test driver might be written validating its only method.
124///
125/// static int fortyTwo();
126/// // Return the integer value '42'.
127/// };
128///
129/// inline
130/// int BslExampleUtil::fortyTwo()
131/// {
132/// return 42;
133/// }
134///
135/// } // close package namespace
136/// @endcode
137/// Then, we can write a test driver for this component. We start by providing
138/// the standard BDE assert test macro:
139/// @code
140/// // ========================================================================
141/// // STANDARD BDE ASSERT TEST MACRO
142/// // ------------------------------------------------------------------------
143/// static int testStatus = 0;
144///
145/// static void aSsErT(bool b, const char *s, int i)
146/// {
147/// if (b) {
148/// printf("Error " __FILE__ "(%d): %s (failed)\n", i, s);
149/// fflush(stdout);
150/// if (testStatus >= 0 && testStatus <= 100) ++testStatus;
151/// }
152/// }
153///
154/// # define ASSERT(X) { aSsErT(!(X), #X, __LINE__); } {#bsls_bsltestutil-define-assert-}}
155///
156/// @endcode
157/// Next, we define the standard print and `LOOP_ASSERT` macros, as aliases to
158/// the macros defined by this component:
159/// @code
160/// // ========================================================================
161/// // STANDARD BDE TEST DRIVER MACROS
162/// // ------------------------------------------------------------------------
163/// #define LOOP_ASSERT BSLS_BSLTESTUTIL_LOOP_ASSERT
164/// #define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT
165/// #define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT
166/// #define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT
167/// #define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT
168/// #define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT
169/// #define LOOP7_ASSERT BSLS_BSLTESTUTIL_LOOP7_ASSERT
170/// #define LOOP8_ASSERT BSLS_BSLTESTUTIL_LOOP8_ASSERT
171///
172/// #define Q BSLS_BSLTESTUTIL_Q // Quote identifier literally.
173/// #define P BSLS_BSLTESTUTIL_P // Print identifier and value.
174/// #define P_ BSLS_BSLTESTUTIL_P_ // 'P(X)' without '\n'.
175/// #define T_ BSLS_BSLTESTUTIL_T_ // Print a tab (w/o newline).
176/// #define L_ BSLS_BSLTESTUTIL_L_ // current Line number
177/// @endcode
178/// Now, using the (standard) abbreviated macro names we have just defined, we
179/// write a test function for the `static` `fortyTwo` method, to be called from
180/// a test case in a test driver.
181/// @code
182/// void testFortyTwo(bool verbose)
183/// {
184/// const int value = bslabc::BslExampleUtil::fortyTwo();
185/// if (verbose) P(value);
186/// LOOP_ASSERT(value, 42 == value);
187/// }
188/// @endcode
189/// Finally, when `testFortyTwo` is called from a test case in verbose mode we
190/// observe the console output:
191/// @code
192/// value = 42
193/// @endcode
194///
195/// ### Example 2: Adding Support For A New User-Defined Type {#bsls_bsltestutil-example-2-adding-support-for-a-new-user-defined-type}
196///
197///
198/// First, we define a new user-defined type, `MyType`:
199/// @code
200/// namespace xyza {
201///
202/// class MyType {
203/// // This elided class provides a type intended to show how the macros in
204/// // 'bsls_bsltestutil' can be extended to support a new user-defined
205/// // type.
206///
207/// private:
208/// // DATA
209/// int d_value; // the value of MyType
210///
211/// // ...
212///
213/// public:
214/// // CREATORS
215///
216/// // ...
217///
218/// explicit MyType(int value);
219/// // Create a 'MyType' object with 'd_value' set to the specified
220/// // 'value'.
221///
222/// // ACCESSORS
223///
224/// // ...
225///
226/// int value() const;
227/// // Return the value of 'd_value'.
228///
229/// // ...
230/// };
231///
232/// // ...
233///
234/// inline
235/// MyType::MyType(int value)
236/// : d_value(value)
237/// {
238/// }
239///
240/// // ...
241///
242/// inline
243/// int MyType::value() const
244/// {
245/// return d_value;
246/// }
247/// @endcode
248/// Then, in the same namespace in which `MyType` is defined, we define a
249/// function `debugprint` that prints the value of a `MyType` object to the
250/// console. (In this case, we will simply print a string literal for
251/// simplicity):
252/// @code
253/// void debugprint(const MyType& obj)
254/// {
255/// printf("MyType<%d>", obj.value());
256/// }
257///
258/// } // close namespace xyza
259/// @endcode
260/// Now, using the (standard) abbreviated macro names previously defined, we
261/// write a test function for the `MyType` constructor, to be called from a test
262/// case in a test driver.
263/// @code
264/// void testMyTypeSetValue(bool verbose) {
265/// xyza::MyType obj(9);
266/// if (verbose) P(obj);
267/// LOOP_ASSERT(obj.value(), obj.value() == 9);
268/// }
269/// @endcode
270/// Finally, when `testMyTypeSetValue` is called from a test case in verbose
271/// mode we observe the console output:
272/// @code
273/// obj = MyType<9>
274/// @endcode
275///
276/// ### Example 3: Printing Unusual Types with printf {#bsls_bsltestutil-example-3-printing-unusual-types-with-printf}
277///
278///
279/// Suppose we are writing a test driver that needs to print out the contents of
280/// a complex data structure in `veryVeryVerbose` mode. The complex data
281/// structure contains, among other values, an array of block sizes, expressed
282/// as `size_t`. It would be very cumbersome, and visually confusing, to print
283/// each member of the array with either the `P_` or `Q_` standard output
284/// macros, so we elect to print out the array as a single string, following the
285/// pattern of `[ A, B, C, D, E, ... ]`. This could be easily accomplished with
286/// multiple calls to `printf`, except that `printf` has no cross-platform
287/// standard formatting string for `size_t`. We can use the
288/// `BSLS_BSLTESTUTIL_FORMAT_ZU` macro to resolve the appropriate format string
289/// for us on each platform.
290///
291/// First, we write a component to test, which provides an a utility that
292/// operates on a list of memory blocks. Each block is a structure containing a
293/// base address, a block size, and a pointer to the next block in the list.
294/// @code
295/// namespace xyza {
296/// struct Block {
297/// // DATA
298/// char *d_address;
299/// size_t d_size;
300/// Block *d_next;
301///
302/// // ...
303/// };
304///
305/// class BlockList {
306/// // ...
307///
308/// // DATA
309/// Block *d_head;
310///
311/// // ...
312///
313/// public:
314/// // CREATORS
315/// BlockList();
316/// ~BlockList();
317///
318/// // MANIPULATORS
319///
320/// Block *begin();
321/// Block *end();
322///
323/// void addBlock(size_t size);
324///
325/// // ...
326///
327/// // ACCESSORS
328/// int length();
329///
330/// // ...
331/// };
332///
333/// } // close namespace xyza
334/// @endcode
335/// Then, we write a test driver for this component.
336/// @code
337/// // ...
338///
339/// // ========================================================================
340/// // STANDARD BDE TEST DRIVER MACROS
341/// // ------------------------------------------------------------------------
342///
343/// // ...
344/// @endcode
345/// Here, after defining the standard BDE test macros, we define a macro, `ZU`
346/// for the platform-specific `printf` format string for `size_t`:
347/// @code
348/// // ========================================================================
349/// // PRINTF FORMAT MACROS
350/// // ------------------------------------------------------------------------
351/// #define ZU BSLS_BSLTESTUTIL_FORMAT_ZU
352/// @endcode
353/// Note that, we could use `BSLS_BSLTESTUTIL_FORMAT_ZU` as is, but it is more
354/// convenient to define `ZU` locally as an abbreviation.
355///
356/// Next, we write the test apparatus for the test driver, which includes a
357/// support function that prints the list of blocks in a `BlockList` in a
358/// visually succinct form:
359/// @code
360/// void printBlockList(xyza::BlockList &list)
361/// {
362/// xyza::Block *blockPtr = list.begin();
363///
364/// printf("{\n");
365/// while (blockPtr != list.end()) {
366/// @endcode
367/// Here, we use `ZU` as the format specifier for the `size_t` in the `printf`
368/// invocation. `ZU` is the appropriate format specifier for `size_t` on each
369/// supported platform.
370/// @code
371/// printf("\t{ address: %p,\tsize: " ZU " }",
372/// blockPtr->d_address,
373/// blockPtr->d_size);
374/// blockPtr = blockPtr->d_next;
375///
376/// if (blockPtr) {
377/// printf(",\n");
378/// } else {
379/// printf("\n");
380/// }
381/// }
382/// printf("}\n");
383/// }
384/// @endcode
385/// Note that because we are looping through a number of blocks, formatting the
386/// output directly with `printf` produces more readable output than we would
387/// get from calling the standard output macros.
388///
389/// Calling `printf` directly will yield output similar to:
390/// @code
391/// {
392/// { address: 0x012345600, size: 32 },
393/// ...
394/// }
395/// @endcode
396/// while the standard output macros would have produced:
397/// @code
398/// {
399/// { blockPtr->d_address = 0x012345600, blockPtr->d_size: 32 },
400/// ...
401/// }
402/// @endcode
403/// Now, we write a test function for one of our test cases, which provides a
404/// detailed trace of `BlockList` contents:
405/// @code
406/// void testBlockListConstruction(bool veryVeryVerbose)
407/// {
408/// // ...
409///
410/// {
411/// xyza::BlockList bl;
412///
413/// bl.addBlock(42);
414/// bl.addBlock(19);
415/// bl.addBlock(1024);
416///
417/// if (veryVeryVerbose) {
418/// printBlockList(bl);
419/// }
420///
421/// ASSERT(3 == bl.length());
422///
423/// // ...
424/// }
425///
426/// // ...
427/// }
428/// @endcode
429/// Finally, when `testBlockListConstruction` is called from a test case in
430/// `veryVeryVerbose` mode, we observe console output similar to:
431/// @code
432/// {
433/// { address: 0x012345600, size: 42 },
434/// { address: 0x012345610, size: 19 },
435/// { address: 0x012345620, size: 1024 }
436/// }
437/// @endcode
438/// @}
439/** @} */
440/** @} */
441
442/** @addtogroup bsl
443 * @{
444 */
445/** @addtogroup bsls
446 * @{
447 */
448/** @addtogroup bsls_bsltestutil
449 * @{
450 */
451
452#include <bsls_platform.h>
453
454#if defined(BSLS_PLATFORM_CMP_MSVC)
455# include <stddef.h>
456#else
457# include <stdint.h>
458#endif
459
460 // =================
461 // Macro Definitions
462 // =================
463
464#define BSLS_BSLTESTUTIL_ASSERT(X) \
465 do { aSsErT(!(X), #X, __LINE__); } while (false)
466
467#define BSLS_BSLTESTUTIL_LOOP0_ASSERT \
468 BSLS_BSLTESTUTIL_ASSERT
469
470#define BSLS_BSLTESTUTIL_LOOP_ASSERT(I,X) do { \
471 if (!(X)) { BloombergLP::bsls:: \
472 BslTestUtil::callDebugprint(I, #I ": ", \
473 " (context)\n"); \
474 aSsErT(true, #X, __LINE__); } } while (false)
475
476#define BSLS_BSLTESTUTIL_LOOP1_ASSERT \
477 BSLS_BSLTESTUTIL_LOOP_ASSERT
478
479#define BSLS_BSLTESTUTIL_LOOP2_ASSERT(I,J,X) do { \
480 if (!(X)) { BloombergLP::bsls:: \
481 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
482 BloombergLP::bsls:: \
483 BslTestUtil::callDebugprint(J, #J ": ", \
484 " (context)\n"); \
485 aSsErT(true, #X, __LINE__); } } while (false)
486
487#define BSLS_BSLTESTUTIL_LOOP3_ASSERT(I,J,K,X) do { \
488 if (!(X)) { BloombergLP::bsls:: \
489 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
490 BloombergLP::bsls:: \
491 BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
492 BloombergLP::bsls:: \
493 BslTestUtil::callDebugprint(K, #K ": ", \
494 " (context)\n"); \
495 aSsErT(true, #X, __LINE__); } } while (false)
496
497#define BSLS_BSLTESTUTIL_LOOP4_ASSERT(I,J,K,L,X) do { \
498 if (!(X)) { BloombergLP::bsls:: \
499 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
500 BloombergLP::bsls:: \
501 BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
502 BloombergLP::bsls:: \
503 BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
504 BloombergLP::bsls:: \
505 BslTestUtil::callDebugprint(L, #L ": ", \
506 " (context)\n"); \
507 aSsErT(true, #X, __LINE__); } } while (false)
508
509#define BSLS_BSLTESTUTIL_LOOP5_ASSERT(I,J,K,L,M,X) do { \
510 if (!(X)) { BloombergLP::bsls:: \
511 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
512 BloombergLP::bsls:: \
513 BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
514 BloombergLP::bsls:: \
515 BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
516 BloombergLP::bsls:: \
517 BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
518 BloombergLP::bsls:: \
519 BslTestUtil::callDebugprint(M, #M ": ", \
520 " (context)\n"); \
521 aSsErT(true, #X, __LINE__); } } while (false)
522
523#define BSLS_BSLTESTUTIL_LOOP6_ASSERT(I,J,K,L,M,N,X) do { \
524 if (!(X)) { BloombergLP::bsls:: \
525 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
526 BloombergLP::bsls:: \
527 BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
528 BloombergLP::bsls:: \
529 BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
530 BloombergLP::bsls:: \
531 BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
532 BloombergLP::bsls:: \
533 BslTestUtil::callDebugprint(M, #M ": ", "\t"); \
534 BloombergLP::bsls:: \
535 BslTestUtil::callDebugprint(N, #N ": ", \
536 " (context)\n"); \
537 aSsErT(true, #X, __LINE__); } } while (false)
538
539#define BSLS_BSLTESTUTIL_LOOP7_ASSERT(I,J,K,L,M,N,O,X) do { \
540 if (!(X)) { BloombergLP::bsls:: \
541 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
542 BloombergLP::bsls:: \
543 BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
544 BloombergLP::bsls:: \
545 BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
546 BloombergLP::bsls:: \
547 BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
548 BloombergLP::bsls:: \
549 BslTestUtil::callDebugprint(M, #M ": ", "\t"); \
550 BloombergLP::bsls:: \
551 BslTestUtil::callDebugprint(N, #N ": ", "\t"); \
552 BloombergLP::bsls:: \
553 BslTestUtil::callDebugprint(O, #O ": ", \
554 " (context)\n"); \
555 aSsErT(true, #X, __LINE__); } } while (false)
556
557#define BSLS_BSLTESTUTIL_LOOP8_ASSERT(I,J,K,L,M,N,O,V,X) do { \
558 if (!(X)) { BloombergLP::bsls:: \
559 BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
560 BloombergLP::bsls:: \
561 BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
562 BloombergLP::bsls:: \
563 BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
564 BloombergLP::bsls:: \
565 BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
566 BloombergLP::bsls:: \
567 BslTestUtil::callDebugprint(M, #M ": ", "\t"); \
568 BloombergLP::bsls:: \
569 BslTestUtil::callDebugprint(N, #N ": ", "\t"); \
570 BloombergLP::bsls:: \
571 BslTestUtil::callDebugprint(O, #O ": ", "\t"); \
572 BloombergLP::bsls:: \
573 BslTestUtil::callDebugprint(V, #V ": ", \
574 " (context)\n"); \
575 aSsErT(true, #X, __LINE__); } } while (false)
576
577// The 'BSLS_BSLTESTUTIL_EXPAND' macro is required to workaround a
578// pre-processor issue on windows that prevents __VA_ARGS__ to be expanded in
579// the definition of 'BSLS_BSLTESTUTIL_NUM_ARGS'
580#define BSLS_BSLTESTUTIL_EXPAND(X) \
581 X
582
583#define BSLS_BSLTESTUTIL_NUM_ARGS_IMPL(X8, X7, X6, X5, X4, X3, X2, X1, X0, \
584 N, ...) \
585 N
586
587#define BSLS_BSLTESTUTIL_NUM_ARGS(...) \
588 BSLS_BSLTESTUTIL_EXPAND(BSLS_BSLTESTUTIL_NUM_ARGS_IMPL( \
589 __VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0, ""))
590
591#define BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL(N, ...) \
592 BSLS_BSLTESTUTIL_EXPAND(BSLS_BSLTESTUTIL_LOOP ## N ## _ASSERT(__VA_ARGS__))
593
594#define BSLS_BSLTESTUTIL_LOOPN_ASSERT(N, ...) \
595 BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL(N, __VA_ARGS__)
596
597#define BSLS_BSLTESTUTIL_ASSERTV(...) \
598 BSLS_BSLTESTUTIL_LOOPN_ASSERT( \
599 BSLS_BSLTESTUTIL_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
600
601// STANDARD TEST DRIVER OUTPUT MACROS
602
603/// Quote identifier literally.
604#define BSLS_BSLTESTUTIL_Q(X) \
605 BloombergLP::bsls:: \
606 BslTestUtil::printStringNoFlush("<| " #X " |>\n");
607
608/// Print identifier and its value.
609#define BSLS_BSLTESTUTIL_P(X) \
610 BloombergLP::bsls:: \
611 BslTestUtil::callDebugprint(X, #X " = ", "\n");
612
613/// P(X) without `\n`.
614#define BSLS_BSLTESTUTIL_P_(X) \
615 BloombergLP::bsls:: \
616 BslTestUtil::callDebugprint(X, #X " = ", ", ");
617
618/// Current line number.
619#define BSLS_BSLTESTUTIL_L_ __LINE__
620
621/// Print a tab (w/o newline).
622#define BSLS_BSLTESTUTIL_T_ BloombergLP::bsls::BslTestUtil::printTab();
623
624// PRINTF FORMAT MACROS
625#if defined(BSLS_PLATFORM_CMP_MSVC)
626# define BSLS_BSLTESTUTIL_FORMAT_ZU "%Iu"
627#else
628# define BSLS_BSLTESTUTIL_FORMAT_ZU "%zu"
629#endif
630 // Provide a platform-independent way to specify a 'size_t' format for
631 // 'printf'.
632
633#if defined(BSLS_PLATFORM_CMP_MSVC)
634# define BSLS_BSLTESTUTIL_FORMAT_TD "%Id"
635#else
636# define BSLS_BSLTESTUTIL_FORMAT_TD "%td"
637#endif
638 // Provide a platform-independent way to specify a 'ptrdiff_t' format for
639 // 'printf'.
640
641#if defined(BSLS_PLATFORM_CMP_MSVC)
642# define BSLS_BSLTESTUTIL_FORMAT_I64 "%I64d"
643#else
644# define BSLS_BSLTESTUTIL_FORMAT_I64 "%lld"
645#endif
646 // Provide a platform-independent way to specify a signed 64-bit integer
647 // format for 'printf'.
648
649#if defined(BSLS_PLATFORM_CMP_MSVC)
650# define BSLS_BSLTESTUTIL_FORMAT_U64 "%I64u"
651#else
652# define BSLS_BSLTESTUTIL_FORMAT_U64 "%llu"
653#endif
654 // Provide a platform-independent way to specify an unsigned 64-bit integer
655 // format for 'printf'.
656
657#if defined(BSLS_PLATFORM_CPU_64_BIT)
658# if defined(BSLS_PLATFORM_CMP_MSVC)
659# define BSLS_BSLTESTUTIL_FORMAT_PTR "%llX"
660# else
661# define BSLS_BSLTESTUTIL_FORMAT_PTR "%lX"
662# endif
663#else
664# define BSLS_BSLTESTUTIL_FORMAT_PTR "%X"
665#endif
666 // Provide a platform-independent way to specify a 'uintptr_t' integer
667 // format for 'printf'.
668
669
670
671namespace bsls {
672
673 // ==================
674 // struct BslTestUtil
675 // ==================
676
677/// This class provides a namespace for utilities that are useful when
678/// writing a test driver that is not permitted to use the standard C++
679/// iostream facilities, which is typical of test drivers in the `bsl`
680/// package group.
681///
682/// See @ref bsls_bsltestutil
684
685 private:
686 // PRIVATE CLASS METHODS
687
688 /// Return `ptr` without modification.
689 /// \note Note that this is NOT an inline
690 /// function, so that if the caller is not in the same module, the
691 /// compiler has no way of knowing that it's an identity transform.
692 static void *identityPtr(void *ptr);
693
694 public:
695 // CLASS METHODS
696
697 /// Write any unwritten text in the output buffer to `stdout`.
698 static void flush();
699
700 /// Print to the console the specified string, `s`.
701 /// \note Note that the
702 /// underlying stream is *not* flushed.
703 static void printStringNoFlush(const char *s);
704
705 /// Print to the console a tab character, and then `flush` the
706 /// underlying stream to ensure the text is written.
707 static void printTab();
708
709 /// Print the value of the specified `object` of the parameterized
710 /// `TYPE` to the console. Optionally specify a `leadingString`, which
711 /// will be printed before `object`, and a `trailingString`, which will
712 /// be printed after `object`. If `leadingString` is 0, then nothing
713 /// will be printed before `object`. If `trailingString` is 0, then
714 /// nothing will be printed after `object`.
715 template <class TYPE>
716 static void callDebugprint(const TYPE& object,
717 const char *leadingString = 0,
718 const char *trailingString = 0);
719
720 /// Return the specified `functionPtr` (expected to be a static function
721 /// pointer) without modification. The value of `functionPtr` is
722 /// transformed through `identityPtr` so that if the caller is in a
723 /// different module, the compiler will have no way of knowing that this
724 /// is an identity transform and thus no way of inlining the call.
725 ///
726 /// Note: the Windows optimizer is still able to inline the call, it may
727 /// be comparing the result of this function with the argument and
728 /// branching to inline on equality and call on inequality, so the
729 /// Windows optimizer has to be turned off with
730 /// `# pragma optimize("", off)`.
731 ///
732 /// Also note that even with an optimizer that can't figure out that
733 /// this is an identity transform, there is still the possibility of
734 /// chaining the call.
735 template <class FUNCTION_PTR>
736 static FUNCTION_PTR makeFunctionCallNonInline(FUNCTION_PTR functionPtr);
737};
738
739// FREE FUNCTIONS
740
741/// Print to the console the string "true" if the specified `v` is true, and
742/// the string "false" otherwise.
743void debugprint(bool v);
744
745/// Print to the console the specified character, `v`, enclosed by
746/// single-quote characters (').
747void debugprint(char v);
748
749/// Print to the console the specified integer value, `v`, formatted as a
750/// string.
751void debugprint(signed char v);
752void debugprint(unsigned char v);
753void debugprint(short v);
754void debugprint(unsigned short v);
755void debugprint(int v);
756void debugprint(unsigned int v);
757void debugprint(long v);
758void debugprint(unsigned long v);
759void debugprint(long long v);
760void debugprint(unsigned long long v);
761
762/// Print to the console the specified value, `v`, formatted as a string
763/// enclosed by single-quote characters (').
764void debugprint(float v);
765void debugprint(double v);
766void debugprint(long double v);
767
768/// Print to the console the specified string, `v`, enclosed by quote
769/// characters ("), unless `v` is null, in which case print `(null)`
770/// (without quotes of any kind).
771void debugprint(const char * v);
772void debugprint(char * v);
773void debugprint(const volatile char *v);
774void debugprint(volatile char *v);
775
776/// Print to the console the specified memory address, `v`, formatted as a
777/// hexadecimal integer.
778void debugprint(void * v);
779void debugprint(volatile void * v);
780void debugprint(const void * v);
781void debugprint(const volatile void *v);
782
783/// Print to the console the specified function pointer, `v`, formatted as a
784/// hexadecimal integer. On some platforms (notably Windows), a function
785/// pointer is treated differently from an object pointer, and the compiler
786/// will not be able to determine which `void *` overload of `debugprint`
787/// should be used for a function pointer. Therefore an overload of
788/// `debugprint` is provided specifically for function pointers. Because
789/// the type signature of a function pointer varies with its return type as
790/// well as with its argument list, a template function is used, to provide
791/// matches for all return types.
792template <class RESULT>
793void debugprint(RESULT (*v)());
794
795// ============================================================================
796// TEMPLATE AND INLINE FUNCTION DEFINITIONS
797// ============================================================================
798
799 // ------------------
800 // struct BslTestUtil
801 // ------------------
802
803// CLASS METHODS
804template <class TYPE>
805void BslTestUtil::callDebugprint(const TYPE& obj,
806 const char *leadingString,
807 const char *trailingString)
808{
809 if (leadingString) {
810 BloombergLP::bsls::BslTestUtil::printStringNoFlush(leadingString);
811 }
812
813 debugprint(obj);
814
815 if (trailingString) {
816 BloombergLP::bsls::BslTestUtil::printStringNoFlush(trailingString);
817 }
818 flush();
819}
820
821template <class FUNCTION_PTR>
822inline
823FUNCTION_PTR BslTestUtil::makeFunctionCallNonInline(FUNCTION_PTR function)
824{
825 // @ref static_assert isn't available pre-C++11, and 'BSLMF_ASSERT' is not
826 // accessible from here in bsls, so we divide by the boolean expression
827 // under test -- if the boolean expression is 'false', it will be a
828 // divide-by-zero in an enum and fail to compile, thus providing us with a
829 // "poor man's" compile-time assert.
830 //
831 // The cast to 'int' is necessary because dividing by 'bool' gives a
832 // compiler warning on Windows.
833
834 enum { k_STATIC_ASSERT = 1 /
835 static_cast<int>(sizeof(FUNCTION_PTR) == sizeof(void *)) };
836
837 return reinterpret_cast<FUNCTION_PTR>(identityPtr(reinterpret_cast<void *>(
838 function)));
839}
840
841} // close package namespace
842
843// FREE FUNCTIONS
844template <class RESULT>
845void bsls::debugprint(RESULT (*v)())
846{
847 uintptr_t address = reinterpret_cast<uintptr_t>(v);
848 debugprint(reinterpret_cast<void *>(address));
849}
850
851
852
853#endif
854
855// ----------------------------------------------------------------------------
856// Copyright 2018 Bloomberg Finance L.P.
857//
858// Licensed under the Apache License, Version 2.0 (the "License");
859// you may not use this file except in compliance with the License.
860// You may obtain a copy of the License at
861//
862// http://www.apache.org/licenses/LICENSE-2.0
863//
864// Unless required by applicable law or agreed to in writing, software
865// distributed under the License is distributed on an "AS IS" BASIS,
866// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
867// See the License for the specific language governing permissions and
868// limitations under the License.
869// ----------------------------- END-OF-FILE ----------------------------------
870
871/** @} */
872/** @} */
873/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlt_iso8601util.h:707
void debugprint(bool v)
Definition bsls_bsltestutil.h:683
static void flush()
Write any unwritten text in the output buffer to stdout.
static void printTab()
static void printStringNoFlush(const char *s)
static void callDebugprint(const TYPE &object, const char *leadingString=0, const char *trailingString=0)
Definition bsls_bsltestutil.h:805
static FUNCTION_PTR makeFunctionCallNonInline(FUNCTION_PTR functionPtr)
Definition bsls_bsltestutil.h:823