BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_bsltestutil

Macros

#define BSLS_BSLTESTUTIL_ASSERT(X)    do { aSsErT(!(X), #X, __LINE__); } while (false)
 
#define BSLS_BSLTESTUTIL_LOOP0_ASSERT    BSLS_BSLTESTUTIL_ASSERT
 
#define BSLS_BSLTESTUTIL_LOOP_ASSERT(I, X)
 
#define BSLS_BSLTESTUTIL_LOOP1_ASSERT    BSLS_BSLTESTUTIL_LOOP_ASSERT
 
#define BSLS_BSLTESTUTIL_LOOP2_ASSERT(I, J, X)
 
#define BSLS_BSLTESTUTIL_LOOP3_ASSERT(I, J, K, X)
 
#define BSLS_BSLTESTUTIL_LOOP4_ASSERT(I, J, K, L, X)
 
#define BSLS_BSLTESTUTIL_LOOP5_ASSERT(I, J, K, L, M, X)
 
#define BSLS_BSLTESTUTIL_LOOP6_ASSERT(I, J, K, L, M, N, X)
 
#define BSLS_BSLTESTUTIL_LOOP7_ASSERT(I, J, K, L, M, N, O, X)
 
#define BSLS_BSLTESTUTIL_LOOP8_ASSERT(I, J, K, L, M, N, O, V, X)
 
#define BSLS_BSLTESTUTIL_EXPAND(X)    X
 
#define BSLS_BSLTESTUTIL_NUM_ARGS_IMPL(X8, X7, X6, X5, X4, X3, X2, X1, X0, N, ...)    N
 
#define BSLS_BSLTESTUTIL_NUM_ARGS(...)
 
#define BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL(N, ...)    BSLS_BSLTESTUTIL_EXPAND(BSLS_BSLTESTUTIL_LOOP ## N ## _ASSERT(__VA_ARGS__))
 
#define BSLS_BSLTESTUTIL_LOOPN_ASSERT(N, ...)    BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL(N, __VA_ARGS__)
 
#define BSLS_BSLTESTUTIL_ASSERTV(...)
 
#define BSLS_BSLTESTUTIL_Q(X)
 Quote identifier literally.
 
#define BSLS_BSLTESTUTIL_P(X)
 Print identifier and its value.
 
#define BSLS_BSLTESTUTIL_P_(X)
 P(X) without '
'.
 
#define BSLS_BSLTESTUTIL_L_   __LINE__
 Current line number.
 
#define BSLS_BSLTESTUTIL_T_   BloombergLP::bsls::BslTestUtil::printTab();
 Print a tab (w/o newline).
 
#define BSLS_BSLTESTUTIL_FORMAT_ZU   "%zu"
 
#define BSLS_BSLTESTUTIL_FORMAT_TD   "%td"
 
#define BSLS_BSLTESTUTIL_FORMAT_I64   "%lld"
 
#define BSLS_BSLTESTUTIL_FORMAT_U64   "%llu"
 
#define BSLS_BSLTESTUTIL_FORMAT_PTR   "%X"
 

Detailed Description

Outline

Purpose

Provide test utilities for bsl that do not use <iostream>.

Classes

Macros

Description

This component provides standard facilities for components in the bsl package group to produce test driver output, including the standard printing macros used in BDE-style test drivers (ASSERT, LOOP_ASSERT, ASSERTV, P, Q, L, and T), and a suite of cross-platform format strings for printing C++ or BDE-specific types with printf.

Many components in the bsl package group reside below the standard library; therefore, hierarchical design dictates that the test driver for these components shall not use iostream (which is part of the standard library), and instead they shall only rely on the printf function to print objects' values. Using printf over iostream has the following disadvantages:

This component provides solutions to these issues by (1) encapsulating all the standard printing macros in a single place, (2) providing a way to extend the supplied macros to support user-defined types, and (3) providing macros that resolve the correct printf format strings for types that do not have standard, cross-platform format strings of their own.

The macros in this component use a class method template, BslTestUtil::callDebugprint, to print the value of an object of the parameterized type, along with an optional leading string and an optional trailing string, to the console. The value of the object of the parameterized type will be printed using a free function named debugprint.

The macros defined in this component natively support built-in types through the debugprint function overloads for these types defined in this component. The macros can be extended support additional user-defined types by defining function overloads for debugprint that takes a single parameter of each user-defined type, in the same namespace in which the user-defined type is defined. See the second usage example for more details.

