Provide utilities to help with testing templates.
More...
Namespaces |
namespace | bsltf |
Detailed Description
- Outline
-
-
- Purpose:
- Provide utilities to help with testing templates.
-
- Classes:
-
-
- Macros:
BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE(CLASS, METHOD, TYPE...) | run all |
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_PRIMITIVE | list of primitive types |
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_USER_DEFINED | list user types |
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_REGULAR | list of typical types |
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_AWKWARD | list of atypical types |
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_ALL | list all bslmf types |
- See also:
- Component bsltf_simpletesttype, Component bslstl_map
-
- Description:
- When testing a container template having a type parameter, we need to ensure that the template supports its contractually specified categories of parameter types. The
bsltf
package provides a representative set of types intended for testing that can be used as template parameters for doing this kind of verification.
- Creating a separate test for each category of types supported by a template would be cumbersome. Instead, writing a single templatized test is usually preferable. Unfortunately, different types often require different syntaxes for constructing an object and getting an object's value. This inconsistency makes writing generic code rather difficult.
- This component provides a solution with a utility
struct
, TemplateTestFacility
, that defines two class method templates, create
and getIdentifier
, that respectively have consistent syntaxes for creating objects and getting a integer value representing the state of objects of a parameterized type.
- This component also provides a macro,
BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
, that serves as a convenient way to instantiate and invoke a template (for testing) having a type parameter for a specified list of types. In addition, this component provides a set of macros referring to commonly useful lists of types intended for testing that can be used as arguments to BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
.
- The utilities and macros provided by this component, along with the types defined in the
bsltf
package, are explained in more detail in the following sections.
-
- TemplateTestFacility:
- The
TemplateTestFacility
struct
provides the following static (class) method templates to construct objects and get the states of objects of a supported parameterized type (supported types are those types intended for testing defined in the bsltf
package):
-
create
: Return an object of the parameterized TYPE
whose value is uniquely associated with a specified integer identifier.
-
getIdentifier
: Return the integer identifier used to create a specified object of the parameterized TYPE
.
-
- Macros and Test Types:
- The
BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
macro instantiates a specified class template for a specified list of types and call a specified class method of each instantiation. The macro takes in arguments in the following order:
-
The name of the class template to be instantiated
-
The name of the class method to be invoked
-
The names of the types for which the class template will be instantiated (up to 20)
- This component also defines a set of macros, each providing a list of types, that can be used as the last argument to
BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
. The following is a brief synopsis of these macros (note that all macros names have the BSLTF_TEMPLATETESTFACILITY_
prefix, which is omitted for layout efficiency):
-
TEST_TYPES_PRIMITIVE
: list of primitive types
-
TEST_TYPES_USER_DEFINED
: list of user-defined types
-
TEST_TYPES_REGULAR
: list of typically used types
-
TEST_TYPES_AWKWARD
: list of types with odd behaviors
-
TEST_TYPES_ALL
: list of all of the types
- The
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_PRIMITIVE
macro refers to a representative set of primitive types that are useful for testing: Type Description
---- -----------
signed char signed character
size_t signed integral type
TemplateTestFacility::ObjectPtr pointer to an object
TemplateTestFacility::FunctionPtr pointer to a function
TemplateTestFacility::MethodPtr pointer to a method
The BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_USER_DEFINED
macro refers to a representative set of user-defined types that are useful for testing (note that all types described here belong to the bsltf
namespace, which is not explicitly qualified for layout efficiency): Type Description
---- -----------
EnumeratedTestType::Enum an enumeration
UnionTestType a union
SimpleTestType class with no special traits defined
AllocTestType class that allocates memory, defines
the 'bslma::UsesBslmaAllocator'
trait, and ensures it is not bitwise
moved
NonOptionalAllocTestType class that allocates memory, defines
the 'bslma::UsesBslmaAllocator'
trait, ensures it is not bitwise
moved, and does not have default ctor.
MovableTestType class that has both move and copy
semantics, and ensures it is not
bitwise moved
MovableAllocTestType class that has both move and copy
semantics, allocates memory, defines
the 'bslma::UsesBslmaAllocator'
trait, and ensures it is not bitwise
moved
MoveOnlyAllocTestType class that has only move semantics,
allocates memory, defines the
'bslma::UsesBslmaAllocator'
trait, and ensures it is not bitwise
moved
BitwiseCopyableTestType class that is bitwise-copyable and
defines the
'bsl::is_trivially_copyable'
trait
BitwiseMoveableTestType class that is bitwise-moveable and
defines the
'bslmf::IsBitwiseMoveable'
trait
AllocatingBitwiseMoveableTestType class that allocates memory, is
bitwisemoveable, and defines the
'bslma::UsesBslmaAllocator'
and 'bslmf::IsBitwiseMoveable'
traits
NonTypicalOverloadsTestType class that defines and assert on
invocation of certain
non-typically-overloaded operators
('operator new', 'operator delete',
'operator&') to ensure that they are
not called
EmplacableTestType class that takes <= 14 non-allocating
arguments and is used to ensure that
arguments are forwarded correctly
from functions and methods taking
variable number of arguments and their
analagous in C++03 environments.
AllocEmplacableTestType class that takes up to 14 allocating
arguments and is used to ensure that
arguments are forwarded correctly
from functions and methods taking
variable number of arguments and their
analagous in C++03 environments.
- The
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_REGULAR
macro refers to the union of the types provided by BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_PRIMITIVE
and BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_USER_DEFINED
. These types are designed to work within the regular operating conditions of a typical template. Typically, a test driver for a template instantiates its tests (using the BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
macro) for all of the types referred by BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_REGULAR
.
- The
BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_AWKWARD
macro refers to a set of types that have certain attributes that make them unlikely to work for all of the operations of a template. Typically, not all methods of a template are instantiable with these types, so these types are most often used independently in tests explicitly designed for a (single) type. Type Description
---- -----------
NonAssignableTestType class having no assignment operator
NonCopyConstructibleTestType class having no copy constructor (Note
that this class can not be created with
'TemplateTestFacility::create' because
the class method returns the newly
constructed object by value.)
NonDefaultConstructibleTestType class having no default constructor
NonEqualComparableTestType class having no equality-comparison
operators
The BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_ALL
refers to all the test types provided in the bsltf
package.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Using the BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE Macro:
- In this example, we demonstrate how to use
BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
to call a class method of a template for a list of types.
- First, we define a
struct
template TestTemplate
taking in a parameterized TYPE
that has a class method, printTypeName
: template <class TYPE>
struct TestTemplate {
static void printTypeName();
};
template <>
void TestTemplate<int>::printTypeName()
{
printf("int\n");
}
template <>
void TestTemplate<char>::printTypeName()
{
printf("char\n");
}
template <>
void TestTemplate<double>::printTypeName()
{
printf("double\n");
}
Now, we can instantiate the TestTemplate
class for each of the types int
, char
, and double
, and call the printTypeName
class method of each instantiation using the BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
macro: Finally, we observe the console output:
-
- Example 2: Writing a Type Independent Test Driver:
- In this example, we demonstrate using the
TemplateTestFacility
struct
and the macros provided by this component to test the default constructor and primary manipulator of a class template in the context of a typical BDE-style test driver. Note that a goal of the demonstrated test is to validate the class template with a broad range of types emulating those with which the template might be instantiated.
- First, we define a simple class template,
MyNullableValue
, that we will later need to test: template <class TYPE>
class MyNullableValue {
TYPE d_value;
bool d_nullFlag;
public:
MyNullableValue()
: d_nullFlag(true)
{
}
bool isNull() const
{
return d_nullFlag;
}
void makeNull()
{
d_nullFlag = true;
}
const TYPE& value() const {
return d_value;
}
void makeValue(const TYPE& value)
{
d_nullFlag = false;
d_value = value;
}
};
Then, we define some aliases for the micros that will be used by the test driver: #define RUN_EACH_TYPE BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
#define TEST_TYPES_REGULAR BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_REGULAR
Next, we define a struct
template, MyTestDriver
, that provides a namespace containing the test cases (here, only testCase2
is defined for brevity) of the test driver: template <class TYPE>
struct MyTestDriver {
typedef MyNullableValue<TYPE> Obj;
static void testCase2();
};
Now, we define the implementation of MyTestDriver::testCase2
: template <class TYPE>
void MyTestDriver<TYPE>::testCase2()
{
if (verbose)
printf("\nDEFAULT CTOR, PRIMARY MANIPULATORS, AND DTOR"
"\n============================================\n");
if (verbose) printf("\nTesting default constructor.\n");
Obj mW; const Obj& W = mW;
assert(true == W.isNull());
Obj mX; const Obj& X = mX;
const TYPE XV = TemplateTestFacility::create<TYPE>(1);
mX.makeValue(XV);
assert(1 == TemplateTestFacility::getIdentifier<TYPE>(X.value()));
if (verbose) printf("\nTesting primary manipulators.\n");
for (size_t ti = 0; ti < 10; ++ti) {
if (veryVerbose) { T_ P(ti) }
Obj mL; const Obj& L = mL;
assert(true == L.isNull());
const TYPE LV = TemplateTestFacility::create<TYPE>(ti);
mL.makeValue(LV);
assert(false == L.isNull());
assert(LV == L.value());
mL.makeNull();
assert(true == L.isNull());
}
if (verbose) printf("\nTesting destructor.\n");
{
Obj Z;
}
assert(true == W.isNull());
assert(XV == X.value());
}
Notice that, we create objects of the parameterized TYPE
using the TemplateTestFacility::create
class method template specifying an integer identifier; the created object has a value that is uniquely associated with the integer identifier.
- Also notice that we verified that an object of the parameterized
TYPE
has the expected value in two ways:
-
By equal comparing (1) the integer identifier returned from calling the
TemplateTestFacility::getIdentifier
class method template (specifying the object), and (2) the integer identifier uniquely associated with the expected state of the object.
-
By directly using the equality-comparison operator for the parameterized
TYPE
. Note that the equality-comparison operator is defined for all types intended for testing in the bsltf
package except for bsltf::NonEqualComparableTestType
.
- Finally, we use the
BSLTF_TEMPLATETESTFACILITY_RUN_EACH_TYPE
macro to instantiate MyTestDriver
for each of the types listed in BSLTF_TEMPLATETESTFACILITY_TEST_TYPES_REGULAR
and invoke the testCase2
class method of each instantiation: case 2: {
if (verbose) printf("\nDEFAULT CTOR & PRIMARY MANIPULATORS"
"\n===================================\n");
RUN_EACH_TYPE(MyTestDriver, testCase2, TEST_TYPES_REGULAR);
} break;