static_stub.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * KUnit function redirection (static stubbing) API.
  4. *
  5. * Copyright (C) 2022, Google LLC.
  6. * Author: David Gow <davidgow@google.com>
  7. */
  8. #ifndef _KUNIT_STATIC_STUB_H
  9. #define _KUNIT_STATIC_STUB_H
  10. #if !IS_ENABLED(CONFIG_KUNIT)
  11. /* If CONFIG_KUNIT is not enabled, these stubs quietly disappear. */
  12. #define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0)
  13. #else
  14. #include <kunit/test.h>
  15. #include <kunit/test-bug.h>
  16. #include <linux/compiler.h> /* for {un,}likely() */
  17. #include <linux/sched.h> /* for task_struct */
  18. /**
  19. * KUNIT_STATIC_STUB_REDIRECT() - call a replacement 'static stub' if one exists
  20. * @real_fn_name: The name of this function (as an identifier, not a string)
  21. * @args: All of the arguments passed to this function
  22. *
  23. * This is a function prologue which is used to allow calls to the current
  24. * function to be redirected by a KUnit test. KUnit tests can call
  25. * kunit_activate_static_stub() to pass a replacement function in. The
  26. * replacement function will be called by KUNIT_STATIC_STUB_REDIRECT(), which
  27. * will then return from the function. If the caller is not in a KUnit context,
  28. * the function will continue execution as normal.
  29. *
  30. * Example:
  31. *
  32. * .. code-block:: c
  33. *
  34. * int real_func(int n)
  35. * {
  36. * KUNIT_STATIC_STUB_REDIRECT(real_func, n);
  37. * return 0;
  38. * }
  39. *
  40. * int replacement_func(int n)
  41. * {
  42. * return 42;
  43. * }
  44. *
  45. * void example_test(struct kunit *test)
  46. * {
  47. * kunit_activate_static_stub(test, real_func, replacement_func);
  48. * KUNIT_EXPECT_EQ(test, real_func(1), 42);
  49. * }
  50. *
  51. */
  52. #define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) \
  53. do { \
  54. typeof(&real_fn_name) replacement; \
  55. struct kunit *current_test = kunit_get_current_test(); \
  56. \
  57. if (likely(!current_test)) \
  58. break; \
  59. \
  60. replacement = kunit_hooks.get_static_stub_address(current_test, \
  61. &real_fn_name); \
  62. \
  63. if (unlikely(replacement)) \
  64. return replacement(args); \
  65. } while (0)
  66. /* Helper function for kunit_activate_static_stub(). The macro does
  67. * typechecking, so use it instead.
  68. */
  69. void __kunit_activate_static_stub(struct kunit *test,
  70. void *real_fn_addr,
  71. void *replacement_addr);
  72. /**
  73. * kunit_activate_static_stub() - replace a function using static stubs.
  74. * @test: A pointer to the 'struct kunit' test context for the current test.
  75. * @real_fn_addr: The address of the function to replace.
  76. * @replacement_addr: The address of the function to replace it with.
  77. *
  78. * When activated, calls to real_fn_addr from within this test (even if called
  79. * indirectly) will instead call replacement_addr. The function pointed to by
  80. * real_fn_addr must begin with the static stub prologue in
  81. * KUNIT_STATIC_STUB_REDIRECT() for this to work. real_fn_addr and
  82. * replacement_addr must have the same type.
  83. *
  84. * The redirection can be disabled again with kunit_deactivate_static_stub().
  85. */
  86. #define kunit_activate_static_stub(test, real_fn_addr, replacement_addr) do { \
  87. typecheck_fn(typeof(&replacement_addr), real_fn_addr); \
  88. __kunit_activate_static_stub(test, real_fn_addr, replacement_addr); \
  89. } while (0)
  90. /**
  91. * kunit_deactivate_static_stub() - disable a function redirection
  92. * @test: A pointer to the 'struct kunit' test context for the current test.
  93. * @real_fn_addr: The address of the function to no-longer redirect
  94. *
  95. * Deactivates a redirection configured with kunit_activate_static_stub(). After
  96. * this function returns, calls to real_fn_addr() will execute the original
  97. * real_fn, not any previously-configured replacement.
  98. */
  99. void kunit_deactivate_static_stub(struct kunit *test, void *real_fn_addr);
  100. #endif
  101. #endif