www.wildbearsoftware.com

Example: Custom Checks

Introduction

The basic fct_chk may not always provide you with useful feedback on a failure. Starting with FCTX v1.1 fct_xchk was added to allow you to customize how an error is reported when a failure occurs.

The fct_xchk function takes N parameters, the first one is the conditional statement, the second one is a format string and the remaining arguments are used to satisfy the format string.

Sample Problem

The fct_xchk function can be used with either C or C++, but to keep things a little interesting lets review with C++. If you look at the fct_xchk function documentation, you will see an example orientated towards C. In our example we will create a contrived money_t class.

  •    1 class money_t {
       2 public:
       3    money_t() amount_(0), currency_("") {};
       4    money_t(int amount, const std::string& currency) 
       5      : amount_(amount), currency_(currency) {};
       6    virtual ~money_t() {};
       7 
       8    /* ...
       9    Skip implementation details, focus on what matters here
      10    ... */
      11 
      12    /* Function returns a string representation of this object. */
      13    std::string to_string() const {
      14        std::stringstream buf;
      15        buf << this->amount_ 
      16            << "," 
      17            << this->currency_;
      18        return buf.str();
      19    };
      20 
      21 private:
      22    int amount_;
      23    std::string currency_;
      24 };
    

We will keep it simple and use strings to represent the currency ("CDN", "USD", "EUR", &etc.). The important part of this class is the to_string method, and we can ignore all the other details like equality checks, deductions, copies, and so on.

Now we will write a simple unit test to confirm that we can copy the money_t object, and the results are equal after the copy.

  •    1 #include "fct.h"
       2 
       3 FCT_BGN() {
       4    FCT_QTEST_BGN(test_money__no_helpful_info) {
       5       money_t m1(10, "USD");
       6       money_t m2(m1);
       7       fct_chk(m1 == m2);
       8    } FCT_QTEST_END();
       9 
      10 } FCT_END();
    

Now, if in our example above m1 was not equal to m2, all we would see in our failure report would be an indication that m1 == m2 failed, and we would have no hint about what m1's and m2's values. So we would have to open the debugger, and actually step through the code to discover why m1 is not equal to m2.

In order to get more information during a failure event we can write an extended check. We will call this chk_money_eq, and it will look like this,

  •    1 /* Note, a real macro would have "\" 
       2 escapes, but at the moment the parser 
       3 for the color coder misinterprets 
       4 them. */
       5 #define chk_money_eq(m1, m2)
       6     fct_xchk(
       7        m1 == m2,
       8       "money not equal: m1 is '%s', m2 is '%s'",
       9        m1.to_string().c_str(),
      10        m2.to_string().c_str()
      11     )
    

Now when we make a check call to chk_money_eq, and it fails it will generate some information about what the money object's look like at the time of failure.

...for Your Project

You may have lots of check's that you want to use throughout your project. The recommended way to add your custom checks is to "extend" the fct.h header with a header of your own. As in the following,

  •    1 /* file: myfct.h */
       2 
       3 /* Get the FCTX implementation. */
       4 #include "fct.h"
       5 
       6 /* Add our implementation. 
       7 Note, a real macro would have "\" 
       8 escapes, but at the moment the parser 
       9 for the color coder misinterprets 
      10 them. */
      11 #define chk_money_eq(m1, m2)
      12     fct_xchk(
      13        m1 == m2,
      14       "money not equal: m1 is '%s', m2 is '%s'",
      15        m1.to_string().c_str(),
      16        m2.to_string().c_str()
      17     )
    

Now you can rewrite your money original unit test as follows,

  •    1 #include "myfct.h"
       2 
       3 FCT_BGN() {
       4    FCT_QTEST_BGN(test_money__can_copy) {
       5       money_t m1(10, "USD");
       6       money_t m2(m1);
       7       chk_money_eq(m1,m2);
       8    } FCT_QTEST_END();
       9 
      10 } FCT_END();
    

and you can us the chk_money_eq throughout your project.

More Samples

To see the complete example go to the examples/custom_check section of the repository or view the custom_check.cpp file.

Most of the checking functions present in FCTX are implemented using the fct_xchk as its basis, and can be also referenced for further examples.