]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Add rudimentary test mocking support.
authorNick Mathewson <nickm@torproject.org>
Wed, 10 Jul 2013 19:03:01 +0000 (15:03 -0400)
committerNick Mathewson <nickm@torproject.org>
Wed, 10 Jul 2013 19:22:16 +0000 (15:22 -0400)
This is not the most beautiful possible implementation (it requires
decorating mockable functions with ugly macros), but it actually
works, and is portable across multiple compilers and architectures.

changes/fancy_testing
src/common/testsupport.h

index ad197c6f584314a35ffa2d75c020e8913594c41f..89876ff270ca9ec832c937a8fa9dde148eb697b6 100644 (file)
       tests (and a new src/or/tor-cov target) to build with gcov test
       coverage support.
 
+  o Testing:
+
+    - We now have rudimentary function mocking support that our unit
+      tests can use to test functions in isolation. Function mocking
+      lets the tests temporarily replace a function's dependencies with
+      stub functions, so that the tests can check the function without
+      invoking the other functions it calls.
+
+
+
+
+
index c6777d0cb22ff7223942de6b5479a785fa687e6b..4a4f50b69b39ec609020fa19cbc4d1dadbdcfd00 100644 (file)
 #define STATIC static
 #endif
 
+/** Quick and dirty macros to implement test mocking.
+ *
+ * To use them, suppose that you have a function you'd like to mock
+ * with the signature "void writebuf(size_t n, char *buf)".  You can then
+ * declare the function as:
+ *
+ *     MOCK_DECL(void, writebuf, (size_t n, char *buf));
+ *
+ * and implement it as:
+ *
+ *     MOCK_IMPL(void
+ *     writebuf,(size_t n, char *buf)
+ *     {
+ *          ...
+ *     }
+ *
+ * For the non-testing build, this will expand simply into:
+ *
+ *     void writebuf(size_t n, char *buf);
+ *     void
+ *     writebuf(size_t n, char *buf)
+ *     {
+ *         ...
+ *     }
+ *
+ * But for the testing case, it will expand into:
+ *
+ *     void writebuf__real(size_t n, char *buf);
+ *     extern void (*writebuf)(size_t n, char *buf);
+ *
+ *     void (*writebuf)(size_t n, char *buf) = writebuf__real;
+ *     void
+ *     writebuf__real(size_t n, char *buf)
+ *     {
+ *         ...
+ *     }
+ *
+ * This is not a great mocking system!  It is deliberately "the simplest
+ * thing that could work", and pays for its simplicity in its lack of
+ * features, and in its uglification of the Tor code.  Replacing it with
+ * something clever would be a fine thing.
+ *
+ * @{ */
+#ifdef TOR_UNIT_TESTS
+#define MOCK_DECL(rv, funcname, arglist)     \
+  rv funcname ##__real arglist;              \
+  extern rv(*funcname) arglist
+#define MOCK_IMPL(rv, funcname, arglist)     \
+  rv(*funcname) arglist = funcname ##__real; \
+  rv funcname ##__real arglist
+#define MOCK(func, replacement)                 \
+  do {                                          \
+    (func) = (replacement);                     \
+  } while (0)
+#define UNMOCK(func)                            \
+  do {                                          \
+    func = func ##__real;                       \
+  } while (0)
+#else
+#define MOCK_DECL(rv, funcname, arglist) \
+  rv funcname arglist
+#define MOCK_IMPL(rv, funcname, arglist) \
+  rv funcname arglist
+#endif
+/** @} */
+
 #endif