hook.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #pragma once
  2. namespace NTesting {
  3. /**
  4. * Hook class and registration system.
  5. *
  6. * Default implementation of the `main` function for G_BENCHMARK and GTEST calls these hooks when executing.
  7. * This is a useful feature if you want to customize behaviour of the `main` function,
  8. * but you don't want to write `main` yourself.
  9. *
  10. * Hooks form an intrusive linked list that's built at application startup. Note that hooks execute
  11. * in arbitrary order.
  12. *
  13. * Use macros below to define hooks.
  14. */
  15. struct THook {
  16. using TFn = void (*)();
  17. TFn Fn = nullptr;
  18. THook* Next = nullptr;
  19. static void RegisterBeforeInit(THook* hook) noexcept;
  20. static void CallBeforeInit();
  21. struct TRegisterBeforeInit {
  22. explicit TRegisterBeforeInit(THook* hook) noexcept {
  23. THook::RegisterBeforeInit(hook);
  24. }
  25. };
  26. static void RegisterBeforeRun(THook* hook) noexcept;
  27. static void CallBeforeRun();
  28. struct TRegisterBeforeRun {
  29. explicit TRegisterBeforeRun(THook* hook) noexcept {
  30. THook::RegisterBeforeRun(hook);
  31. }
  32. };
  33. static void RegisterAfterRun(THook* hook) noexcept;
  34. static void CallAfterRun();
  35. struct TRegisterAfterRun {
  36. explicit TRegisterAfterRun(THook* hook) noexcept {
  37. THook::RegisterAfterRun(hook);
  38. }
  39. };
  40. };
  41. /**
  42. * Called right before initializing test programm
  43. *
  44. * This hook is intended for setting up default parameters. If you're doing initialization, consider
  45. * using `Y_TEST_HOOK_BEFORE_RUN` instead.
  46. *
  47. * *Note:* hooks execute in arbitrary order.
  48. *
  49. *
  50. * # Usage
  51. *
  52. * Instantiate this class in a cpp file. Pass a unique name for your hook,
  53. * implement body right after macro instantiation:
  54. *
  55. * ```
  56. * Y_TEST_HOOK_BEFORE_INIT(SetupParams) {
  57. * // hook code
  58. * }
  59. * ```
  60. */
  61. #define Y_TEST_HOOK_BEFORE_INIT(N) \
  62. void N(); \
  63. ::NTesting::THook N##Hook{&N, nullptr}; \
  64. ::NTesting::THook::TRegisterBeforeInit N##HookReg{&N##Hook}; \
  65. void N()
  66. /**
  67. * Called right before launching tests.
  68. *
  69. * Hooks execute in arbitrary order. As such, we recommend using this hook to set up an event listener,
  70. * and performing initialization and cleanup in the corresponding event handlers. This is better than performing
  71. * initialization and cleanup directly in the hook's code because it gives more control over
  72. * order in which initialization is performed.
  73. *
  74. *
  75. * # Usage
  76. *
  77. * Instantiate this class in a cpp file. Pass a unique name for your hook,
  78. * implement body right after macro instantiation:
  79. *
  80. * ```
  81. * Y_TEST_HOOK_BEFORE_RUN(InitMyApp) {
  82. * // hook code
  83. * }
  84. * ```
  85. */
  86. #define Y_TEST_HOOK_BEFORE_RUN(N) \
  87. void N(); \
  88. ::NTesting::THook N##Hook{&N, nullptr}; \
  89. ::NTesting::THook::TRegisterBeforeRun N##HookReg{&N##Hook}; \
  90. void N()
  91. /**
  92. * Called after all tests has finished, just before program exit.
  93. *
  94. * This hook is intended for simple cleanup routines that don't care about order in which hooks are executed.
  95. * For more complex cases, we recommend using `Y_TEST_HOOK_BEFORE_RUN`.
  96. *
  97. *
  98. * # Usage
  99. *
  100. * Instantiate this class in a cpp file. Pass a unique name for your hook,
  101. * implement body right after macro instantiation:
  102. *
  103. * ```
  104. * Y_TEST_HOOK_AFTER_RUN(StopMyApp) {
  105. * // hook code
  106. * }
  107. * ```
  108. */
  109. #define Y_TEST_HOOK_AFTER_RUN(N) \
  110. void N(); \
  111. ::NTesting::THook N##Hook{&N, nullptr}; \
  112. ::NTesting::THook::TRegisterAfterRun N##HookReg{&N##Hook}; \
  113. void N()
  114. }