1489 lines
49 KiB
C
1489 lines
49 KiB
C
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
/*
|
||
|
* Mocking API for KUnit.
|
||
|
*
|
||
|
* Copyright (C) 2018, Google LLC.
|
||
|
* Author: Brendan Higgins <brendanhiggins@google.com>
|
||
|
*/
|
||
|
|
||
|
#ifndef _TEST_MOCK_H
|
||
|
#define _TEST_MOCK_H
|
||
|
|
||
|
#include <linux/types.h>
|
||
|
#include <linux/tracepoint.h> /* For PARAMS(...) */
|
||
|
#include <test/test.h>
|
||
|
#include <test/test-stream.h>
|
||
|
#include <test/params.h>
|
||
|
|
||
|
/**
|
||
|
* 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 */
|