Usage

This section illustrates intended use of this component.

Example 1: Writing a Test Driver

First, we write a component to test, which provides a utility class:

namespace bslabc {
struct BslExampleUtil {
// This utility class provides sample functionality to demonstrate how
// a test driver might be written validating its only method.
static int fortyTwo();
// Return the integer value '42'.
};
inline
int BslExampleUtil::fortyTwo()
{
return 42;
}
} // close package namespace

Then, we can write a test driver for this component. We start by providing the standard BDE assert test macro:

// ========================================================================
// STANDARD BDE ASSERT TEST MACRO
// ------------------------------------------------------------------------
static int testStatus = 0;
static void aSsErT(bool b, const char *s, int i)
{
if (b) {
printf("Error " __FILE__ "(%d): %s (failed)\n", i, s);
if (testStatus >= 0 && testStatus <= 100) ++testStatus;
}
}
# define ASSERT(X) { aSsErT(!(X), #X, __LINE__); }

Next, we define the standard print and LOOP_ASSERT macros, as aliases to the macros defined by this component:

// ========================================================================
// STANDARD BDE TEST DRIVER MACROS
// ------------------------------------------------------------------------
#define LOOP_ASSERT BSLS_BSLTESTUTIL_LOOP_ASSERT
#define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT
#define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT
#define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT
#define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT
#define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT
#define LOOP7_ASSERT BSLS_BSLTESTUTIL_LOOP7_ASSERT
#define LOOP8_ASSERT BSLS_BSLTESTUTIL_LOOP8_ASSERT
#define Q BSLS_BSLTESTUTIL_Q // Quote identifier literally.
#define P BSLS_BSLTESTUTIL_P // Print identifier and value.
#define P_ BSLS_BSLTESTUTIL_P_ // 'P(X)' without '\n'.
#define T_ BSLS_BSLTESTUTIL_T_ // Print a tab (w/o newline).
#define L_ BSLS_BSLTESTUTIL_L_ // current Line number

Now, using the (standard) abbreviated macro names we have just defined, we write a test function for the static fortyTwo method, to be called from a test case in a test driver.

void testFortyTwo(bool verbose)
{
const int value = bslabc::BslExampleUtil::fortyTwo();
if (verbose) P(value);
LOOP_ASSERT(value, 42 == value);
}

Finally, when testFortyTwo is called from a test case in verbose mode we observe the console output:

value = 42

Example 2: Adding Support For A New User-Defined Type

First, we define a new user-defined type, MyType:

namespace xyza {
class MyType {
// This elided class provides a type intended to show how the macros in
// 'bsls_bsltestutil' can be extended to support a new user-defined
// type.
private:
// DATA
int d_value; // the value of MyType
// ...
public:
// CREATORS
// ...
explicit MyType(int value);
// Create a 'MyType' object with 'd_value' set to the specified
// 'value'.
// ACCESSORS
// ...
int value() const;
// Return the value of 'd_value'.
// ...
};
// ...
inline
MyType::MyType(int value)
: d_value(value)
{
}
// ...
inline
int MyType::value() const
{
return d_value;
}

Then, in the same namespace in which MyType is defined, we define a function debugprint that prints the value of a MyType object to the console. (In this case, we will simply print a string literal for simplicity):

void debugprint(const MyType& obj)
{
printf("MyType<%d>", obj.value());
}
} // close namespace xyza

Now, using the (standard) abbreviated macro names previously defined, we write a test function for the MyType constructor, to be called from a test case in a test driver.

void testMyTypeSetValue(bool verbose) {
xyza::MyType obj(9);
if (verbose) P(obj);
LOOP_ASSERT(obj.value(), obj.value() == 9);
}

Finally, when testMyTypeSetValue is called from a test case in verbose mode we observe the console output:

obj = MyType<9>

Example 3: Printing Unusual Types with printf

Suppose we are writing a test driver that needs to print out the contents of a complex data structure in veryVeryVerbose mode. The complex data structure contains, among other values, an array of block sizes, expressed as size_t. It would be very cumbersome, and visually confusing, to print each member of the array with either the P_ or Q_ standard output macros, so we elect to print out the array as a single string, following the pattern of [ A, B, C, D, E, ... ]. This could be easily accomplished with multiple calls to printf, except that printf has no cross-platform standard formatting string for size_t. We can use the BSLS_BSLTESTUTIL_FORMAT_ZU macro to resolve the appropriate format string for us on each platform.

