the Compartmented Robust Posix C++ Unit Test system

CRPCUT_WRAP_FUNC(lib, func, rv, param_list, param_call)

Define a wrapper around a global function

Used in: User defined namespace scope

Define access to a library function you want to write a wrapper for, for example for checking parameters or inject hard-to-test error situations.

[Note]Note
CRPCUT_WRAP_FUNC uses dlopen() and dlsym() to get access to the library function. This means you can only access functions in a shared library, and also that functions used by dlopen() and dlsym() are very tricky to get access to. crpcut already provides wrappers for the heap (See crpcut::heap.)

[Caution]Caution
Do not expand CRPCUT_WRAP_FUNC in global scope, or you will be unable to make a wrapper, since the expansion will create a new function with the same name.

Macro parameters

lib

The library with the function. crpcut predefines libc and librt.

To write a wrapper for a function defined in another library, a name access function in namespace crpcut::libs must be provided.

func

The name of the function, without quotes.

rv

The return type of the function.

param_list

The types and names for all parameters to the function, enclosed in parenthesis.

param_call

The names from param_list without type information, comma separated and enclosed in parenthesis.

Example: The test program

     
     #include <crpcut.hpp>
     
     extern "C"
     {
     #include <stdio.h>
     #include <string.h>
     }
     
     namespace original {
       CRPCUT_WRAP_FUNC(libc,
                        fopen,
                        FILE*,
                        (const char *pathname, const char *mode),
                        (pathname, mode))
     }
     
     const char *expected_filename = 0;
     extern "C"
     {
       FILE *fopen(const char *name, const char *mode)
       {
         if (expected_filename && ::strcmp(name, expected_filename) != 0)
           {
             FAIL << "fopen() called with " << name <<
               " when " << expected_filename << " was expected";
           }
         return original::fopen(name, mode);
       }
     }
     
     size_t read_data(const char *name)
     {
       FILE *handle = ::fopen(name, "r");
       if (!handle) return ~size_t();
       char buff[10];
       size_t n = ::fread(buff, 1, sizeof(buff), handle);
       fclose(handle);
       return n;
     }
     
     TEST(wrapped_with_no_expectations)
     {
       (void)read_data("/dev/zero");
     }
     
     TEST(wrapped_with_wrong_expectations)
     {
       expected_filename = "/dev/random";
       (void)read_data("/dev/zero");
     }
     
     int main(int argc, char *argv[])
     {
       return crpcut::run(argc, argv);
     }

        

reports one failed test:


     FAILED!: wrapped_with_wrong_expectations
     phase="running"  --------------------------------------------------------------
     samples/wrap_func.cpp:51
     fopen() called with /dev/zero when /dev/random was expected
     -------------------------------------------------------------------------------
     ===============================================================================
     2 test cases selected
     
                    Sum   Critical   Non-critical
     PASSED   :       1          1              0
     FAILED   :       1          1              0

        

See crpcut::libs for details.

See also CRPCUT_WRAP_V_FUNC(lib, func, rv, param_list, param_call) for functions with void return, and FAIL