testsupport.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* Copyright (c) 2013-2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file testsupport.h
  5. *
  6. * \brief Macros to implement mocking and selective exposure for the test code.
  7. *
  8. * Each Tor source file is built twice: once with TOR_UNIT_TESTS defined, and
  9. * once with it undefined. The only difference between these configurations
  10. * should be that when building for the tests, more functions are exposed as
  11. * non-static, and a number of functions are declared as mockable.
  12. **/
  13. #ifndef TOR_TESTSUPPORT_H
  14. #define TOR_TESTSUPPORT_H
  15. #ifdef TOR_UNIT_TESTS
  16. /** The "STATIC" macro marks a function or variable that is static when
  17. * building Tor for production, but non-static when building the unit
  18. * tests. */
  19. #define STATIC
  20. #define EXTERN(type, name) extern type name;
  21. #else
  22. #define STATIC static
  23. #define EXTERN(type, name)
  24. #endif /* defined(TOR_UNIT_TESTS) */
  25. /** Quick and dirty macros to implement test mocking.
  26. *
  27. * To use them, suppose that you have a function you'd like to mock
  28. * with the signature "void writebuf(size_t n, char *buf)". You can then
  29. * declare the function as:
  30. *
  31. * MOCK_DECL(void, writebuf, (size_t n, char *buf));
  32. *
  33. * and implement it as:
  34. *
  35. * MOCK_IMPL(void,
  36. * writebuf,(size_t n, char *buf))
  37. * {
  38. * ...
  39. * }
  40. *
  41. * For the non-testing build, this will expand simply into:
  42. *
  43. * void writebuf(size_t n, char *buf);
  44. * void
  45. * writebuf(size_t n, char *buf)
  46. * {
  47. * ...
  48. * }
  49. *
  50. * But for the testing case, it will expand into:
  51. *
  52. * void writebuf__real(size_t n, char *buf);
  53. * extern void (*writebuf)(size_t n, char *buf);
  54. *
  55. * void (*writebuf)(size_t n, char *buf) = writebuf__real;
  56. * void
  57. * writebuf__real(size_t n, char *buf)
  58. * {
  59. * ...
  60. * }
  61. *
  62. * This is not a great mocking system! It is deliberately "the simplest
  63. * thing that could work", and pays for its simplicity in its lack of
  64. * features, and in its uglification of the Tor code. Replacing it with
  65. * something clever would be a fine thing.
  66. *
  67. * @{ */
  68. #ifdef TOR_UNIT_TESTS
  69. #define MOCK_DECL(rv, funcname, arglist) \
  70. rv funcname ##__real arglist; \
  71. extern rv(*funcname) arglist
  72. #define MOCK_IMPL(rv, funcname, arglist) \
  73. rv(*funcname) arglist = funcname ##__real; \
  74. rv funcname ##__real arglist
  75. #define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
  76. rv funcname ##__real arglist attr; \
  77. extern rv(*funcname) arglist
  78. #define MOCK_IMPL(rv, funcname, arglist) \
  79. rv(*funcname) arglist = funcname ##__real; \
  80. rv funcname ##__real arglist
  81. #define MOCK(func, replacement) \
  82. do { \
  83. (func) = (replacement); \
  84. } while (0)
  85. #define UNMOCK(func) \
  86. do { \
  87. func = func ##__real; \
  88. } while (0)
  89. #else /* !(defined(TOR_UNIT_TESTS)) */
  90. #define MOCK_DECL(rv, funcname, arglist) \
  91. rv funcname arglist
  92. #define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
  93. rv funcname arglist attr
  94. #define MOCK_IMPL(rv, funcname, arglist) \
  95. rv funcname arglist
  96. #endif /* defined(TOR_UNIT_TESTS) */
  97. /** @} */
  98. #endif /* !defined(TOR_TESTSUPPORT_H) */