summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-07-10 15:03:01 -0400
committerNick Mathewson <nickm@torproject.org>2013-07-10 15:22:16 -0400
commitb6e8c74667cf723c5ef4d081fc901752e05f9a9b (patch)
treec8d51b23edbe5de7fa57ad5b9923dd968a68f5a8
parent4753ad4f1dbd7fa3233ead5770e9c8bd619b8d07 (diff)
downloadtor-b6e8c74667cf723c5ef4d081fc901752e05f9a9b.tar.gz
tor-b6e8c74667cf723c5ef4d081fc901752e05f9a9b.zip
Add rudimentary test mocking support.
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.
-rw-r--r--changes/fancy_testing12
-rw-r--r--src/common/testsupport.h66
2 files changed, 78 insertions, 0 deletions
diff --git a/changes/fancy_testing b/changes/fancy_testing
index ad197c6f58..89876ff270 100644
--- a/changes/fancy_testing
+++ b/changes/fancy_testing
@@ -14,3 +14,15 @@
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.
+
+
+
+
+
diff --git a/src/common/testsupport.h b/src/common/testsupport.h
index c6777d0cb2..4a4f50b69b 100644
--- a/src/common/testsupport.h
+++ b/src/common/testsupport.h
@@ -10,5 +10,71 @@
#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