First, we write a component to test, which provides an a utility that operates on a list of memory blocks. Each block is a structure containing a base address, a block size, and a pointer to the next block in the list.

namespace xyza {
struct Block {
// DATA
char *d_address;
size_t d_size;
Block *d_next;
// ...
};
class BlockList {
// ...
// DATA
Block *d_head;
// ...
public:
// CREATORS
BlockList();
~BlockList();
// MANIPULATORS
Block *begin();
Block *end();
void addBlock(size_t size);
// ...
// ACCESSORS
int length();
// ...
};
} // close namespace xyza

Then, we write a test driver for this component.

// ...
// ========================================================================
// STANDARD BDE TEST DRIVER MACROS
// ------------------------------------------------------------------------
// ...

Here, after defining the standard BDE test macros, we define a macro, ZU for the platform-specific printf format string for size_t:

// ========================================================================
// PRINTF FORMAT MACROS
// ------------------------------------------------------------------------
#define ZU BSLS_BSLTESTUTIL_FORMAT_ZU

Note that, we could use BSLS_BSLTESTUTIL_FORMAT_ZU as is, but it is more convenient to define ZU locally as an abbreviation.

Next, we write the test apparatus for the test driver, which includes a support function that prints the list of blocks in a BlockList in a visually succinct form:

void printBlockList(xyza::BlockList &list)
{
xyza::Block *blockPtr = list.begin();
printf("{\n");
while (blockPtr != list.end()) {

Here, we use ZU as the format specifier for the size_t in the printf invocation. ZU is the appropriate format specifier for size_t on each supported platform.

printf("\t{ address: %p,\tsize: " ZU " }",
blockPtr->d_address,
blockPtr->d_size);
blockPtr = blockPtr->d_next;
if (blockPtr) {
printf(",\n");
} else {
printf("\n");
}
}
printf("}\n");
}

Note that because we are looping through a number of blocks, formatting the output directly with printf produces more readable output than we would get from callling the standard output macros.

Calling printf directly will yield output similar to:

{
{ address: 0x012345600, size: 32 },
...
}

while the standard output macros would have produced:

{
{ blockPtr->d_address = 0x012345600, blockPtr->d_size: 32 },
...
}

Now, we write a test function for one of our test cases, which provides a detailed trace of BlockList contents:

void testBlockListConstruction(bool veryVeryVerbose)
{
// ...
{
xyza::BlockList bl;
bl.addBlock(42);
bl.addBlock(19);
bl.addBlock(1024);
if (veryVeryVerbose) {
printBlockList(bl);
}
ASSERT(3 == bl.length());
// ...
}
// ...
}

Finally, when testBlockListConstruction is called from a test case in veryVeryVerbose mode, we observe console output similar to:

{
{ address: 0x012345600, size: 42 },
{ address: 0x012345610, size: 19 },
{ address: 0x012345620, size: 1024 }
}
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.

Macro Definition Documentation

◆ BSLS_BSLTESTUTIL_ASSERT

#define BSLS_BSLTESTUTIL_ASSERT (   X)     do { aSsErT(!(X), #X, __LINE__); } while (false)

◆ BSLS_BSLTESTUTIL_ASSERTV

#define BSLS_BSLTESTUTIL_ASSERTV (   ...)
Value:
BSLS_BSLTESTUTIL_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
#define BSLS_BSLTESTUTIL_NUM_ARGS(...)
Definition bsls_bsltestutil.h:576
#define BSLS_BSLTESTUTIL_LOOPN_ASSERT(N,...)
Definition bsls_bsltestutil.h:583

◆ BSLS_BSLTESTUTIL_EXPAND

#define BSLS_BSLTESTUTIL_EXPAND (   X)     X

◆ BSLS_BSLTESTUTIL_FORMAT_I64

#define BSLS_BSLTESTUTIL_FORMAT_I64   "%lld"

◆ BSLS_BSLTESTUTIL_FORMAT_PTR

#define BSLS_BSLTESTUTIL_FORMAT_PTR   "%X"

◆ BSLS_BSLTESTUTIL_FORMAT_TD

#define BSLS_BSLTESTUTIL_FORMAT_TD   "%td"

◆ BSLS_BSLTESTUTIL_FORMAT_U64

#define BSLS_BSLTESTUTIL_FORMAT_U64   "%llu"

◆ BSLS_BSLTESTUTIL_FORMAT_ZU

#define BSLS_BSLTESTUTIL_FORMAT_ZU   "%zu"

