Provide classes and macros for testing abstract protocols.
More...
Detailed Description
- Outline
-
-
- Purpose:
- Provide classes and macros for testing abstract protocols.
-
- Classes:
-
-
- Macros:
BSLS_PROTOCOLTEST_ASSERT | macro for testing protocol methods |
-
- Description:
- This component provides classes and macros that simplify the creation of test drivers for protocol (i.e., pure abstract interface) classes.
- The purpose of a test driver for a protocol class is to verify concerns for that protocol's definition. Although each protocol is different and requires its own test driver, there is a common set of concerns that apply to all protocol classes. This component allows us to verify those concerns in a generic manner.
- Each protocol class has to satisfy the following set of requirements (concerns):
-
The protocol is abstract: no objects of it can be created.
-
The protocol has no data members.
-
The protocol has a virtual destructor.
-
All methods of the protocol are pure virtual.
-
All methods of the protocol are publicly accessible.
- This protocol test component is intended to verify conformance to these requirements; however, it is not possible to verify all protocol requirements fully within the framework of the C++ language. The following aspects of the above requirements are not verified by this component:
-
Non-creator methods of the protocol are pure virtual.
-
There are no methods in the protocol other than the ones being tested.
- Additionally some coding guidelines related to protocols are also not verified:
-
The destructor is not pure virtual.
-
The destructor is not implemented inline.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Testing a Protocol Class:
- This example demonstrates how to test a protocol class,
ProtocolClass
, using this protocol test component. Our ProtocolClass
provides two of pure virtual methods (foo
and bar
), along with a virtual destructor: struct ProtocolClass {
virtual ~ProtocolClass();
virtual const char *bar(char const *, char const *) = 0;
virtual int foo(int) const = 0;
};
ProtocolClass::~ProtocolClass()
{
}
First, we define a test class derived from this protocol, and implement its virtual methods. Rather than deriving the test class from ProtocolClass
directly, the test class is derived from bsls::ProtocolTestImp<ProtocolClass>
(which, in turn, is derived automatically from ProtocolClass
). This special base class implements boilerplate code and provides useful functionality for testing of protocols.
struct ProtocolClassTestImp : bsls::ProtocolTestImp<ProtocolClass> {
const char *bar(char const *, char const *) { return markDone(); }
int foo(int) const { return markDone(); }
};
Notice that in ProtocolClassTestImp
we must provide an implementation for every protocol method except for the destructor. The implementation of each method calls the (protected) markDone
which is provided by the base class for the purpose of verifying that the method from which it's called is declared as virtual in the protocol class.
- Then, in our protocol test case we describe the concerns we have for the protocol class and the plan to test those concerns: Next we print the banner for this test case:
if (verbose) printf("\nPROTOCOL TEST"
"\n=============\n");
Then, we create an object of type bsls::ProtocolTest<ProtocolClassTestImp>
, testObj
: Now we use the testObj
to test some general concerns about the protocol class. if (verbose) printf("\nVerify that the protocol is abstract.\n");
ASSERT(testObj.testAbstract());
if (verbose) printf("\nVerify that there are no data members.\n");
ASSERT(testObj.testNoDataMembers());
if (verbose) printf("\nVerify that the destructor is virtual.\n");
ASSERT(testObj.testVirtualDestructor());
Finally we use the testObj
to test concerns for each individual method of the protocol class. To test a protocol method we need to call it from inside the BSLS_PROTOCOLTEST_ASSERT
macro, and also pass the testObj
: These steps conclude the protocol testing. If there are any failures, they will be reported via standard test driver assertions (i.e., the standard ASSERT
macro).
-
- Implementation Note:
- This component has a number of private meta-functions on some platforms, e.g.,
ProtocolTest_EnableIf
, ProtocolTest_IsClass
, and ProtocolTest_IsAbstract
. These mimic, to a limited extent, standard library meta-functions in the namespace std
that are not available on all platforms. For general use, see the bslmf
package and the bsl
namespace for portable implementations of some of these meta-functions.
Define Documentation
#define BSLS_PROTOCOLTEST_ASSERT |
( |
|
test, |
|
|
|
methodCall | |
|
) |
| | |
Value:do { \
test.method( \
"inside BSLS_PROTOCOLTEST_ASSERT("#methodCall")")->methodCall;\
if (!test.lastStatus()) { \
ASSERT(0 && "Not a virtual method: "#methodCall); \
} \
} while (0)