the Compartmented Robust Posix C++ Unit Test system |
|
---|
General Predicates are used with
ASSERT_PRED(pred, ...)
or
VERIFY_PRED(pred, ...)
. Logically
ASSERT_PRED
(predicate
,
param1
, param2
,
...paramN
) is identical with
ASSERT_TRUE
(predicate
(param1
, param2
,
...paramN
)), and likewise for
VERIFY_PRED
(). The difference lies in error
reporting.
ASSERT_PRED(pred, ...)
and
VERIFY_PRED(pred, ...)
will list the value of each of the parameters in a violation
report, whereas
ASSERT_TRUE(expr)
and
VERIFY_TRUE(expr)
will give a
cruder report with fewer details.
The below example uses both versions:
#include <crpcut.hpp> bool has_substring_in(const std::string &needle, const std::string &haystack) { return haystack.find(needle) != std::string::npos; } TEST(using_assert_pred) { const char needle[] = "pqr"; const char haystack[] = "a mountain of hay"; ASSERT_PRED(has_substring_in, needle, haystack); } TEST(using_assert_true) { const char needle[] = "pqr"; const char haystack[] = "a mountain of hay"; ASSERT_TRUE(has_substring_in(needle, haystack)); } int main(int argc, char *argv[]) { return crpcut::run(argc, argv); }
The result shows the difference clearly
FAILED!: using_assert_pred phase="running" -------------------------------------------------------------- samples/simple-pred.cpp:39 ASSERT_PRED(has_substring_in, needle, haystack) param1 = pqr param2 = a mountain of hay ------------------------------------------------------------------------------- =============================================================================== FAILED!: using_assert_true phase="running" -------------------------------------------------------------- samples/simple-pred.cpp:46 ASSERT_TRUE(has_substring_in(needle, haystack)) is evaluated as: 0 ------------------------------------------------------------------------------- =============================================================================== 2 test cases selected Sum Critical Non-critical FAILED : 2 2 0
If a predicate has an output-stream operator defined, it will be called when making violation reports.
Sometimes you may want the type of the predicate object to be
determined by the types of one or several expressions.
crpcut solves that with the function template
crpcut::match
<pred_type>(),
together with the traits class template crpcut::match_traits.
By default, the type returned from
crpcut::match
<pred_type>()
is pred_type, and the object constructor is called
with the parameters to
crpcut::match
<pred_type>().
However, you can specialize the traits class template
crpcut::match_traits for your predicate class, to provide
a better suitable type, for example a specialization on the
parameters.
Note | |
---|---|
If you use GCC version 4.3 or
higher, and compile your test sources with -std=c++0x,
there is no limit to the number of parameters to the
match <pred_type>()
function nor the crpcut::match_traits specialization,
otherwise there is a maximum limit of 9 parameters.
|
The above example now generalized, is unsurprisingly longer, and slightly different:
#include <crpcut.hpp> class is_substring { public: template <typename T> class implementation { public: implementation(const T t) : needle(t) {} template <typename U> bool operator()(const U* haystack) const { return operator()(std::basic_string<U>(haystack)); } template <typename U> bool operator()(const std::basic_string<U> &haystack) const { return haystack.find(needle) != std::basic_string<U>::npos; } friend std::ostream &operator<<(std::ostream &os, const implementation& i) { return os << "failed when searcing for " << i.needle; } private: T needle; }; }; namespace crpcut { template <typename T> struct match_traits<is_substring, const T*> { typedef is_substring::template implementation<const T*> type; }; template <typename T> struct match_traits<is_substring, T*> { typedef is_substring::template implementation<const T*> type; }; template <typename T> struct match_traits<is_substring, std::basic_string<T> > { typedef is_substring::template implementation<std::basic_string<T> > type; }; } TEST(using_char_array) { char needle[] = "steel"; const char hay[] = "hay"; char haystack[] = "a mountain of hay"; ASSERT_PRED(crpcut::match<is_substring>(hay), haystack); ASSERT_PRED(crpcut::match<is_substring>(needle), haystack); } TEST(using_const_char_ptr) { const char *needle = "steel"; const char *hay = "hay"; const char *haystack = "a mountain of hay"; ASSERT_PRED(crpcut::match<is_substring>(hay), haystack); ASSERT_PRED(crpcut::match<is_substring>(needle), haystack); } TEST(using_string) { std::string needle("steel"); const std::string hay("hay"); std::string haystack("a mountain of hay"); ASSERT_PRED(crpcut::match<is_substring>(hay), haystack); ASSERT_PRED(crpcut::match<is_substring>(needle), haystack); } int main(int argc, char *argv[]) { return crpcut::run(argc, argv); }
The result from running the test program is:
FAILED!: using_char_array phase="running" -------------------------------------------------------------- samples/template-pred.cpp:84 ASSERT_PRED(crpcut::match<is_substring>(needle), haystack) param1 = a mountain of hay for crpcut::match<is_substring>(needle): failed when searcing for steel ------------------------------------------------------------------------------- =============================================================================== FAILED!: using_const_char_ptr phase="running" -------------------------------------------------------------- samples/template-pred.cpp:93 ASSERT_PRED(crpcut::match<is_substring>(needle), haystack) param1 = a mountain of hay for crpcut::match<is_substring>(needle): failed when searcing for steel ------------------------------------------------------------------------------- =============================================================================== FAILED!: using_string phase="running" -------------------------------------------------------------- samples/template-pred.cpp:102 ASSERT_PRED(crpcut::match<is_substring>(needle), haystack) param1 = a mountain of hay for crpcut::match<is_substring>(needle): failed when searcing for steel ------------------------------------------------------------------------------- =============================================================================== 3 test cases selected Sum Critical Non-critical FAILED : 3 3 0
What may be less obvious is that the above three tests instantiated is_substring::implementation<const char*> for the first two versions, and is_substring::implementation<std::string> for the last.