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