◆ BSLS_BSLTESTUTIL_L_

#define BSLS_BSLTESTUTIL_L_   __LINE__

◆ BSLS_BSLTESTUTIL_LOOP0_ASSERT

#define BSLS_BSLTESTUTIL_LOOP0_ASSERT    BSLS_BSLTESTUTIL_ASSERT

◆ BSLS_BSLTESTUTIL_LOOP1_ASSERT

#define BSLS_BSLTESTUTIL_LOOP1_ASSERT    BSLS_BSLTESTUTIL_LOOP_ASSERT

◆ BSLS_BSLTESTUTIL_LOOP2_ASSERT

#define BSLS_BSLTESTUTIL_LOOP2_ASSERT (   I,
  J,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP3_ASSERT

#define BSLS_BSLTESTUTIL_LOOP3_ASSERT (   I,
  J,
  K,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(K, #K ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP4_ASSERT

#define BSLS_BSLTESTUTIL_LOOP4_ASSERT (   I,
  J,
  K,
  L,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(L, #L ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP5_ASSERT

#define BSLS_BSLTESTUTIL_LOOP5_ASSERT (   I,
  J,
  K,
  L,
  M,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(M, #M ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP6_ASSERT

#define BSLS_BSLTESTUTIL_LOOP6_ASSERT (   I,
  J,
  K,
  L,
  M,
  N,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(M, #M ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(N, #N ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP7_ASSERT

#define BSLS_BSLTESTUTIL_LOOP7_ASSERT (   I,
  J,
  K,
  L,
  M,
  N,
  O,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(M, #M ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(N, #N ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(O, #O ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP8_ASSERT

#define BSLS_BSLTESTUTIL_LOOP8_ASSERT (   I,
  J,
  K,
  L,
  M,
  N,
  O,
  V,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(J, #J ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(K, #K ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(L, #L ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(M, #M ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(N, #N ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(O, #O ": ", "\t"); \
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(V, #V ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOP_ASSERT

#define BSLS_BSLTESTUTIL_LOOP_ASSERT (   I,
 
)
Value:
do { \
if (!(X)) { BloombergLP::bsls:: \
BslTestUtil::callDebugprint(I, #I ": ", "\n"); \
aSsErT(true, #X, __LINE__); } } while (false)

◆ BSLS_BSLTESTUTIL_LOOPN_ASSERT

#define BSLS_BSLTESTUTIL_LOOPN_ASSERT (   N,
  ... 
)     BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL(N, __VA_ARGS__)

◆ BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL

#define BSLS_BSLTESTUTIL_LOOPN_ASSERT_IMPL (   N,
  ... 
)     BSLS_BSLTESTUTIL_EXPAND(BSLS_BSLTESTUTIL_LOOP ## N ## _ASSERT(__VA_ARGS__))

◆ BSLS_BSLTESTUTIL_NUM_ARGS

#define BSLS_BSLTESTUTIL_NUM_ARGS (   ...)
Value:
__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0, ""))
#define BSLS_BSLTESTUTIL_NUM_ARGS_IMPL(X8, X7, X6, X5, X4, X3, X2, X1, X0, N,...)
Definition bsls_bsltestutil.h:572
#define BSLS_BSLTESTUTIL_EXPAND(X)
Definition bsls_bsltestutil.h:569

◆ BSLS_BSLTESTUTIL_NUM_ARGS_IMPL

#define BSLS_BSLTESTUTIL_NUM_ARGS_IMPL (   X8,
  X7,
  X6,
  X5,
  X4,
  X3,
  X2,
  X1,
  X0,
  N,
  ... 
)     N

◆ BSLS_BSLTESTUTIL_P

#define BSLS_BSLTESTUTIL_P (   X)
Value:
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(X, #X " = ", "\n");

◆ BSLS_BSLTESTUTIL_P_

#define BSLS_BSLTESTUTIL_P_ (   X)
Value:
BloombergLP::bsls:: \
BslTestUtil::callDebugprint(X, #X " = ", ", ");

◆ BSLS_BSLTESTUTIL_Q

#define BSLS_BSLTESTUTIL_Q (   X)
Value:
BloombergLP::bsls:: \
BslTestUtil::printStringNoFlush("<| " #X " |>\n");

◆ BSLS_BSLTESTUTIL_T_

#define BSLS_BSLTESTUTIL_T_   BloombergLP::bsls::BslTestUtil::printTab();