/* SPDX-License-Identifier: GPL-2.0 */ /* * Mocking API for KUnit. * * Copyright (C) 2018, Google LLC. * Author: Brendan Higgins */ #ifndef _TEST_MOCK_H #define _TEST_MOCK_H #include #include /* For PARAMS(...) */ #include #include #include /** * struct mock_param_matcher - represents a matcher used in a *call expectation* * @match: the function that performs the matching * * The matching function takes a couple of parameters: * * - ``this``: refers to the parent struct * - ``stream``: a &test_stream to which a detailed message should be added as * to why the parameter matches or not * - ``param``: a pointer to the parameter to check for a match * * The matching function should return whether or not the passed parameter * matches. */ struct mock_param_matcher { bool (*match)(struct mock_param_matcher *this, struct test_stream *stream, const void *param); }; #define MOCK_MAX_PARAMS 255 struct mock_matcher { struct mock_param_matcher *matchers[MOCK_MAX_PARAMS]; int num; }; /** * struct mock_action - Represents an action that a mock performs when * expectation is matched * @do_action: the action to perform * * The action function is given some parameters: * * - ``this``: refers to the parent struct * - ``params``: an array of pointers to the params passed into the mocked * method or function. **The class argument is excluded for a mocked class * method.** * - ``len``: size of ``params`` * * The action function returns a pointer to the value that the mocked method * or function should be returning. */ struct mock_action { void *(*do_action)(struct mock_action *this, const void **params, int len); }; /** * struct mock_expectation - represents a *call expectation* on a function. * @action: A &struct mock_action to perform when the function is called. * @max_calls_expected: maximum number of times an expectation may be called. * @min_calls_expected: minimum number of times an expectation may be called. * @retire_on_saturation: no longer match once ``max_calls_expected`` is * reached. * * Represents a *call expectation* on a function created with EXPECT_CALL(). */ struct mock_expectation { struct mock_action *action; int max_calls_expected; int min_calls_expected; bool retire_on_saturation; /* private: internal use only. */ const char *expectation_name; struct list_head node; struct mock_matcher *matcher; struct mock_method *method; int times_called; const char *file_name; int line_no; const char* expectation_text; /* internal list of prerequisites */ struct list_head prerequisites; }; struct mock_expectation_prereq_entry { struct mock_expectation *expectation; struct list_head node; }; struct mock_method { struct list_head node; const char *method_name; const void *method_ptr; struct mock_action *default_action; struct list_head expectations; }; enum mock_type { MOCK_TYPE_NICE, MOCK_TYPE_NAGGY, MOCK_TYPE_STRICT }; struct mock { struct test_post_condition parent; struct KUNIT_T *test; struct list_head methods; enum mock_type type; const void *(*do_expect)(struct mock *mock, const char *method_name, const void *method_ptr, const char * const *param_types, const void **params, int len); }; #define DEFAULT_MOCK_TYPE MOCK_TYPE_NAGGY void mock_init_ctrl(struct KUNIT_T *test, struct mock *mock); void mock_validate_expectations(struct mock *mock); int mock_set_default_action(struct mock *mock, const char *method_name, const void *method_ptr, struct mock_action *action); struct mock_expectation *mock_add_matcher(struct mock *mock, const char *method_name, const void *method_ptr, struct mock_param_matcher *matchers[], int len); struct mock_param_formatter { struct list_head node; const char *type_name; void (*format)(struct mock_param_formatter *formatter, struct test_stream *stream, const void *param); }; void mock_register_formatter(struct mock_param_formatter *formatter); void mock_unregister_formatter(struct mock_param_formatter *formatter); struct mock *mock_get_global_mock(void); // Transitional: hacks necessary to force expansion if `name` is a macro. #define MOCK(name) MOCK_NOEXPAND(EXPAND(name)) #define MOCK_NOEXPAND(name) MOCK_ACTUALLY(name) #define MOCK_ACTUALLY(name) name##_mock /** * STRICT_MOCK() - sets the mock to be strict and returns the mock * @mock: the mock * * For an example, see ``The Nice, the Strict, and the Naggy`` under * ``Using KUnit``. */ #define STRICT_MOCK(mock) \ ({ \ mock_get_ctrl(mock)->type = MOCK_TYPE_STRICT; \ mock; \ }) static inline bool is_strict_mock(struct mock *mock) { return mock->type == MOCK_TYPE_STRICT; } /** * NICE_MOCK() - sets the mock to be nice and returns the mock * @mock: the mock * * For an example, see ``The Nice, the Strict, and the Naggy`` under * ``Using KUnit``. */ #define NICE_MOCK(mock) \ ({ \ mock_get_ctrl(mock)->type = MOCK_TYPE_NICE; \ mock; \ }) static inline bool is_nice_mock(struct mock *mock) { return mock->type == MOCK_TYPE_NICE; } /** * NAGGY_MOCK() - sets the mock to be naggy and returns the mock * @mock: the mock * * For an example, see ``The Nice, the Strict, and the Naggy`` under * ``Using KUnit``. */ #define NAGGY_MOCK(mock) \ ({ \ mock_get_ctrl(mock)->type = MOCK_TYPE_NAGGY; \ mock; \ }) static inline bool is_naggy_mock(struct mock *mock) { return mock->type == MOCK_TYPE_NAGGY; } /** * EXPECT_CALL() - Declares a *call expectation* on a mock method or function. * @expectation_call: a mocked method or function with parameters replaced with * matchers. * * Example: * * .. code-block:: c * * // Class to mock. * struct example { * int (*foo)(struct example *, int); * }; * * // Define the mock. * DECLARE_STRUCT_CLASS_MOCK_PREREQS(example); * * DEFINE_STRUCT_CLASS_MOCK(METHOD(foo), CLASS(example), * RETURNS(int), * PARAMS(struct example *, int)); * * static int example_init(struct MOCK(example) *mock_example) * { * struct example *example = mock_get_trgt(mock_example); * * example->foo = foo; * return 0; * } * * DEFINE_STRUCT_CLASS_MOCK_INIT(example, example_init); * * static void foo_example_test_success(struct KUNIT_T *test) * { * struct MOCK(example) *mock_example; * struct example *example = mock_get_trgt(mock_example); * struct mock_expectation *handle; * * mock_example = CONSTRUCT_MOCK(example, test); * * handle = EXPECT_CALL(foo(mock_get_ctrl(mock_example), * int_eq(test, 5))); * handle->action = int_return(test, 2); * * EXPECT_EQ(test, 2, example_bar(example, 5)); * } * * Return: * A &struct mock_expectation representing the call expectation. * allowing additional conditions and actions to be specified. */ #define EXPECT_CALL(expectation_call) \ expect_call_wrapper(__FILE__, __LINE__, \ #expectation_call, mock_master_##expectation_call) static inline struct mock_expectation *expect_call_wrapper( const char *file_name, int line_no, const char* expectation_text, struct mock_expectation *expectation) { expectation->file_name = file_name; expectation->line_no = line_no; expectation->expectation_text = expectation_text; return expectation; } /** * Times() - sets the number of times a method is expected be called with the * matching parameters * @times: the number of times expected * @expectation: the expectation to set * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *Times( int times, struct mock_expectation *expectation) { expectation->min_calls_expected = times; expectation->max_calls_expected = times; return expectation; } /** * AtLeast() - sets the minimum number of times a method is expected to be * called with matching parameters * @times: the minimum number of times expected * @expectation: the expectation to set * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *AtLeast( int times, struct mock_expectation *expectation) { expectation->min_calls_expected = times; expectation->max_calls_expected = INT_MAX; return expectation; } /** * AtMost() - sets the maximum number of times a method is expected to be * called with matching parameters * @times: the maximum number of times expected * @expectation: the expectation to set * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *AtMost( int times, struct mock_expectation *expectation) { expectation->min_calls_expected = 0; expectation->max_calls_expected = times; return expectation; } /** * Between() - sets the minimum and maximum number of times a method is * expected to be called with matching parameters * @min_times: the minimum number of times expected * @max_times: the maximum number of times expected * @expectation: the expectation to set * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *Between( int min_times, int max_times, struct mock_expectation *expectation) { expectation->min_calls_expected = min_times; expectation->max_calls_expected = max_times; return expectation; } /** * Never() - alias for Times(0) * @expectation: the expectation to set * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *Never( struct mock_expectation *expectation) { return Times(0, expectation); } /** * RetireOnSaturation() - sets the expectation to retire on saturation * @expectation: the expectation to set * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *RetireOnSaturation( struct mock_expectation *expectation) { expectation->retire_on_saturation = true; return expectation; } /** * ActionOnMatch() - sets a action of the expectation when matched * @expectation: the expectation to set the action of * @action: action to perform when expectation matches * * Example: * * .. code-block:: c * * ActionOnMatch(EXPECT_CALL(...), INVOKE_REAL(test, ...)); * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *ActionOnMatch( struct mock_expectation *expectation, struct mock_action *action) { expectation->action = action; return expectation; } /** * Returns() - sets a action of the expectation to return a value * @expectation: the expectation to set the return value of * @return_action: a return action * * Example: * * .. code-block:: c * * Returns(EXPECT_CALL(...), int_return(test, 10)); * * Return: * the same &struct mock_expectation passed in */ static inline struct mock_expectation *Returns( struct mock_expectation *expectation, struct mock_action *return_action) { return ActionOnMatch(expectation, return_action); } /** * InSequence() - defines an order for expectations to be matched * @test: the test, used for internal resource allocations * @first: the first &struct mock_expectation in the sequence * @...: the rest of the expectations in order following * * Example: * * .. code-block:: c * * struct mock_expectation *a = EXPECT_CALL(...); * struct mock_expectation *b = EXPECT_CALL(...); * struct mock_expectation *c = EXPECT_CALL(...); * * InSequence(test, a, b, c); * * Return: * 0 if everything was successful, otherwise a memory allocation error */ #define InSequence(test, first, ...) \ mock_in_sequence(test, first, __VA_ARGS__, 0) int mock_in_sequence(struct KUNIT_T *test, struct mock_expectation *first, ...); #define mock_get_ctrl_internal(mock_object) (&(mock_object)->ctrl) #define mock_get_ctrl(mock_object) mock_get_ctrl_internal(mock_object) #define mock_get_trgt_internal(mock_object) (&(mock_object)->trgt) #define mock_get_trgt(mock_object) mock_get_trgt_internal(mock_object) #define mock_get_test(mock_object) (mock_get_ctrl(mock_object)->test) #define CLASS(struct_name) EXPAND(struct_name) #define HANDLE_INDEX(index) index #define METHOD(method_name) method_name #define RETURNS(return_type) return_type /* #define PARAMS(...) __VA_ARGS__ included by linux/tracepoint.h */ #define MOCK_INIT_ID(struct_name) struct_name##mock_init #define REAL_ID(func_name) __real__##func_name #define INVOKE_ID(func_name) __invoke__##func_name #define DECLARE_MOCK_CLIENT(name, return_type, param_types...) \ return_type name(PARAM_LIST_FROM_TYPES(param_types)) #define DECLARE_MOCK_MASTER(name, ctrl_index, param_types...) \ struct mock_expectation *mock_master_##name( \ MATCHER_PARAM_LIST_FROM_TYPES(ctrl_index, \ param_types)); #define DECLARE_MOCK_COMMON(name, handle_index, return_type, param_types...) \ DECLARE_MOCK_CLIENT(name, return_type, param_types); \ DECLARE_MOCK_MASTER(name, handle_index, param_types) #define DECLARE_REDIRECT_MOCKABLE(name, return_type, param_types...) \ return_type REAL_ID(name)(param_types); \ return_type name(param_types); \ void *INVOKE_ID(name)(struct KUNIT_T *test, \ const void *params[], \ int len) #define DECLARE_MOCK_FUNC_CLIENT(name, return_type, param_types...) \ DECLARE_MOCK_CLIENT(name, return_type, param_types) #define DECLARE_MOCK_FUNC_MASTER(name, param_types...) \ DECLARE_MOCK_MASTER(name, MOCK_MAX_PARAMS, param_types) #define DECLARE_STRUCT_CLASS_MOCK_STRUCT(struct_name) \ struct MOCK(struct_name) { \ struct mock ctrl; \ struct struct_name trgt; \ } #define DECLARE_STRUCT_CLASS_MOCK_CONVERTER(struct_name) \ static inline struct mock *from_##struct_name##_to_mock( \ const struct struct_name *trgt) \ { \ return mock_get_ctrl( \ container_of(trgt, \ struct MOCK(struct_name), \ trgt)); \ } /** * DECLARE_STRUCT_CLASS_MOCK_PREREQS() - Create a mock child class * @struct_name: name of the class/struct to be mocked * * Creates a mock child class of ``struct_name`` named * ``struct MOCK(struct_name)`` along with supporting internally used methods. * * See EXPECT_CALL() for example usages. */ #define DECLARE_STRUCT_CLASS_MOCK_PREREQS(struct_name) \ DECLARE_STRUCT_CLASS_MOCK_STRUCT(struct_name); \ DECLARE_STRUCT_CLASS_MOCK_CONVERTER(struct_name) #define DECLARE_STRUCT_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ struct_name, \ handle_index, \ return_type, \ param_types...) \ DECLARE_MOCK_COMMON(name, \ handle_index, \ return_type, \ param_types) #define DECLARE_STRUCT_CLASS_MOCK_HANDLE_INDEX(name, \ struct_name, \ handle_index, \ return_type, \ param_types...) \ DECLARE_STRUCT_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ struct_name, \ handle_index, \ return_type, \ param_types) /** * DECLARE_STRUCT_CLASS_MOCK() * @name: method name * @struct_name: name of the class/struct * @return_type: return type of the method * @param_types: parameters of the method * * Same as DEFINE_STRUCT_CLASS_MOCK(), but only makes header compatible * declarations. */ #define DECLARE_STRUCT_CLASS_MOCK(name, \ struct_name, \ return_type, \ param_types...) \ DECLARE_STRUCT_CLASS_MOCK_HANDLE_INDEX(name, \ struct_name, \ 0, \ return_type, \ param_types) /** * DECLARE_STRUCT_CLASS_MOCK_VOID_RETURN() * @name: method name * @struct_name: name of the class/struct * @param_types: parameters of the method * * Same as DEFINE_STRUCT_CLASS_MOCK_VOID_RETURN(), but only makes header * compatible declarations. */ #define DECLARE_STRUCT_CLASS_MOCK_VOID_RETURN(name, \ struct_name, \ param_types...) \ DECLARE_STRUCT_CLASS_MOCK_HANDLE_INDEX(name, \ struct_name, \ 0, \ void, \ param_types) /** * DECLARE_STRUCT_CLASS_MOCK_INIT() * @struct_name: name of the class/struct * * Same as DEFINE_STRUCT_CLASS_MOCK_INIT(), but only makes header compatible * declarations. */ #define DECLARE_STRUCT_CLASS_MOCK_INIT(struct_name) \ DECLARE_STRUCT_CLASS_MOCK_INIT_NOEXPAND(EXPAND(struct_name)) #define DECLARE_STRUCT_CLASS_MOCK_INIT_NOEXPAND(struct_name) \ struct MOCK(struct_name) *MOCK_INIT_ID(struct_name)( \ struct KUNIT_T *test) #define DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ handle_index, \ return_type, \ param_types...) \ DECLARE_MOCK_COMMON(name, \ handle_index, \ return_type, \ param_types) #define DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX(name, \ handle_index, \ return_type, \ param_types...) \ DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ handle_index, \ return_type, \ param_types) /** * CONSTRUCT_MOCK() * @struct_name: name of the class * @test: associated test * * Constructs and allocates a test managed ``struct MOCK(struct_name)`` given * the name of the class for which the mock is defined and a test object. * * See EXPECT_CALL() for example usage. */ #define CONSTRUCT_MOCK(struct_name, test) MOCK_INIT_ID(struct_name)(test) #define DECLARE_FUNCTION_MOCK_INTERNAL(name, return_type, param_types...) \ DECLARE_MOCK_FUNC_CLIENT(name, return_type, param_types); \ DECLARE_MOCK_FUNC_MASTER(name, param_types); #define DECLARE_FUNCTION_MOCK(name, return_type, param_types...) \ DECLARE_FUNCTION_MOCK_INTERNAL(name, return_type, param_types) #define DECLARE_FUNCTION_MOCK_VOID_RETURN(name, param_types...) \ DECLARE_FUNCTION_MOCK(name, void, param_types) #define DEFINE_MOCK_CLIENT_COMMON(name, \ handle_index, \ MOCK_SOURCE, \ mock_source_ctx, \ return_type, \ RETURN, \ param_types...) \ return_type name(PARAM_LIST_FROM_TYPES(param_types)) \ { \ struct mock *mock = MOCK_SOURCE(mock_source_ctx, \ handle_index); \ static const char * const param_type_names[] = { \ TYPE_NAMES_FROM_TYPES(handle_index, \ param_types) \ }; \ const void *params[] = { \ PTR_TO_ARG_FROM_TYPES(handle_index, \ param_types) \ }; \ const void *retval; \ \ retval = mock->do_expect(mock, \ #name, \ name, \ param_type_names, \ params, \ ARRAY_SIZE(params)); \ if (!retval) { \ ASSERT_FAILURE(mock->test, "mock " #name \ " expects to return a value," \ " but none is provided."); \ } \ RETURN(return_type, retval); \ } #if IS_ENABLED(CONFIG_SEC_KUNIT) #define DEFINE_INVOKABLE(name, return_type, RETURN_ASSIGN, param_types...) \ void *INVOKE_ID(name)(struct KUNIT_T *test, \ const void *params[], \ int len) { \ return_type *retval; \ \ ASSERT_EQ(test, NUM_VA_ARGS(param_types), len); \ retval = test_kzalloc(test, \ sizeof(*retval), \ GFP_KERNEL); \ ASSERT_NOT_ERR_OR_NULL(test, retval); \ RETURN_ASSIGN() REAL_ID(name)( \ ARRAY_ACCESSORS_FROM_TYPES( \ param_types)); \ return retval; \ } #else #define DEFINE_INVOKABLE(name, return_type, RETURN_ASSIGN, param_types...) #endif #define DEFINE_REDIRECT_MOCKABLE_COMMON(name, \ return_type, \ RETURN_ASSIGN, \ param_types...) \ return_type REAL_ID(name)(param_types); \ return_type name(param_types) __mockable_alias(REAL_ID(name)); \ DEFINE_INVOKABLE(name, return_type, RETURN_ASSIGN, param_types); #define ASSIGN() *retval = /** * DEFINE_REDIRECT_MOCKABLE() * @name: name of the function * @return_type: return type of the function * @param_types: parameter types of the function * * Used to define a function which is *redirect-mockable*, which allows the * function to be mocked and refer to the original definition via * INVOKE_REAL(). * * Example: * * .. code-block:: c * * DEFINE_REDIRECT_MOCKABLE(i2c_add_adapter, * RETURNS(int), PARAMS(struct i2c_adapter *)); * int REAL_ID(i2c_add_adapter)(struct i2c_adapter *adapter) * { * ... * } * * static int aspeed_i2c_test_init(struct KUNIT_T *test) * { * struct mock_param_capturer *adap_capturer; * struct mock_expectation *handle; * struct aspeed_i2c_test *ctx; * int ret; * * ctx = test_kzalloc(test, sizeof(*ctx), GFP_KERNEL); * if (!ctx) * return -ENOMEM; * test->priv = ctx; * * handle = EXPECT_CALL( * i2c_add_adapter(capturer_to_matcher( * adap_capturer))); * handle->action = INVOKE_REAL(test, i2c_add_adapter); * ret = of_fake_probe_platform_by_name(test, * "aspeed-i2c-bus", * "test-i2c-bus"); * if (ret < 0) * return ret; * * ASSERT_PARAM_CAPTURED(test, adap_capturer); * ctx->adap = mock_capturer_get(adap_capturer, * struct i2c_adapter *); * * return 0; * } */ #define DEFINE_REDIRECT_MOCKABLE(name, return_type, param_types...) \ DEFINE_REDIRECT_MOCKABLE_COMMON(name, \ return_type, \ ASSIGN, \ param_types) #define NO_ASSIGN() #define DEFINE_REDIRECT_MOCKABLE_VOID_RETURN(name, param_types) \ DEFINE_REDIRECT_MOCKABLE_COMMON(name, \ void, \ NO_ASSIGN, \ param_types) #define CLASS_MOCK_CLIENT_SOURCE(ctx, handle_index) ctx(arg##handle_index) #define DEFINE_MOCK_METHOD_CLIENT_COMMON(name, \ handle_index, \ mock_converter, \ return_type, \ RETURN, \ param_types...) \ DEFINE_MOCK_CLIENT_COMMON(name, \ handle_index, \ CLASS_MOCK_CLIENT_SOURCE, \ mock_converter, \ return_type, \ RETURN, \ param_types) #define CAST_AND_RETURN(return_type, retval) return *((return_type *) retval) #define NO_RETURN(return_type, retval) #define DEFINE_MOCK_METHOD_CLIENT(name, \ handle_index, \ mock_converter, \ return_type, \ param_types...) \ DEFINE_MOCK_METHOD_CLIENT_COMMON(name, \ handle_index, \ mock_converter, \ return_type, \ CAST_AND_RETURN, \ param_types) #define DEFINE_MOCK_METHOD_CLIENT_VOID_RETURN(name, \ handle_index, \ mock_converter, \ param_types...) \ DEFINE_MOCK_METHOD_CLIENT_COMMON(name, \ handle_index, \ mock_converter, \ void, \ NO_RETURN, \ param_types) #define FUNC_MOCK_SOURCE(ctx, handle_index) mock_get_global_mock() #define DEFINE_MOCK_FUNC_CLIENT_COMMON(name, \ return_type, \ RETURN, \ param_types...) \ DEFINE_MOCK_CLIENT_COMMON(name, \ MOCK_MAX_PARAMS, \ FUNC_MOCK_SOURCE, \ name, \ return_type, \ RETURN, \ param_types) #define DEFINE_MOCK_FUNC_CLIENT(name, return_type, param_types...) \ DEFINE_MOCK_FUNC_CLIENT_COMMON(name, \ return_type, \ CAST_AND_RETURN, \ param_types) #define DEFINE_MOCK_FUNC_CLIENT_VOID_RETURN(name, param_types...) \ DEFINE_MOCK_FUNC_CLIENT_COMMON(name, \ void, \ NO_RETURN, \ param_types) #define DEFINE_MOCK_MASTER_COMMON_INTERNAL(name, \ ctrl_index, \ MOCK_SOURCE, \ param_types...) \ struct mock_expectation *mock_master_##name( \ MATCHER_PARAM_LIST_FROM_TYPES(ctrl_index, \ param_types)) \ { \ struct mock_param_matcher *matchers[] = { \ ARG_NAMES_FROM_TYPES(ctrl_index, param_types) \ }; \ \ return mock_add_matcher(MOCK_SOURCE(ctrl_index), \ #name, \ (const void *) name, \ matchers, \ ARRAY_SIZE(matchers)); \ } #define DEFINE_MOCK_MASTER_COMMON(name, \ ctrl_index, \ MOCK_SOURCE, \ param_types...) \ DEFINE_MOCK_MASTER_COMMON_INTERNAL(name, \ ctrl_index, \ MOCK_SOURCE, \ param_types) #define CLASS_MOCK_MASTER_SOURCE(ctrl_index) arg##ctrl_index #define DEFINE_MOCK_METHOD_MASTER(name, ctrl_index, param_types...) \ DEFINE_MOCK_MASTER_COMMON(name, \ ctrl_index, \ CLASS_MOCK_MASTER_SOURCE, \ param_types) #define FUNC_MOCK_CLIENT_SOURCE(ctrl_index) mock_get_global_mock() #define DEFINE_MOCK_FUNC_MASTER(name, param_types...) \ DEFINE_MOCK_MASTER_COMMON(name, \ MOCK_MAX_PARAMS, \ FUNC_MOCK_CLIENT_SOURCE, \ param_types) #define DEFINE_MOCK_COMMON(name, \ handle_index, \ mock_converter, \ return_type, \ param_types...) \ DEFINE_MOCK_METHOD_CLIENT(name, \ handle_index, \ mock_converter, \ return_type, \ param_types); \ DEFINE_MOCK_METHOD_MASTER(name, handle_index, param_types) #define DEFINE_MOCK_COMMON_VOID_RETURN(name, \ handle_index, \ mock_converter, \ param_types...) \ DEFINE_MOCK_METHOD_CLIENT_VOID_RETURN(name, \ handle_index, \ mock_converter, \ param_types); \ DEFINE_MOCK_METHOD_MASTER(name, handle_index, param_types) #define DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ struct_name, \ handle_index, \ return_type, \ param_types...) \ DEFINE_MOCK_COMMON(name, \ handle_index, \ from_##struct_name##_to_mock, \ return_type, param_types) #define DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX(name, \ struct_name, \ handle_index, \ return_type, \ param_types...) \ DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ struct_name, \ handle_index, \ return_type, \ param_types) #define DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX_VOID_RETURN_INTERNAL( \ name, \ struct_name, \ handle_index, \ param_types...) \ DEFINE_MOCK_COMMON_VOID_RETURN(name, \ handle_index, \ from_##struct_name##_to_mock, \ param_types) #define DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX_VOID_RETURN(name, \ struct_name, \ handle_index, \ param_types...) \ DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX_VOID_RETURN_INTERNAL( \ name, \ struct_name, \ handle_index, \ param_types) /** * DEFINE_STRUCT_CLASS_MOCK() * @name: name of the method * @struct_name: name of the class of which the method belongs * @return_type: return type of the method to be created. **Must not be void.** * @param_types: parameters to method to be created. * * See EXPECT_CALL() for example usage. */ #define DEFINE_STRUCT_CLASS_MOCK(name, \ struct_name, \ return_type, \ param_types...) \ DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX(name, \ struct_name, \ 0, \ return_type, \ param_types) /** * DEFINE_STRUCT_CLASS_MOCK_VOID_RETURN() * @name: name of the method * @struct_name: name of the class of which the method belongs * @param_types: parameters to method to be created. * * Same as DEFINE_STRUCT_CLASS_MOCK() except the method has a ``void`` return * type. */ #define DEFINE_STRUCT_CLASS_MOCK_VOID_RETURN(name, struct_name, param_types...)\ DEFINE_STRUCT_CLASS_MOCK_HANDLE_INDEX_VOID_RETURN(name, \ struct_name, \ 0, \ param_types) /** * DEFINE_STRUCT_CLASS_MOCK_INIT() * @struct_name: name of the class * @init_func: a function of type ``int (*)(struct MOCK(struct_name) *)``. This * function is passed a pointer to an allocated, *but not * initialized*, ``struct MOCK(struct_name)``. The job of this user * provided function is to perform remaining initialization. Usually * this entails assigning mock methods to the function pointers in * the parent struct. * * See EXPECT_CALL() for example usage. */ #define DEFINE_STRUCT_CLASS_MOCK_INIT(struct_name, init_func) \ struct MOCK(struct_name) *MOCK_INIT_ID(struct_name)( \ struct KUNIT_T *test) \ { \ struct MOCK(struct_name) *mock_obj; \ \ mock_obj = test_kzalloc(test, \ sizeof(*mock_obj), \ GFP_KERNEL); \ if (!mock_obj) \ return NULL; \ \ mock_init_ctrl(test, mock_get_ctrl(mock_obj)); \ \ if (init_func(mock_obj)) \ return NULL; \ \ return mock_obj; \ } struct MOCK(void) { struct mock ctrl; void *trgt; }; static inline struct mock *from_void_ptr_to_mock(const void *ptr) { struct MOCK(void) *mock_void_ptr = (void *)ptr; return mock_get_ctrl(mock_void_ptr); } #define DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ handle_index, \ return_type, \ param_types...) \ DEFINE_MOCK_COMMON(name, \ handle_index, \ from_void_ptr_to_mock, \ return_type, \ param_types) #define DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX(name, \ handle_index, \ return_type, \ param_types...) \ DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \ handle_index, \ return_type, \ param_types) DECLARE_STRUCT_CLASS_MOCK_INIT(void); #define DEFINE_FUNCTION_MOCK_INTERNAL(name, return_type, param_types...) \ DEFINE_MOCK_FUNC_CLIENT(name, return_type, param_types); \ DEFINE_MOCK_FUNC_MASTER(name, param_types) /** * DEFINE_FUNCTION_MOCK() * @name: name of the function * @return_type: return type of the function * @...: parameter types of the function * * Same as DEFINE_STRUCT_CLASS_MOCK() except can be used to mock any function * declared %__mockable or DEFINE_REDIRECT_MOCKABLE() */ #define DEFINE_FUNCTION_MOCK(name, return_type, param_types...) \ DEFINE_FUNCTION_MOCK_INTERNAL(name, return_type, param_types) #define DEFINE_FUNCTION_MOCK_VOID_RETURN_INTERNAL(name, param_types...) \ DEFINE_MOCK_FUNC_CLIENT_VOID_RETURN(name, param_types); \ DEFINE_MOCK_FUNC_MASTER(name, param_types) /** * DEFINE_FUNCTION_MOCK_VOID_RETURN() * @name: name of the function * @...: parameter types of the function * * Same as DEFINE_FUNCTION_MOCK() except the method has a ``void`` return * type. */ #define DEFINE_FUNCTION_MOCK_VOID_RETURN(name, param_types...) \ DEFINE_FUNCTION_MOCK_VOID_RETURN_INTERNAL(name, param_types) #if IS_ENABLED(CONFIG_SEC_KUNIT) /** * __mockable - A function decorator that allows the function to be mocked. * * Example: * * .. code-block:: c * * int __mockable example(int arg) { ... } */ #define __mockable __weak #define __mockable_alias(id) __weak __alias(id) /** * __visible_for_testing - Makes a static function visible when testing. * * A macro that replaces the `static` specifier on functions and global * variables that is static when compiled normally and visible when compiled for * tests. */ #define __visible_for_testing #else #define __mockable #define __mockable_alias(id) __alias(id) #define __visible_for_testing static #endif #define CONVERT_TO_ACTUAL_TYPE(type, ptr) (*((type *) ptr)) /** * DOC: Built In Matchers * * These are the matchers that can be used when matching arguments in * :c:func:`EXPECT_CALL` (more can be defined manually). * * For example, there's a matcher that matches any arguments: * * .. code-block:: c * * struct mock_param_matcher *any(struct KUNIT_T *test); * * There are matchers for integers based on the binary condition: * * * eq: equals to * * ne: not equal to * * lt: less than * * le: less than or equal to * * gt: greater than * * ge: greater than or equal to * * .. code-block:: c * * struct mock_param_matcher *int_eq(struct KUNIT_T *test, int expected); * struct mock_param_matcher *int_ne(struct KUNIT_T *test, int expected); * struct mock_param_matcher *int_lt(struct KUNIT_T *test, int expected); * struct mock_param_matcher *int_le(struct KUNIT_T *test, int expected); * struct mock_param_matcher *int_gt(struct KUNIT_T *test, int expected); * struct mock_param_matcher *int_ge(struct KUNIT_T *test, int expected); * * For a detailed list, please see * ``include/linux/mock.h``. */ /* Matches any argument */ struct mock_param_matcher *any(struct KUNIT_T *test); /* * Matches different types of integers, the argument is compared to the * `expected` field, based on the comparison defined. */ struct mock_param_matcher *u8_eq(struct KUNIT_T *test, u8 expected); struct mock_param_matcher *u8_ne(struct KUNIT_T *test, u8 expected); struct mock_param_matcher *u8_le(struct KUNIT_T *test, u8 expected); struct mock_param_matcher *u8_lt(struct KUNIT_T *test, u8 expected); struct mock_param_matcher *u8_ge(struct KUNIT_T *test, u8 expected); struct mock_param_matcher *u8_gt(struct KUNIT_T *test, u8 expected); struct mock_param_matcher *u16_eq(struct KUNIT_T *test, u16 expected); struct mock_param_matcher *u16_ne(struct KUNIT_T *test, u16 expected); struct mock_param_matcher *u16_le(struct KUNIT_T *test, u16 expected); struct mock_param_matcher *u16_lt(struct KUNIT_T *test, u16 expected); struct mock_param_matcher *u16_ge(struct KUNIT_T *test, u16 expected); struct mock_param_matcher *u16_gt(struct KUNIT_T *test, u16 expected); struct mock_param_matcher *u32_eq(struct KUNIT_T *test, u32 expected); struct mock_param_matcher *u32_ne(struct KUNIT_T *test, u32 expected); struct mock_param_matcher *u32_le(struct KUNIT_T *test, u32 expected); struct mock_param_matcher *u32_lt(struct KUNIT_T *test, u32 expected); struct mock_param_matcher *u32_ge(struct KUNIT_T *test, u32 expected); struct mock_param_matcher *u32_gt(struct KUNIT_T *test, u32 expected); struct mock_param_matcher *u64_eq(struct KUNIT_T *test, u64 expected); struct mock_param_matcher *u64_ne(struct KUNIT_T *test, u64 expected); struct mock_param_matcher *u64_le(struct KUNIT_T *test, u64 expected); struct mock_param_matcher *u64_lt(struct KUNIT_T *test, u64 expected); struct mock_param_matcher *u64_ge(struct KUNIT_T *test, u64 expected); struct mock_param_matcher *u64_gt(struct KUNIT_T *test, u64 expected); struct mock_param_matcher *char_eq(struct KUNIT_T *test, char expected); struct mock_param_matcher *char_ne(struct KUNIT_T *test, char expected); struct mock_param_matcher *char_le(struct KUNIT_T *test, char expected); struct mock_param_matcher *char_lt(struct KUNIT_T *test, char expected); struct mock_param_matcher *char_ge(struct KUNIT_T *test, char expected); struct mock_param_matcher *char_gt(struct KUNIT_T *test, char expected); struct mock_param_matcher *uchar_eq(struct KUNIT_T *test, unsigned char expected); struct mock_param_matcher *uchar_ne(struct KUNIT_T *test, unsigned char expected); struct mock_param_matcher *uchar_le(struct KUNIT_T *test, unsigned char expected); struct mock_param_matcher *uchar_lt(struct KUNIT_T *test, unsigned char expected); struct mock_param_matcher *uchar_ge(struct KUNIT_T *test, unsigned char expected); struct mock_param_matcher *uchar_gt(struct KUNIT_T *test, unsigned char expected); struct mock_param_matcher *schar_eq(struct KUNIT_T *test, signed char expected); struct mock_param_matcher *schar_ne(struct KUNIT_T *test, signed char expected); struct mock_param_matcher *schar_le(struct KUNIT_T *test, signed char expected); struct mock_param_matcher *schar_lt(struct KUNIT_T *test, signed char expected); struct mock_param_matcher *schar_ge(struct KUNIT_T *test, signed char expected); struct mock_param_matcher *schar_gt(struct KUNIT_T *test, signed char expected); struct mock_param_matcher *short_eq(struct KUNIT_T *test, short expected); struct mock_param_matcher *short_ne(struct KUNIT_T *test, short expected); struct mock_param_matcher *short_le(struct KUNIT_T *test, short expected); struct mock_param_matcher *short_lt(struct KUNIT_T *test, short expected); struct mock_param_matcher *short_ge(struct KUNIT_T *test, short expected); struct mock_param_matcher *short_gt(struct KUNIT_T *test, short expected); struct mock_param_matcher *ushort_eq(struct KUNIT_T *test, unsigned short expected); struct mock_param_matcher *ushort_ne(struct KUNIT_T *test, unsigned short expected); struct mock_param_matcher *ushort_le(struct KUNIT_T *test, unsigned short expected); struct mock_param_matcher *ushort_lt(struct KUNIT_T *test, unsigned short expected); struct mock_param_matcher *ushort_ge(struct KUNIT_T *test, unsigned short expected); struct mock_param_matcher *ushort_gt(struct KUNIT_T *test, unsigned short expected); struct mock_param_matcher *int_eq(struct KUNIT_T *test, int expected); struct mock_param_matcher *int_ne(struct KUNIT_T *test, int expected); struct mock_param_matcher *int_lt(struct KUNIT_T *test, int expected); struct mock_param_matcher *int_le(struct KUNIT_T *test, int expected); struct mock_param_matcher *int_gt(struct KUNIT_T *test, int expected); struct mock_param_matcher *int_ge(struct KUNIT_T *test, int expected); struct mock_param_matcher *uint_eq(struct KUNIT_T *test, unsigned int expected); struct mock_param_matcher *uint_ne(struct KUNIT_T *test, unsigned int expected); struct mock_param_matcher *uint_lt(struct KUNIT_T *test, unsigned int expected); struct mock_param_matcher *uint_le(struct KUNIT_T *test, unsigned int expected); struct mock_param_matcher *uint_gt(struct KUNIT_T *test, unsigned int expected); struct mock_param_matcher *uint_ge(struct KUNIT_T *test, unsigned int expected); struct mock_param_matcher *long_eq(struct KUNIT_T *test, long expected); struct mock_param_matcher *long_ne(struct KUNIT_T *test, long expected); struct mock_param_matcher *long_le(struct KUNIT_T *test, long expected); struct mock_param_matcher *long_lt(struct KUNIT_T *test, long expected); struct mock_param_matcher *long_ge(struct KUNIT_T *test, long expected); struct mock_param_matcher *long_gt(struct KUNIT_T *test, long expected); struct mock_param_matcher *ulong_eq(struct KUNIT_T *test, unsigned long expected); struct mock_param_matcher *ulong_ne(struct KUNIT_T *test, unsigned long expected); struct mock_param_matcher *ulong_le(struct KUNIT_T *test, unsigned long expected); struct mock_param_matcher *ulong_lt(struct KUNIT_T *test, unsigned long expected); struct mock_param_matcher *ulong_ge(struct KUNIT_T *test, unsigned long expected); struct mock_param_matcher *ulong_gt(struct KUNIT_T *test, unsigned long expected); struct mock_param_matcher *longlong_eq(struct KUNIT_T *test, long long expected); struct mock_param_matcher *longlong_ne(struct KUNIT_T *test, long long expected); struct mock_param_matcher *longlong_le(struct KUNIT_T *test, long long expected); struct mock_param_matcher *longlong_lt(struct KUNIT_T *test, long long expected); struct mock_param_matcher *longlong_ge(struct KUNIT_T *test, long long expected); struct mock_param_matcher *longlong_gt(struct KUNIT_T *test, long long expected); struct mock_param_matcher *ulonglong_eq(struct KUNIT_T *test, unsigned long long expected); struct mock_param_matcher *ulonglong_ne(struct KUNIT_T *test, unsigned long long expected); struct mock_param_matcher *ulonglong_le(struct KUNIT_T *test, unsigned long long expected); struct mock_param_matcher *ulonglong_lt(struct KUNIT_T *test, unsigned long long expected); struct mock_param_matcher *ulonglong_ge(struct KUNIT_T *test, unsigned long long expected); struct mock_param_matcher *ulonglong_gt(struct KUNIT_T *test, unsigned long long expected); /* matches booleans. */ struct mock_param_matcher *bool_eq(struct KUNIT_T *test, bool expected); struct mock_param_matcher *bool_ne(struct KUNIT_T *test, bool expected); /* Matches pointers. */ struct mock_param_matcher *ptr_eq(struct KUNIT_T *test, void *expected); struct mock_param_matcher *ptr_ne(struct KUNIT_T *test, void *expected); struct mock_param_matcher *ptr_lt(struct KUNIT_T *test, void *expected); struct mock_param_matcher *ptr_le(struct KUNIT_T *test, void *expected); struct mock_param_matcher *ptr_gt(struct KUNIT_T *test, void *expected); struct mock_param_matcher *ptr_ge(struct KUNIT_T *test, void *expected); /* Matches memory sections and strings. */ struct mock_param_matcher *memeq(struct KUNIT_T *test, const void *buf, size_t size); struct mock_param_matcher *streq(struct KUNIT_T *test, const char *str); struct mock_param_matcher *str_contains(struct KUNIT_T *test, const char *needle); /* Matches var-arg arguments. */ struct mock_param_matcher *va_format_cmp(struct KUNIT_T *test, struct mock_param_matcher *fmt_matcher, struct mock_param_matcher *va_matcher); /* Compound matchers */ struct mock_param_matcher *and(struct KUNIT_T *test, struct mock_param_matcher *left_matcher, struct mock_param_matcher *right_matcher); struct mock_param_matcher *or(struct KUNIT_T *test, struct mock_param_matcher *left_matcher, struct mock_param_matcher *right_matcher); struct mock_param_matcher *not(struct KUNIT_T *test, struct mock_param_matcher *inner_matcher); struct mock_action *bool_return(struct KUNIT_T *test, bool ret); struct mock_action *u8_return(struct KUNIT_T *test, u8 ret); struct mock_action *u16_return(struct KUNIT_T *test, u16 ret); struct mock_action *u32_return(struct KUNIT_T *test, u32 ret); struct mock_action *u64_return(struct KUNIT_T *test, u64 ret); struct mock_action *char_return(struct KUNIT_T *test, char ret); struct mock_action *uchar_return(struct KUNIT_T *test, unsigned char ret); struct mock_action *schar_return(struct KUNIT_T *test, signed char ret); struct mock_action *short_return(struct KUNIT_T *test, short ret); struct mock_action *ushort_return(struct KUNIT_T *test, unsigned short ret); struct mock_action *int_return(struct KUNIT_T *test, int ret); struct mock_action *uint_return(struct KUNIT_T *test, unsigned int ret); struct mock_action *long_return(struct KUNIT_T *test, long ret); struct mock_action *ulong_return(struct KUNIT_T *test, unsigned long ret); struct mock_action *longlong_return(struct KUNIT_T *test, long long ret); struct mock_action *ulonglong_return(struct KUNIT_T *test, unsigned long long ret); struct mock_action *ptr_return(struct KUNIT_T *test, void *ret); /** * struct mock_struct_matcher_entry - composed with other &struct * mock_struct_matcher_entry to make a * &struct struct_matcher * @member_offset: offset of this member * @matcher: matcher for this particular member * * This is used for struct_cmp() matchers. */ struct mock_struct_matcher_entry { size_t member_offset; struct mock_param_matcher *matcher; }; static inline void init_mock_struct_matcher_entry_internal( struct mock_struct_matcher_entry *entry, size_t offset, struct mock_param_matcher *matcher) { entry->member_offset = offset; entry->matcher = matcher; } /** * INIT_MOCK_STRUCT_MATCHER_ENTRY() * @entry: the &struct mock_struct_matcher_entry to initialize * @type: the struct being matched * @member: the member of the struct being matched, used to calculate the offset * @matcher: matcher to match that member * * Initializes ``entry`` to match ``type->member`` with ``matcher``. */ #define INIT_MOCK_STRUCT_MATCHER_ENTRY(entry, type, member, matcher) \ init_mock_struct_matcher_entry_internal(entry, \ offsetof(type, member),\ matcher) static inline void INIT_MOCK_STRUCT_MATCHER_ENTRY_LAST( struct mock_struct_matcher_entry *entry) { entry->matcher = NULL; } struct mock_param_matcher *struct_cmp( struct KUNIT_T *test, const char *struct_name, struct mock_struct_matcher_entry *entries); /** * struct mock_param_capturer - used to capture parameter when matching * * Use the associated helper macros to access relevant fields. * Example: * * .. code-block::c * * static int some_test(struct KUNIT_T *test) * { * // imagine a mocked function: int add(int a, int b) * struct mock_param_capturer *capturer = * mock_int_capturer_create(test, any(test)); * EXPECT_CALL(add(any(test), capturer_to_matcher(capturer))); * ASSERT_PARAM_CAPTURED(test, capturer); * * int captured_value = mock_capturer_get(capturer, int); * } */ struct mock_param_capturer { /* private: internal use only. */ struct mock_param_matcher matcher; struct mock_param_matcher *child_matcher; void *(*capture_param)(struct KUNIT_T *test, const void *param); void *captured_param; }; struct mock_param_capturer *mock_param_capturer_create( struct KUNIT_T *test, struct mock_param_matcher *child_matcher, void *(*capture_param)(struct KUNIT_T *, const void *)); /** * mock_int_capturer_create() - creates a int parameter capturer * @test: associated test * @child_matcher: matcher used to match the integer * * The capturer will capture the value if the matcher is satisfied. */ struct mock_param_capturer *mock_int_capturer_create( struct KUNIT_T *test, struct mock_param_matcher *child_matcher); /** * mock_int_capturer_create() - creates a generic pointer parameter capturer * @test: associated test * @child_matcher: matcher used to match the pointer * * The capturer will capture the value if the matcher is satisfied */ struct mock_param_capturer *mock_ptr_capturer_create( struct KUNIT_T *test, struct mock_param_matcher *child_matcher); /** * capturer_to_matcher() * @capturer: the param capturer * * Use this function when passing a capturer into an EXPECT_CALL() where a * matcher would be expected. See the example for &struct mock_param_capturer. */ #define capturer_to_matcher(capturer) (&(capturer)->matcher) /** * ASSERT_PARAM_CAPTURED(): Asserts that the capturer has captured a parameter. * @test: the associated test * @capturer: the param capturer * * See &struct mock_param_capturer for an example. */ #define ASSERT_PARAM_CAPTURED(test, capturer) \ __ASSERT(test, \ !IS_ERR_OR_NULL((capturer)->captured_param), \ "Asserted " #capturer " captured param, but did not.") /** * mock_capturer_get(): Returns the value captured by ``capturer`` * @capturer: the param capturer * @type: the type of the value * * See &struct mock_param_capturer for an example. */ #define mock_capturer_get(capturer, type) \ CONVERT_TO_ACTUAL_TYPE(type, (capturer)->captured_param) struct mock_action *invoke(struct KUNIT_T *test, void *(*invokable)(struct KUNIT_T *, const void *params[], int len)); /** * INVOKE_REAL() * @test: associated test * @func_name: name of the function * * See DEFINE_REDIRECT_MOCKABLE() for an example. * * Return: &struct mock_action that makes the associated mock method or function * call the original function definition of a redirect-mockable * function. */ #define INVOKE_REAL(test, func_name) invoke(test, INVOKE_ID(func_name)) struct mock_struct_formatter_entry { size_t member_offset; struct mock_param_formatter *formatter; }; static inline void init_mock_struct_formatter_entry_internal( struct mock_struct_formatter_entry *entry, size_t offset, struct mock_param_formatter *formatter) { entry->member_offset = offset; entry->formatter = formatter; } #define INIT_MOCK_STRUCT_FORMATTER_ENTRY(entry, type, member, formatter) \ init_mock_struct_formatter_entry_internal(entry, \ offsetof(type, \ member), \ formatter) static inline void INIT_MOCK_STRUCT_FORMATTER_ENTRY_LAST( struct mock_struct_formatter_entry *entry) { entry->formatter = NULL; } struct mock_param_formatter *mock_struct_formatter( struct KUNIT_T *test, const char *struct_name, struct mock_struct_formatter_entry *entries); struct mock_param_formatter *mock_find_formatter(const char *type_name); #define FORMATTER_FROM_TYPE(type) mock_find_formatter(#type) extern struct mock_param_formatter unknown_formatter[]; #endif /* _TEST_MOCK_H */