aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 ad197c6f5..89876ff27 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 c6777d0cb..4a4f50b69 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