diff options
Diffstat (limited to 'include/kunit/test.h')
| -rw-r--r-- | include/kunit/test.h | 1823 |
1 files changed, 863 insertions, 960 deletions
diff --git a/include/kunit/test.h b/include/kunit/test.h index b26400731c02..5ec5182b5e57 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -12,9 +12,12 @@ #include <kunit/assert.h> #include <kunit/try-catch.h> +#include <linux/args.h> +#include <linux/compiler.h> #include <linux/container_of.h> #include <linux/err.h> #include <linux/init.h> +#include <linux/jump_label.h> #include <linux/kconfig.h> #include <linux/kref.h> #include <linux/list.h> @@ -25,83 +28,13 @@ #include <linux/types.h> #include <asm/rwonce.h> +#include <asm/sections.h> -struct kunit_resource; - -typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *); -typedef void (*kunit_resource_free_t)(struct kunit_resource *); - -/** - * struct kunit_resource - represents a *test managed resource* - * @data: for the user to store arbitrary data. - * @name: optional name - * @free: a user supplied function to free the resource. Populated by - * kunit_resource_alloc(). - * - * Represents a *test managed resource*, a resource which will automatically be - * cleaned up at the end of a test case. - * - * Resources are reference counted so if a resource is retrieved via - * kunit_alloc_and_get_resource() or kunit_find_resource(), we need - * to call kunit_put_resource() to reduce the resource reference count - * when finished with it. Note that kunit_alloc_resource() does not require a - * kunit_resource_put() because it does not retrieve the resource itself. - * - * Example: - * - * .. code-block:: c - * - * struct kunit_kmalloc_params { - * size_t size; - * gfp_t gfp; - * }; - * - * static int kunit_kmalloc_init(struct kunit_resource *res, void *context) - * { - * struct kunit_kmalloc_params *params = context; - * res->data = kmalloc(params->size, params->gfp); - * - * if (!res->data) - * return -ENOMEM; - * - * return 0; - * } - * - * static void kunit_kmalloc_free(struct kunit_resource *res) - * { - * kfree(res->data); - * } - * - * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp) - * { - * struct kunit_kmalloc_params params; - * - * params.size = size; - * params.gfp = gfp; - * - * return kunit_alloc_resource(test, kunit_kmalloc_init, - * kunit_kmalloc_free, ¶ms); - * } - * - * Resources can also be named, with lookup/removal done on a name - * basis also. kunit_add_named_resource(), kunit_find_named_resource() - * and kunit_destroy_named_resource(). Resource names must be - * unique within the test instance. - */ -struct kunit_resource { - void *data; - const char *name; - kunit_resource_free_t free; - - /* private: internal use only. */ - struct kref refcount; - struct list_head node; -}; +/* Static key: true if any KUnit tests are currently running */ +DECLARE_STATIC_KEY_FALSE(kunit_running); struct kunit; - -/* Size of log associated with test. */ -#define KUNIT_LOG_SIZE 512 +struct string_stream; /* Maximum size of parameter description string. */ #define KUNIT_PARAM_DESC_SIZE 128 @@ -114,6 +47,7 @@ struct kunit; * sub-subtest. See the "Subtests" section in * https://node-tap.org/tap-protocol/ */ +#define KUNIT_INDENT_LEN 4 #define KUNIT_SUBTEST_INDENT " " #define KUNIT_SUBSUBTEST_INDENT " " @@ -129,12 +63,37 @@ enum kunit_status { KUNIT_SKIPPED, }; +/* Attribute struct/enum definitions */ + +/* + * Speed Attribute is stored as an enum and separated into categories of + * speed: very_slow, slow, and normal. These speeds are relative to + * other KUnit tests. + * + * Note: unset speed attribute acts as default of KUNIT_SPEED_NORMAL. + */ +enum kunit_speed { + KUNIT_SPEED_UNSET, + KUNIT_SPEED_VERY_SLOW, + KUNIT_SPEED_SLOW, + KUNIT_SPEED_NORMAL, + KUNIT_SPEED_MAX = KUNIT_SPEED_NORMAL, +}; + +/* Holds attributes for each test case and suite */ +struct kunit_attributes { + enum kunit_speed speed; +}; + /** * struct kunit_case - represents an individual test case. * * @run_case: the function representing the actual test case. * @name: the name of the test case. * @generate_params: the generator function for parameterized tests. + * @attr: the attributes associated with the test + * @param_init: The init function to run before a parameterized test. + * @param_exit: The exit function to run after a parameterized test. * * A test case is a function with the signature, * ``void (*)(struct kunit *)`` @@ -169,11 +128,16 @@ enum kunit_status { struct kunit_case { void (*run_case)(struct kunit *test); const char *name; - const void* (*generate_params)(const void *prev, char *desc); + const void* (*generate_params)(struct kunit *test, + const void *prev, char *desc); + struct kunit_attributes attr; + int (*param_init)(struct kunit *test); + void (*param_exit)(struct kunit *test); /* private: internal use only. */ enum kunit_status status; - char *log; + char *module_name; + struct string_stream *log; }; static inline char *kunit_status_to_ok_not_ok(enum kunit_status status) @@ -197,7 +161,32 @@ static inline char *kunit_status_to_ok_not_ok(enum kunit_status status) * &struct kunit_case object from it. See the documentation for * &struct kunit_case for an example on how to use it. */ -#define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name } +#define KUNIT_CASE(test_name) \ + { .run_case = test_name, .name = #test_name, \ + .module_name = KBUILD_MODNAME} + +/** + * KUNIT_CASE_ATTR - A helper for creating a &struct kunit_case + * with attributes + * + * @test_name: a reference to a test case function. + * @attributes: a reference to a struct kunit_attributes object containing + * test attributes + */ +#define KUNIT_CASE_ATTR(test_name, attributes) \ + { .run_case = test_name, .name = #test_name, \ + .attr = attributes, .module_name = KBUILD_MODNAME} + +/** + * KUNIT_CASE_SLOW - A helper for creating a &struct kunit_case + * with the slow attribute + * + * @test_name: a reference to a test case function. + */ + +#define KUNIT_CASE_SLOW(test_name) \ + { .run_case = test_name, .name = #test_name, \ + .attr.speed = KUNIT_SPEED_SLOW, .module_name = KBUILD_MODNAME} /** * KUNIT_CASE_PARAM - A helper for creation a parameterized &struct kunit_case @@ -218,34 +207,104 @@ static inline char *kunit_status_to_ok_not_ok(enum kunit_status status) */ #define KUNIT_CASE_PARAM(test_name, gen_params) \ { .run_case = test_name, .name = #test_name, \ - .generate_params = gen_params } + .generate_params = gen_params, .module_name = KBUILD_MODNAME} + +/** + * KUNIT_CASE_PARAM_ATTR - A helper for creating a parameterized &struct + * kunit_case with attributes + * + * @test_name: a reference to a test case function. + * @gen_params: a reference to a parameter generator function. + * @attributes: a reference to a struct kunit_attributes object containing + * test attributes + */ +#define KUNIT_CASE_PARAM_ATTR(test_name, gen_params, attributes) \ + { .run_case = test_name, .name = #test_name, \ + .generate_params = gen_params, \ + .attr = attributes, .module_name = KBUILD_MODNAME} + +/** + * KUNIT_CASE_PARAM_WITH_INIT - Define a parameterized KUnit test case with custom + * param_init() and param_exit() functions. + * @test_name: The function implementing the test case. + * @gen_params: The function to generate parameters for the test case. + * @init: A reference to the param_init() function to run before a parameterized test. + * @exit: A reference to the param_exit() function to run after a parameterized test. + * + * Provides the option to register param_init() and param_exit() functions. + * param_init/exit will be passed the parameterized test context and run once + * before and once after the parameterized test. The init function can be used + * to add resources to share between parameter runs, pass parameter arrays, + * and any other setup logic. The exit function can be used to clean up resources + * that were not managed by the parameterized test, and any other teardown logic. + * + * Note: If you are registering a parameter array in param_init() with + * kunit_register_param_array() then you need to pass kunit_array_gen_params() + * to this as the generator function. + */ +#define KUNIT_CASE_PARAM_WITH_INIT(test_name, gen_params, init, exit) \ + { .run_case = test_name, .name = #test_name, \ + .generate_params = gen_params, \ + .param_init = init, .param_exit = exit, \ + .module_name = KBUILD_MODNAME} /** * struct kunit_suite - describes a related collection of &struct kunit_case * * @name: the name of the test. Purely informational. + * @suite_init: called once per test suite before the test cases. + * @suite_exit: called once per test suite after all test cases. * @init: called before every test case. * @exit: called after every test case. * @test_cases: a null terminated array of test cases. + * @attr: the attributes associated with the test suite * * A kunit_suite is a collection of related &struct kunit_case s, such that * @init is called before every test case and @exit is called after every * test case, similar to the notion of a *test fixture* or a *test class* * in other unit testing frameworks like JUnit or Googletest. * + * Note that @exit and @suite_exit will run even if @init or @suite_init + * fail: make sure they can handle any inconsistent state which may result. + * * Every &struct kunit_case must be associated with a kunit_suite for KUnit * to run it. */ struct kunit_suite { const char name[256]; + int (*suite_init)(struct kunit_suite *suite); + void (*suite_exit)(struct kunit_suite *suite); int (*init)(struct kunit *test); void (*exit)(struct kunit *test); struct kunit_case *test_cases; + struct kunit_attributes attr; /* private: internal use only */ char status_comment[KUNIT_STATUS_COMMENT_SIZE]; struct dentry *debugfs; - char *log; + struct string_stream *log; + int suite_init_err; + bool is_init; +}; + +/* Stores an array of suites, end points one past the end */ +struct kunit_suite_set { + struct kunit_suite * const *start; + struct kunit_suite * const *end; +}; + +/* Stores the pointer to the parameter array and its metadata. */ +struct kunit_params { + /* + * Reference to the parameter array for a parameterized test. This + * is NULL if a parameter array wasn't directly passed to the + * parameterized test context struct kunit via kunit_register_params_array(). + */ + const void *params; + /* Reference to a function that gets the description of a parameter. */ + void (*get_description)(struct kunit *test, const void *param, char *desc); + size_t num_params; + size_t elem_size; }; /** @@ -253,18 +312,24 @@ struct kunit_suite { * * @priv: for user to store arbitrary data. Commonly used to pass data * created in the init function (see &struct kunit_suite). + * @parent: reference to the parent context of type struct kunit that can + * be used for storing shared resources. + * @params_array: for storing the parameter array. * * Used to store information about the current context under which the test * is running. Most of this data is private and should only be accessed - * indirectly via public functions; the one exception is @priv which can be - * used by the test writer to store arbitrary data. + * indirectly via public functions; the exceptions are @priv, @parent and + * @params_array which can be used by the test writer to store arbitrary data, + * access the parent context, and to store the parameter array, respectively. */ struct kunit { void *priv; + struct kunit *parent; + struct kunit_params params_array; /* private: internal use only. */ const char *name; /* Read only after initialization! */ - char *log; /* Points at case log after initialization */ + struct string_stream *log; /* Points at case log after initialization */ struct kunit_try_catch try_catch; /* param_value is the current parameter value for a test case. */ const void *param_value; @@ -287,6 +352,8 @@ struct kunit { struct list_head resources; /* Protected by lock. */ char status_comment[KUNIT_STATUS_COMMENT_SIZE]; + /* Saves the last seen test. Useful to help with faults. */ + struct kunit_loc last_seen; }; static inline void kunit_set_failure(struct kunit *test) @@ -294,7 +361,14 @@ static inline void kunit_set_failure(struct kunit *test) WRITE_ONCE(test->status, KUNIT_FAILURE); } -void kunit_init_test(struct kunit *test, const char *name, char *log); +bool kunit_enabled(void); +bool kunit_autorun(void); +const char *kunit_action(void); +const char *kunit_filter_glob(void); +char *kunit_filter(void); +char *kunit_filter_action(void); + +void kunit_init_test(struct kunit *test, const char *name, struct string_stream *log); int kunit_run_tests(struct kunit_suite *suite); @@ -303,9 +377,26 @@ size_t kunit_suite_num_test_cases(struct kunit_suite *suite); unsigned int kunit_test_case_num(struct kunit_suite *suite, struct kunit_case *test_case); -int __kunit_test_suites_init(struct kunit_suite * const * const suites); +struct kunit_suite_set +kunit_filter_suites(const struct kunit_suite_set *suite_set, + const char *filter_glob, + char *filters, + char *filter_action, + int *err); +void kunit_free_suite_set(struct kunit_suite_set suite_set); + +int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_suites, + bool run_tests); + +void __kunit_test_suites_exit(struct kunit_suite **suites, int num_suites); + +void kunit_exec_run_tests(struct kunit_suite_set *suite_set, bool builtin); +void kunit_exec_list_tests(struct kunit_suite_set *suite_set, bool include_attr); -void __kunit_test_suites_exit(struct kunit_suite **suites); +struct kunit_suite_set kunit_merge_suite_sets(struct kunit_suite_set init_suite_set, + struct kunit_suite_set suite_set); + +const void *kunit_array_gen_params(struct kunit *test, const void *prev, char *desc); #if IS_BUILTIN(CONFIG_KUNIT) int kunit_run_all_tests(void); @@ -316,43 +407,10 @@ static inline int kunit_run_all_tests(void) } #endif /* IS_BUILTIN(CONFIG_KUNIT) */ -#ifdef MODULE -/** - * kunit_test_suites_for_module() - used to register one or more - * &struct kunit_suite with KUnit. - * - * @__suites: a statically allocated list of &struct kunit_suite. - * - * Registers @__suites with the test framework. See &struct kunit_suite for - * more information. - * - * If a test suite is built-in, module_init() gets translated into - * an initcall which we don't want as the idea is that for builtins - * the executor will manage execution. So ensure we do not define - * module_{init|exit} functions for the builtin case when registering - * suites via kunit_test_suites() below. - */ -#define kunit_test_suites_for_module(__suites) \ - static int __init kunit_test_suites_init(void) \ - { \ - return __kunit_test_suites_init(__suites); \ - } \ - module_init(kunit_test_suites_init); \ - \ - static void __exit kunit_test_suites_exit(void) \ - { \ - return __kunit_test_suites_exit(__suites); \ - } \ - module_exit(kunit_test_suites_exit) -#else -#define kunit_test_suites_for_module(__suites) -#endif /* MODULE */ - -#define __kunit_test_suites(unique_array, unique_suites, ...) \ - static struct kunit_suite *unique_array[] = { __VA_ARGS__, NULL }; \ - kunit_test_suites_for_module(unique_array); \ - static struct kunit_suite **unique_suites \ - __used __section(".kunit_test_suites") = unique_array +#define __kunit_test_suites(unique_array, ...) \ + static struct kunit_suite *unique_array[] \ + __aligned(sizeof(struct kunit_suite *)) \ + __used __section(".kunit_test_suites") = { __VA_ARGS__ } /** * kunit_test_suites() - used to register one or more &struct kunit_suite @@ -360,256 +418,56 @@ static inline int kunit_run_all_tests(void) * * @__suites: a statically allocated list of &struct kunit_suite. * - * Registers @suites with the test framework. See &struct kunit_suite for - * more information. - * - * When builtin, KUnit tests are all run via executor; this is done - * by placing the array of struct kunit_suite * in the .kunit_test_suites - * ELF section. + * Registers @suites with the test framework. + * This is done by placing the array of struct kunit_suite * in the + * .kunit_test_suites ELF section. * - * An alternative is to build the tests as a module. Because modules do not - * support multiple initcall()s, we need to initialize an array of suites for a - * module. + * When builtin, KUnit tests are all run via the executor at boot, and when + * built as a module, they run on module load. * */ #define kunit_test_suites(__suites...) \ __kunit_test_suites(__UNIQUE_ID(array), \ - __UNIQUE_ID(suites), \ ##__suites) #define kunit_test_suite(suite) kunit_test_suites(&suite) -#define kunit_suite_for_each_test_case(suite, test_case) \ - for (test_case = suite->test_cases; test_case->run_case; test_case++) - -enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite); - -/* - * Like kunit_alloc_resource() below, but returns the struct kunit_resource - * object that contains the allocation. This is mostly for testing purposes. - */ -struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test, - kunit_resource_init_t init, - kunit_resource_free_t free, - gfp_t internal_gfp, - void *context); - -/** - * kunit_get_resource() - Hold resource for use. Should not need to be used - * by most users as we automatically get resources - * retrieved by kunit_find_resource*(). - * @res: resource - */ -static inline void kunit_get_resource(struct kunit_resource *res) -{ - kref_get(&res->refcount); -} - -/* - * Called when refcount reaches zero via kunit_put_resources(); - * should not be called directly. - */ -static inline void kunit_release_resource(struct kref *kref) -{ - struct kunit_resource *res = container_of(kref, struct kunit_resource, - refcount); - - /* If free function is defined, resource was dynamically allocated. */ - if (res->free) { - res->free(res); - kfree(res); - } -} - -/** - * kunit_put_resource() - When caller is done with retrieved resource, - * kunit_put_resource() should be called to drop - * reference count. The resource list maintains - * a reference count on resources, so if no users - * are utilizing a resource and it is removed from - * the resource list, it will be freed via the - * associated free function (if any). Only - * needs to be used if we alloc_and_get() or - * find() resource. - * @res: resource - */ -static inline void kunit_put_resource(struct kunit_resource *res) -{ - kref_put(&res->refcount, kunit_release_resource); -} - -/** - * kunit_add_resource() - Add a *test managed resource*. - * @test: The test context object. - * @init: a user-supplied function to initialize the result (if needed). If - * none is supplied, the resource data value is simply set to @data. - * If an init function is supplied, @data is passed to it instead. - * @free: a user-supplied function to free the resource (if needed). - * @res: The resource. - * @data: value to pass to init function or set in resource data field. - */ -int kunit_add_resource(struct kunit *test, - kunit_resource_init_t init, - kunit_resource_free_t free, - struct kunit_resource *res, - void *data); - -/** - * kunit_add_named_resource() - Add a named *test managed resource*. - * @test: The test context object. - * @init: a user-supplied function to initialize the resource data, if needed. - * @free: a user-supplied function to free the resource data, if needed. - * @res: The resource. - * @name: name to be set for resource. - * @data: value to pass to init function or set in resource data field. - */ -int kunit_add_named_resource(struct kunit *test, - kunit_resource_init_t init, - kunit_resource_free_t free, - struct kunit_resource *res, - const char *name, - void *data); - -/** - * kunit_alloc_resource() - Allocates a *test managed resource*. - * @test: The test context object. - * @init: a user supplied function to initialize the resource. - * @free: a user supplied function to free the resource. - * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL - * @context: for the user to pass in arbitrary data to the init function. - * - * Allocates a *test managed resource*, a resource which will automatically be - * cleaned up at the end of a test case. See &struct kunit_resource for an - * example. - * - * Note: KUnit needs to allocate memory for a kunit_resource object. You must - * specify an @internal_gfp that is compatible with the use context of your - * resource. - */ -static inline void *kunit_alloc_resource(struct kunit *test, - kunit_resource_init_t init, - kunit_resource_free_t free, - gfp_t internal_gfp, - void *context) -{ - struct kunit_resource *res; - - res = kzalloc(sizeof(*res), internal_gfp); - if (!res) - return NULL; - - if (!kunit_add_resource(test, init, free, res, context)) - return res->data; - - return NULL; -} - -typedef bool (*kunit_resource_match_t)(struct kunit *test, - struct kunit_resource *res, - void *match_data); +#define __kunit_init_test_suites(unique_array, ...) \ + static struct kunit_suite *unique_array[] \ + __aligned(sizeof(struct kunit_suite *)) \ + __used __section(".kunit_init_test_suites") = { __VA_ARGS__ } /** - * kunit_resource_instance_match() - Match a resource with the same instance. - * @test: Test case to which the resource belongs. - * @res: The resource. - * @match_data: The resource pointer to match against. + * kunit_test_init_section_suites() - used to register one or more &struct + * kunit_suite containing init functions or + * init data. * - * An instance of kunit_resource_match_t that matches a resource whose - * allocation matches @match_data. - */ -static inline bool kunit_resource_instance_match(struct kunit *test, - struct kunit_resource *res, - void *match_data) -{ - return res->data == match_data; -} - -/** - * kunit_resource_name_match() - Match a resource with the same name. - * @test: Test case to which the resource belongs. - * @res: The resource. - * @match_name: The name to match against. - */ -static inline bool kunit_resource_name_match(struct kunit *test, - struct kunit_resource *res, - void *match_name) -{ - return res->name && strcmp(res->name, match_name) == 0; -} - -/** - * kunit_find_resource() - Find a resource using match function/data. - * @test: Test case to which the resource belongs. - * @match: match function to be applied to resources/match data. - * @match_data: data to be used in matching. - */ -static inline struct kunit_resource * -kunit_find_resource(struct kunit *test, - kunit_resource_match_t match, - void *match_data) -{ - struct kunit_resource *res, *found = NULL; - unsigned long flags; - - spin_lock_irqsave(&test->lock, flags); - - list_for_each_entry_reverse(res, &test->resources, node) { - if (match(test, res, (void *)match_data)) { - found = res; - kunit_get_resource(found); - break; - } - } - - spin_unlock_irqrestore(&test->lock, flags); - - return found; -} - -/** - * kunit_find_named_resource() - Find a resource using match name. - * @test: Test case to which the resource belongs. - * @name: match name. - */ -static inline struct kunit_resource * -kunit_find_named_resource(struct kunit *test, - const char *name) -{ - return kunit_find_resource(test, kunit_resource_name_match, - (void *)name); -} - -/** - * kunit_destroy_resource() - Find a kunit_resource and destroy it. - * @test: Test case to which the resource belongs. - * @match: Match function. Returns whether a given resource matches @match_data. - * @match_data: Data passed into @match. + * @__suites: a statically allocated list of &struct kunit_suite. * - * RETURNS: - * 0 if kunit_resource is found and freed, -ENOENT if not found. + * This functions similar to kunit_test_suites() except that it compiles the + * list of suites during init phase. + * + * This macro also suffixes the array and suite declarations it makes with + * _probe; so that modpost suppresses warnings about referencing init data + * for symbols named in this manner. + * + * Note: these init tests are not able to be run after boot so there is no + * "run" debugfs file generated for these tests. + * + * Also, do not mark the suite or test case structs with __initdata because + * they will be used after the init phase with debugfs. */ -int kunit_destroy_resource(struct kunit *test, - kunit_resource_match_t match, - void *match_data); +#define kunit_test_init_section_suites(__suites...) \ + __kunit_init_test_suites(CONCATENATE(__UNIQUE_ID(array), _probe), \ + ##__suites) -static inline int kunit_destroy_named_resource(struct kunit *test, - const char *name) -{ - return kunit_destroy_resource(test, kunit_resource_name_match, - (void *)name); -} +#define kunit_test_init_section_suite(suite) \ + kunit_test_init_section_suites(&suite) -/** - * kunit_remove_resource() - remove resource from resource list associated with - * test. - * @test: The test context object. - * @res: The resource to be removed. - * - * Note that the resource will not be immediately freed since it is likely - * the caller has a reference to it via alloc_and_get() or find(); - * in this case a final call to kunit_put_resource() is required. - */ -void kunit_remove_resource(struct kunit *test, struct kunit_resource *res); +#define kunit_suite_for_each_test_case(suite, test_case) \ + for (test_case = suite->test_cases; test_case->run_case; test_case++) + +enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite); /** * kunit_kmalloc_array() - Like kmalloc_array() except the allocation is *test managed*. @@ -619,8 +477,11 @@ void kunit_remove_resource(struct kunit *test, struct kunit_resource *res); * @gfp: flags passed to underlying kmalloc(). * * Just like `kmalloc_array(...)`, except the allocation is managed by the test case - * and is automatically cleaned up after the test case concludes. See &struct - * kunit_resource for more information. + * and is automatically cleaned up after the test case concludes. See kunit_add_action() + * for more information. + * + * Note that some internal context data is also allocated with GFP_KERNEL, + * regardless of the gfp passed in. */ void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp); @@ -631,6 +492,9 @@ void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp); * @gfp: flags passed to underlying kmalloc(). * * See kmalloc() and kunit_kmalloc_array() for more information. + * + * Note that some internal context data is also allocated with GFP_KERNEL, + * regardless of the gfp passed in. */ static inline void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp) { @@ -671,14 +535,91 @@ static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp return kunit_kmalloc_array(test, n, size, gfp | __GFP_ZERO); } + +/** + * kunit_kfree_const() - conditionally free test managed memory + * @test: The test context object. + * @x: pointer to the memory + * + * Calls kunit_kfree() only if @x is not in .rodata section. + * See kunit_kstrdup_const() for more information. + */ +void kunit_kfree_const(struct kunit *test, const void *x); + +/** + * kunit_kstrdup() - Duplicates a string into a test managed allocation. + * + * @test: The test context object. + * @str: The NULL-terminated string to duplicate. + * @gfp: flags passed to underlying kmalloc(). + * + * See kstrdup() and kunit_kmalloc_array() for more information. + */ +static inline char *kunit_kstrdup(struct kunit *test, const char *str, gfp_t gfp) +{ + size_t len; + char *buf; + + if (!str) + return NULL; + + len = strlen(str) + 1; + buf = kunit_kmalloc(test, len, gfp); + if (buf) + memcpy(buf, str, len); + return buf; +} + +/** + * kunit_kstrdup_const() - Conditionally duplicates a string into a test managed allocation. + * + * @test: The test context object. + * @str: The NULL-terminated string to duplicate. + * @gfp: flags passed to underlying kmalloc(). + * + * Calls kunit_kstrdup() only if @str is not in the rodata section. Must be freed with + * kunit_kfree_const() -- not kunit_kfree(). + * See kstrdup_const() and kunit_kmalloc_array() for more information. + */ +const char *kunit_kstrdup_const(struct kunit *test, const char *str, gfp_t gfp); + +/** + * kunit_attach_mm() - Create and attach a new mm if it doesn't already exist. + * + * Allocates a &struct mm_struct and attaches it to @current. In most cases, call + * kunit_vm_mmap() without calling kunit_attach_mm() directly. Only necessary when + * code under test accesses the mm before executing the mmap (e.g., to perform + * additional initialization beforehand). + * + * Return: 0 on success, -errno on failure. + */ +int kunit_attach_mm(void); + +/** + * kunit_vm_mmap() - Allocate KUnit-tracked vm_mmap() area + * @test: The test context object. + * @file: struct file pointer to map from, if any + * @addr: desired address, if any + * @len: how many bytes to allocate + * @prot: mmap PROT_* bits + * @flag: mmap flags + * @offset: offset into @file to start mapping from. + * + * See vm_mmap() for more information. + */ +unsigned long kunit_vm_mmap(struct kunit *test, struct file *file, + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flag, + unsigned long offset); + void kunit_cleanup(struct kunit *test); -void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); +void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt, ...); /** - * kunit_mark_skipped() - Marks @test_or_suite as skipped + * kunit_mark_skipped() - Marks @test as skipped * - * @test_or_suite: The test context object. + * @test: The test context object. * @fmt: A printk() style format string. * * Marks the test as skipped. @fmt is given output as the test status @@ -686,18 +627,18 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); * * Test execution continues after kunit_mark_skipped() is called. */ -#define kunit_mark_skipped(test_or_suite, fmt, ...) \ +#define kunit_mark_skipped(test, fmt, ...) \ do { \ - WRITE_ONCE((test_or_suite)->status, KUNIT_SKIPPED); \ - scnprintf((test_or_suite)->status_comment, \ + WRITE_ONCE((test)->status, KUNIT_SKIPPED); \ + scnprintf((test)->status_comment, \ KUNIT_STATUS_COMMENT_SIZE, \ fmt, ##__VA_ARGS__); \ } while (0) /** - * kunit_skip() - Marks @test_or_suite as skipped + * kunit_skip() - Marks @test as skipped * - * @test_or_suite: The test context object. + * @test: The test context object. * @fmt: A printk() style format string. * * Skips the test. @fmt is given output as the test status @@ -705,10 +646,10 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); * * Test execution is halted after kunit_skip() is called. */ -#define kunit_skip(test_or_suite, fmt, ...) \ +#define kunit_skip(test, fmt, ...) \ do { \ - kunit_mark_skipped((test_or_suite), fmt, ##__VA_ARGS__);\ - kunit_try_catch_throw(&((test_or_suite)->try_catch)); \ + kunit_mark_skipped((test), fmt, ##__VA_ARGS__); \ + kunit_try_catch_throw(&((test)->try_catch)); \ } while (0) /* @@ -718,7 +659,7 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); #define kunit_log(lvl, test_or_suite, fmt, ...) \ do { \ printk(lvl fmt, ##__VA_ARGS__); \ - kunit_log_append((test_or_suite)->log, fmt "\n", \ + kunit_log_append((test_or_suite)->log, fmt, \ ##__VA_ARGS__); \ } while (0) @@ -760,6 +701,15 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); #define kunit_err(test, fmt, ...) \ kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__) +/* + * Must be called at the beginning of each KUNIT_*_ASSERTION(). + * Cf. KUNIT_CURRENT_LOC. + */ +#define _KUNIT_SAVE_LOC(test) do { \ + WRITE_ONCE(test->last_seen.file, __FILE__); \ + WRITE_ONCE(test->last_seen.line, __LINE__); \ +} while (0) + /** * KUNIT_SUCCEED() - A no-op expectation. Only exists for code clarity. * @test: The test context object. @@ -768,30 +718,42 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); * words, it does nothing and only exists for code clarity. See * KUNIT_EXPECT_TRUE() for more information. */ -#define KUNIT_SUCCEED(test) do {} while (0) +#define KUNIT_SUCCEED(test) _KUNIT_SAVE_LOC(test) + +void __noreturn __kunit_abort(struct kunit *test); -void kunit_do_assertion(struct kunit *test, - struct kunit_assert *assert, - bool pass, - const char *fmt, ...); +void __printf(6, 7) __kunit_do_failed_assertion(struct kunit *test, + const struct kunit_loc *loc, + enum kunit_assert_type type, + const struct kunit_assert *assert, + assert_format_t assert_format, + const char *fmt, ...); -#define KUNIT_ASSERTION(test, pass, assert_class, INITIALIZER, fmt, ...) do { \ - struct assert_class __assertion = INITIALIZER; \ - kunit_do_assertion(test, \ - &__assertion.assert, \ - pass, \ - fmt, \ - ##__VA_ARGS__); \ +#define _KUNIT_FAILED(test, assert_type, assert_class, assert_format, INITIALIZER, fmt, ...) do { \ + static const struct kunit_loc __loc = KUNIT_CURRENT_LOC; \ + const struct assert_class __assertion = INITIALIZER; \ + __kunit_do_failed_assertion(test, \ + &__loc, \ + assert_type, \ + &__assertion.assert, \ + assert_format, \ + fmt, \ + ##__VA_ARGS__); \ + if (assert_type == KUNIT_ASSERTION) \ + __kunit_abort(test); \ } while (0) -#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) \ - KUNIT_ASSERTION(test, \ - false, \ - kunit_fail_assert, \ - KUNIT_INIT_FAIL_ASSERT_STRUCT(test, assert_type), \ - fmt, \ - ##__VA_ARGS__) +#define KUNIT_FAIL_ASSERTION(test, assert_type, fmt, ...) do { \ + _KUNIT_SAVE_LOC(test); \ + _KUNIT_FAILED(test, \ + assert_type, \ + kunit_fail_assert, \ + kunit_fail_assert_format, \ + {}, \ + fmt, \ + ##__VA_ARGS__); \ +} while (0) /** * KUNIT_FAIL() - Always causes a test to fail when evaluated. @@ -810,21 +772,29 @@ void kunit_do_assertion(struct kunit *test, fmt, \ ##__VA_ARGS__) +/* Helper to safely pass around an initializer list to other macros. */ +#define KUNIT_INIT_ASSERT(initializers...) { initializers } + #define KUNIT_UNARY_ASSERTION(test, \ assert_type, \ - condition, \ - expected_true, \ + condition_, \ + expected_true_, \ fmt, \ ...) \ - KUNIT_ASSERTION(test, \ - !!(condition) == !!expected_true, \ - kunit_unary_assert, \ - KUNIT_INIT_UNARY_ASSERT_STRUCT(test, \ - assert_type, \ - #condition, \ - expected_true), \ - fmt, \ - ##__VA_ARGS__) +do { \ + _KUNIT_SAVE_LOC(test); \ + if (likely(!!(condition_) == !!expected_true_)) \ + break; \ + \ + _KUNIT_FAILED(test, \ + assert_type, \ + kunit_unary_assert, \ + kunit_unary_assert_format, \ + KUNIT_INIT_ASSERT(.condition = #condition_, \ + .expected_true = expected_true_), \ + fmt, \ + ##__VA_ARGS__); \ +} while (0) #define KUNIT_TRUE_MSG_ASSERTION(test, assert_type, condition, fmt, ...) \ KUNIT_UNARY_ASSERTION(test, \ @@ -834,9 +804,6 @@ void kunit_do_assertion(struct kunit *test, fmt, \ ##__VA_ARGS__) -#define KUNIT_TRUE_ASSERTION(test, assert_type, condition) \ - KUNIT_TRUE_MSG_ASSERTION(test, assert_type, condition, NULL) - #define KUNIT_FALSE_MSG_ASSERTION(test, assert_type, condition, fmt, ...) \ KUNIT_UNARY_ASSERTION(test, \ assert_type, \ @@ -845,9 +812,6 @@ void kunit_do_assertion(struct kunit *test, fmt, \ ##__VA_ARGS__) -#define KUNIT_FALSE_ASSERTION(test, assert_type, condition) \ - KUNIT_FALSE_MSG_ASSERTION(test, assert_type, condition, NULL) - /* * A factory macro for defining the assertions and expectations for the basic * comparisons defined for the built in types. @@ -864,7 +828,7 @@ void kunit_do_assertion(struct kunit *test, */ #define KUNIT_BASE_BINARY_ASSERTION(test, \ assert_class, \ - ASSERT_CLASS_INIT, \ + format_func, \ assert_type, \ left, \ op, \ @@ -872,353 +836,59 @@ void kunit_do_assertion(struct kunit *test, fmt, \ ...) \ do { \ - typeof(left) __left = (left); \ - typeof(right) __right = (right); \ + const typeof(left) __left = (left); \ + const typeof(right) __right = (right); \ + static const struct kunit_binary_assert_text __text = { \ + .operation = #op, \ + .left_text = #left, \ + .right_text = #right, \ + }; \ + \ + _KUNIT_SAVE_LOC(test); \ + if (likely(__left op __right)) \ + break; \ \ - KUNIT_ASSERTION(test, \ - __left op __right, \ - assert_class, \ - ASSERT_CLASS_INIT(test, \ - assert_type, \ - #op, \ - #left, \ - __left, \ - #right, \ - __right), \ - fmt, \ - ##__VA_ARGS__); \ + _KUNIT_FAILED(test, \ + assert_type, \ + assert_class, \ + format_func, \ + KUNIT_INIT_ASSERT(.text = &__text, \ + .left_value = __left, \ + .right_value = __right), \ + fmt, \ + ##__VA_ARGS__); \ } while (0) -#define KUNIT_BASE_EQ_MSG_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_BINARY_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, ==, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BASE_NE_MSG_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_BINARY_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, !=, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BASE_LT_MSG_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_BINARY_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, <, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BASE_LE_MSG_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_BINARY_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, <=, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BASE_GT_MSG_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, \ - right, \ - fmt, \ +#define KUNIT_BINARY_INT_ASSERTION(test, \ + assert_type, \ + left, \ + op, \ + right, \ + fmt, \ ...) \ KUNIT_BASE_BINARY_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ + kunit_binary_assert, \ + kunit_binary_assert_format, \ assert_type, \ - left, >, right, \ + left, op, right, \ fmt, \ ##__VA_ARGS__) -#define KUNIT_BASE_GE_MSG_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, \ - right, \ - fmt, \ +#define KUNIT_BINARY_PTR_ASSERTION(test, \ + assert_type, \ + left, \ + op, \ + right, \ + fmt, \ ...) \ KUNIT_BASE_BINARY_ASSERTION(test, \ - assert_class, \ - ASSERT_CLASS_INIT, \ - assert_type, \ - left, >=, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_EQ_MSG_ASSERTION(test, assert_type, left, right, fmt, ...)\ - KUNIT_BASE_EQ_MSG_ASSERTION(test, \ - kunit_binary_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_EQ_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_EQ_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_PTR_EQ_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_EQ_MSG_ASSERTION(test, \ - kunit_binary_ptr_assert, \ - KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_PTR_EQ_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_PTR_EQ_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_NE_MSG_ASSERTION(test, assert_type, left, right, fmt, ...)\ - KUNIT_BASE_NE_MSG_ASSERTION(test, \ - kunit_binary_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_NE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_NE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_PTR_NE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_NE_MSG_ASSERTION(test, \ - kunit_binary_ptr_assert, \ - KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_PTR_NE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_PTR_NE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_LT_MSG_ASSERTION(test, assert_type, left, right, fmt, ...)\ - KUNIT_BASE_LT_MSG_ASSERTION(test, \ - kunit_binary_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_LT_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_LT_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_PTR_LT_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_LT_MSG_ASSERTION(test, \ - kunit_binary_ptr_assert, \ - KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_PTR_LT_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_PTR_LT_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_LE_MSG_ASSERTION(test, assert_type, left, right, fmt, ...)\ - KUNIT_BASE_LE_MSG_ASSERTION(test, \ - kunit_binary_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_LE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_LE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_PTR_LE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_LE_MSG_ASSERTION(test, \ - kunit_binary_ptr_assert, \ - KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_PTR_LE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_PTR_LE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_GT_MSG_ASSERTION(test, assert_type, left, right, fmt, ...)\ - KUNIT_BASE_GT_MSG_ASSERTION(test, \ - kunit_binary_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_GT_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_GT_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_PTR_GT_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_GT_MSG_ASSERTION(test, \ kunit_binary_ptr_assert, \ - KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT, \ + kunit_binary_ptr_assert_format, \ assert_type, \ - left, \ - right, \ + left, op, right, \ fmt, \ ##__VA_ARGS__) -#define KUNIT_BINARY_PTR_GT_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_PTR_GT_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_GE_MSG_ASSERTION(test, assert_type, left, right, fmt, ...)\ - KUNIT_BASE_GE_MSG_ASSERTION(test, \ - kunit_binary_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_GE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_GE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_PTR_GE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BASE_GE_MSG_ASSERTION(test, \ - kunit_binary_ptr_assert, \ - KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_PTR_GE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_PTR_GE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - #define KUNIT_BINARY_STR_ASSERTION(test, \ assert_type, \ left, \ @@ -1228,59 +898,63 @@ do { \ ...) \ do { \ const char *__left = (left); \ - const char *__right = (right); \ + const char *__right = (right); \ + static const struct kunit_binary_assert_text __text = { \ + .operation = #op, \ + .left_text = #left, \ + .right_text = #right, \ + }; \ + \ + _KUNIT_SAVE_LOC(test); \ + if (likely((__left) && (__right) && (strcmp(__left, __right) op 0))) \ + break; \ + \ \ - KUNIT_ASSERTION(test, \ - strcmp(__left, __right) op 0, \ - kunit_binary_str_assert, \ - KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \ - assert_type, \ - #op, \ - #left, \ - __left, \ - #right, \ - __right), \ - fmt, \ - ##__VA_ARGS__); \ + _KUNIT_FAILED(test, \ + assert_type, \ + kunit_binary_str_assert, \ + kunit_binary_str_assert_format, \ + KUNIT_INIT_ASSERT(.text = &__text, \ + .left_value = __left, \ + .right_value = __right), \ + fmt, \ + ##__VA_ARGS__); \ } while (0) -#define KUNIT_BINARY_STR_EQ_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BINARY_STR_ASSERTION(test, \ - assert_type, \ - left, ==, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_STR_EQ_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_STR_EQ_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) - -#define KUNIT_BINARY_STR_NE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - fmt, \ - ...) \ - KUNIT_BINARY_STR_ASSERTION(test, \ - assert_type, \ - left, !=, right, \ - fmt, \ - ##__VA_ARGS__) - -#define KUNIT_BINARY_STR_NE_ASSERTION(test, assert_type, left, right) \ - KUNIT_BINARY_STR_NE_MSG_ASSERTION(test, \ - assert_type, \ - left, \ - right, \ - NULL) +#define KUNIT_MEM_ASSERTION(test, \ + assert_type, \ + left, \ + op, \ + right, \ + size_, \ + fmt, \ + ...) \ +do { \ + const void *__left = (left); \ + const void *__right = (right); \ + const size_t __size = (size_); \ + static const struct kunit_binary_assert_text __text = { \ + .operation = #op, \ + .left_text = #left, \ + .right_text = #right, \ + }; \ + \ + _KUNIT_SAVE_LOC(test); \ + if (likely(__left && __right)) \ + if (likely(memcmp(__left, __right, __size) op 0)) \ + break; \ + \ + _KUNIT_FAILED(test, \ + assert_type, \ + kunit_mem_assert, \ + kunit_mem_assert_format, \ + KUNIT_INIT_ASSERT(.text = &__text, \ + .left_value = __left, \ + .right_value = __right, \ + .size = __size), \ + fmt, \ + ##__VA_ARGS__); \ +} while (0) #define KUNIT_PTR_NOT_ERR_OR_NULL_MSG_ASSERTION(test, \ assert_type, \ @@ -1288,25 +962,21 @@ do { \ fmt, \ ...) \ do { \ - typeof(ptr) __ptr = (ptr); \ + const typeof(ptr) __ptr = (ptr); \ \ - KUNIT_ASSERTION(test, \ - !IS_ERR_OR_NULL(__ptr), \ - kunit_ptr_not_err_assert, \ - KUNIT_INIT_PTR_NOT_ERR_STRUCT(test, \ - assert_type, \ - #ptr, \ - __ptr), \ - fmt, \ - ##__VA_ARGS__); \ + _KUNIT_SAVE_LOC(test); \ + if (!IS_ERR_OR_NULL(__ptr)) \ + break; \ + \ + _KUNIT_FAILED(test, \ + assert_type, \ + kunit_ptr_not_err_assert, \ + kunit_ptr_not_err_assert_format, \ + KUNIT_INIT_ASSERT(.text = #ptr, .value = __ptr), \ + fmt, \ + ##__VA_ARGS__); \ } while (0) -#define KUNIT_PTR_NOT_ERR_OR_NULL_ASSERTION(test, assert_type, ptr) \ - KUNIT_PTR_NOT_ERR_OR_NULL_MSG_ASSERTION(test, \ - assert_type, \ - ptr, \ - NULL) - /** * KUNIT_EXPECT_TRUE() - Causes a test failure when the expression is not true. * @test: The test context object. @@ -1319,7 +989,7 @@ do { \ * *expectation failure*. */ #define KUNIT_EXPECT_TRUE(test, condition) \ - KUNIT_TRUE_ASSERTION(test, KUNIT_EXPECTATION, condition) + KUNIT_EXPECT_TRUE_MSG(test, condition, NULL) #define KUNIT_EXPECT_TRUE_MSG(test, condition, fmt, ...) \ KUNIT_TRUE_MSG_ASSERTION(test, \ @@ -1338,7 +1008,7 @@ do { \ * KUNIT_EXPECT_TRUE() for more information. */ #define KUNIT_EXPECT_FALSE(test, condition) \ - KUNIT_FALSE_ASSERTION(test, KUNIT_EXPECTATION, condition) + KUNIT_EXPECT_FALSE_MSG(test, condition, NULL) #define KUNIT_EXPECT_FALSE_MSG(test, condition, fmt, ...) \ KUNIT_FALSE_MSG_ASSERTION(test, \ @@ -1359,15 +1029,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_EQ(test, left, right) \ - KUNIT_BINARY_EQ_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_EQ_MSG(test, left, right, NULL) #define KUNIT_EXPECT_EQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_EQ_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, ==, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_PTR_EQ() - Expects that pointers @left and @right are equal. @@ -1381,18 +1050,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_PTR_EQ(test, left, right) \ - KUNIT_BINARY_PTR_EQ_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right) + KUNIT_EXPECT_PTR_EQ_MSG(test, left, right, NULL) #define KUNIT_EXPECT_PTR_EQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_PTR_EQ_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, ==, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_NE() - An expectation that @left and @right are not equal. @@ -1406,15 +1071,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_NE(test, left, right) \ - KUNIT_BINARY_NE_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_NE_MSG(test, left, right, NULL) #define KUNIT_EXPECT_NE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_NE_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, !=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_PTR_NE() - Expects that pointers @left and @right are not equal. @@ -1428,18 +1092,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_PTR_NE(test, left, right) \ - KUNIT_BINARY_PTR_NE_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right) + KUNIT_EXPECT_PTR_NE_MSG(test, left, right, NULL) #define KUNIT_EXPECT_PTR_NE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_PTR_NE_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, !=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_LT() - An expectation that @left is less than @right. @@ -1453,15 +1113,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_LT(test, left, right) \ - KUNIT_BINARY_LT_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_LT_MSG(test, left, right, NULL) #define KUNIT_EXPECT_LT_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_LT_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, <, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_LE() - Expects that @left is less than or equal to @right. @@ -1475,15 +1134,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_LE(test, left, right) \ - KUNIT_BINARY_LE_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_LE_MSG(test, left, right, NULL) #define KUNIT_EXPECT_LE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_LE_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, <=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_GT() - An expectation that @left is greater than @right. @@ -1497,15 +1155,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_GT(test, left, right) \ - KUNIT_BINARY_GT_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_GT_MSG(test, left, right, NULL) #define KUNIT_EXPECT_GT_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_GT_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, >, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_GE() - Expects that @left is greater than or equal to @right. @@ -1519,15 +1176,14 @@ do { \ * more information. */ #define KUNIT_EXPECT_GE(test, left, right) \ - KUNIT_BINARY_GE_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_GE_MSG(test, left, right, NULL) #define KUNIT_EXPECT_GE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_GE_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, >=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_STREQ() - Expects that strings @left and @right are equal. @@ -1541,15 +1197,14 @@ do { \ * for more information. */ #define KUNIT_EXPECT_STREQ(test, left, right) \ - KUNIT_BINARY_STR_EQ_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_STREQ_MSG(test, left, right, NULL) #define KUNIT_EXPECT_STREQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_STR_EQ_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_STR_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, ==, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_STRNEQ() - Expects that strings @left and @right are not equal. @@ -1563,15 +1218,110 @@ do { \ * for more information. */ #define KUNIT_EXPECT_STRNEQ(test, left, right) \ - KUNIT_BINARY_STR_NE_ASSERTION(test, KUNIT_EXPECTATION, left, right) + KUNIT_EXPECT_STRNEQ_MSG(test, left, right, NULL) #define KUNIT_EXPECT_STRNEQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_STR_NE_MSG_ASSERTION(test, \ - KUNIT_EXPECTATION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_STR_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, !=, right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_EXPECT_MEMEQ() - Expects that the first @size bytes of @left and @right are equal. + * @test: The test context object. + * @left: An arbitrary expression that evaluates to the specified size. + * @right: An arbitrary expression that evaluates to the specified size. + * @size: Number of bytes compared. + * + * Sets an expectation that the values that @left and @right evaluate to are + * equal. This is semantically equivalent to + * KUNIT_EXPECT_TRUE(@test, !memcmp((@left), (@right), (@size))). See + * KUNIT_EXPECT_TRUE() for more information. + * + * Although this expectation works for any memory block, it is not recommended + * for comparing more structured data, such as structs. This expectation is + * recommended for comparing, for example, data arrays. + */ +#define KUNIT_EXPECT_MEMEQ(test, left, right, size) \ + KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, NULL) + +#define KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, fmt, ...) \ + KUNIT_MEM_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, ==, right, \ + size, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_EXPECT_MEMNEQ() - Expects that the first @size bytes of @left and @right are not equal. + * @test: The test context object. + * @left: An arbitrary expression that evaluates to the specified size. + * @right: An arbitrary expression that evaluates to the specified size. + * @size: Number of bytes compared. + * + * Sets an expectation that the values that @left and @right evaluate to are + * not equal. This is semantically equivalent to + * KUNIT_EXPECT_TRUE(@test, memcmp((@left), (@right), (@size))). See + * KUNIT_EXPECT_TRUE() for more information. + * + * Although this expectation works for any memory block, it is not recommended + * for comparing more structured data, such as structs. This expectation is + * recommended for comparing, for example, data arrays. + */ +#define KUNIT_EXPECT_MEMNEQ(test, left, right, size) \ + KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, NULL) + +#define KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, fmt, ...) \ + KUNIT_MEM_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + left, !=, right, \ + size, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_EXPECT_NULL() - Expects that @ptr is null. + * @test: The test context object. + * @ptr: an arbitrary pointer. + * + * Sets an expectation that the value that @ptr evaluates to is null. This is + * semantically equivalent to KUNIT_EXPECT_PTR_EQ(@test, ptr, NULL). + * See KUNIT_EXPECT_TRUE() for more information. + */ +#define KUNIT_EXPECT_NULL(test, ptr) \ + KUNIT_EXPECT_NULL_MSG(test, \ + ptr, \ + NULL) + +#define KUNIT_EXPECT_NULL_MSG(test, ptr, fmt, ...) \ + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + ptr, ==, NULL, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_EXPECT_NOT_NULL() - Expects that @ptr is not null. + * @test: The test context object. + * @ptr: an arbitrary pointer. + * + * Sets an expectation that the value that @ptr evaluates to is not null. This + * is semantically equivalent to KUNIT_EXPECT_PTR_NE(@test, ptr, NULL). + * See KUNIT_EXPECT_TRUE() for more information. + */ +#define KUNIT_EXPECT_NOT_NULL(test, ptr) \ + KUNIT_EXPECT_NOT_NULL_MSG(test, \ + ptr, \ + NULL) + +#define KUNIT_EXPECT_NOT_NULL_MSG(test, ptr, fmt, ...) \ + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_EXPECTATION, \ + ptr, !=, NULL, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_EXPECT_NOT_ERR_OR_NULL() - Expects that @ptr is not null and not err. @@ -1584,7 +1334,7 @@ do { \ * more information. */ #define KUNIT_EXPECT_NOT_ERR_OR_NULL(test, ptr) \ - KUNIT_PTR_NOT_ERR_OR_NULL_ASSERTION(test, KUNIT_EXPECTATION, ptr) + KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, ptr, NULL) #define KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, ptr, fmt, ...) \ KUNIT_PTR_NOT_ERR_OR_NULL_MSG_ASSERTION(test, \ @@ -1593,7 +1343,18 @@ do { \ fmt, \ ##__VA_ARGS__) -#define KUNIT_ASSERT_FAILURE(test, fmt, ...) \ +/** + * KUNIT_FAIL_AND_ABORT() - Always causes a test to fail and abort when evaluated. + * @test: The test context object. + * @fmt: an informational message to be printed when the assertion is made. + * @...: string format arguments. + * + * The opposite of KUNIT_SUCCEED(), it is an assertion that always fails. In + * other words, it always results in a failed assertion, and consequently + * always causes the test case to fail and abort when evaluated. + * See KUNIT_ASSERT_TRUE() for more information. + */ +#define KUNIT_FAIL_AND_ABORT(test, fmt, ...) \ KUNIT_FAIL_ASSERTION(test, KUNIT_ASSERTION, fmt, ##__VA_ARGS__) /** @@ -1608,7 +1369,7 @@ do { \ * this is otherwise known as an *assertion failure*. */ #define KUNIT_ASSERT_TRUE(test, condition) \ - KUNIT_TRUE_ASSERTION(test, KUNIT_ASSERTION, condition) + KUNIT_ASSERT_TRUE_MSG(test, condition, NULL) #define KUNIT_ASSERT_TRUE_MSG(test, condition, fmt, ...) \ KUNIT_TRUE_MSG_ASSERTION(test, \ @@ -1627,7 +1388,7 @@ do { \ * (see KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_FALSE(test, condition) \ - KUNIT_FALSE_ASSERTION(test, KUNIT_ASSERTION, condition) + KUNIT_ASSERT_FALSE_MSG(test, condition, NULL) #define KUNIT_ASSERT_FALSE_MSG(test, condition, fmt, ...) \ KUNIT_FALSE_MSG_ASSERTION(test, \ @@ -1647,15 +1408,14 @@ do { \ * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_EQ(test, left, right) \ - KUNIT_BINARY_EQ_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_EQ_MSG(test, left, right, NULL) #define KUNIT_ASSERT_EQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_EQ_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, ==, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_PTR_EQ() - Asserts that pointers @left and @right are equal. @@ -1668,15 +1428,14 @@ do { \ * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_PTR_EQ(test, left, right) \ - KUNIT_BINARY_PTR_EQ_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_PTR_EQ_MSG(test, left, right, NULL) #define KUNIT_ASSERT_PTR_EQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_PTR_EQ_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, ==, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_NE() - An assertion that @left and @right are not equal. @@ -1689,15 +1448,14 @@ do { \ * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_NE(test, left, right) \ - KUNIT_BINARY_NE_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_NE_MSG(test, left, right, NULL) #define KUNIT_ASSERT_NE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_NE_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, !=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_PTR_NE() - Asserts that pointers @left and @right are not equal. @@ -1711,15 +1469,14 @@ do { \ * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_PTR_NE(test, left, right) \ - KUNIT_BINARY_PTR_NE_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_PTR_NE_MSG(test, left, right, NULL) #define KUNIT_ASSERT_PTR_NE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_PTR_NE_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, !=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_LT() - An assertion that @left is less than @right. * @test: The test context object. @@ -1732,15 +1489,14 @@ do { \ * is not met. */ #define KUNIT_ASSERT_LT(test, left, right) \ - KUNIT_BINARY_LT_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_LT_MSG(test, left, right, NULL) #define KUNIT_ASSERT_LT_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_LT_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, <, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_LE() - An assertion that @left is less than or equal to @right. * @test: The test context object. @@ -1753,15 +1509,14 @@ do { \ * KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_LE(test, left, right) \ - KUNIT_BINARY_LE_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_LE_MSG(test, left, right, NULL) #define KUNIT_ASSERT_LE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_LE_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, <=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_GT() - An assertion that @left is greater than @right. @@ -1775,15 +1530,14 @@ do { \ * is not met. */ #define KUNIT_ASSERT_GT(test, left, right) \ - KUNIT_BINARY_GT_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_GT_MSG(test, left, right, NULL) #define KUNIT_ASSERT_GT_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_GT_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, >, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_GE() - Assertion that @left is greater than or equal to @right. @@ -1797,15 +1551,14 @@ do { \ * is not met. */ #define KUNIT_ASSERT_GE(test, left, right) \ - KUNIT_BINARY_GE_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_GE_MSG(test, left, right, NULL) #define KUNIT_ASSERT_GE_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_GE_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_INT_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, >=, right, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_STREQ() - An assertion that strings @left and @right are equal. @@ -1818,37 +1571,131 @@ do { \ * assertion failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_STREQ(test, left, right) \ - KUNIT_BINARY_STR_EQ_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_STREQ_MSG(test, left, right, NULL) #define KUNIT_ASSERT_STREQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_STR_EQ_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_STR_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, ==, right, \ + fmt, \ + ##__VA_ARGS__) /** - * KUNIT_ASSERT_STRNEQ() - Expects that strings @left and @right are not equal. + * KUNIT_ASSERT_STRNEQ() - An assertion that strings @left and @right are not equal. * @test: The test context object. * @left: an arbitrary expression that evaluates to a null terminated string. * @right: an arbitrary expression that evaluates to a null terminated string. * - * Sets an expectation that the values that @left and @right evaluate to are + * Sets an assertion that the values that @left and @right evaluate to are * not equal. This is semantically equivalent to * KUNIT_ASSERT_TRUE(@test, strcmp((@left), (@right))). See KUNIT_ASSERT_TRUE() * for more information. */ #define KUNIT_ASSERT_STRNEQ(test, left, right) \ - KUNIT_BINARY_STR_NE_ASSERTION(test, KUNIT_ASSERTION, left, right) + KUNIT_ASSERT_STRNEQ_MSG(test, left, right, NULL) #define KUNIT_ASSERT_STRNEQ_MSG(test, left, right, fmt, ...) \ - KUNIT_BINARY_STR_NE_MSG_ASSERTION(test, \ - KUNIT_ASSERTION, \ - left, \ - right, \ - fmt, \ - ##__VA_ARGS__) + KUNIT_BINARY_STR_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, !=, right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_MEMEQ() - Asserts that the first @size bytes of @left and @right are equal. + * @test: The test context object. + * @left: An arbitrary expression that evaluates to the specified size. + * @right: An arbitrary expression that evaluates to the specified size. + * @size: Number of bytes compared. + * + * Sets an assertion that the values that @left and @right evaluate to are + * equal. This is semantically equivalent to + * KUNIT_ASSERT_TRUE(@test, !memcmp((@left), (@right), (@size))). See + * KUNIT_ASSERT_TRUE() for more information. + * + * Although this assertion works for any memory block, it is not recommended + * for comparing more structured data, such as structs. This assertion is + * recommended for comparing, for example, data arrays. + */ +#define KUNIT_ASSERT_MEMEQ(test, left, right, size) \ + KUNIT_ASSERT_MEMEQ_MSG(test, left, right, size, NULL) + +#define KUNIT_ASSERT_MEMEQ_MSG(test, left, right, size, fmt, ...) \ + KUNIT_MEM_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, ==, right, \ + size, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_MEMNEQ() - Asserts that the first @size bytes of @left and @right are not equal. + * @test: The test context object. + * @left: An arbitrary expression that evaluates to the specified size. + * @right: An arbitrary expression that evaluates to the specified size. + * @size: Number of bytes compared. + * + * Sets an assertion that the values that @left and @right evaluate to are + * not equal. This is semantically equivalent to + * KUNIT_ASSERT_TRUE(@test, memcmp((@left), (@right), (@size))). See + * KUNIT_ASSERT_TRUE() for more information. + * + * Although this assertion works for any memory block, it is not recommended + * for comparing more structured data, such as structs. This assertion is + * recommended for comparing, for example, data arrays. + */ +#define KUNIT_ASSERT_MEMNEQ(test, left, right, size) \ + KUNIT_ASSERT_MEMNEQ_MSG(test, left, right, size, NULL) + +#define KUNIT_ASSERT_MEMNEQ_MSG(test, left, right, size, fmt, ...) \ + KUNIT_MEM_ASSERTION(test, \ + KUNIT_ASSERTION, \ + left, !=, right, \ + size, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_NULL() - Asserts that pointers @ptr is null. + * @test: The test context object. + * @ptr: an arbitrary pointer. + * + * Sets an assertion that the values that @ptr evaluates to is null. This is + * the same as KUNIT_EXPECT_NULL(), except it causes an assertion + * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_NULL(test, ptr) \ + KUNIT_ASSERT_NULL_MSG(test, \ + ptr, \ + NULL) + +#define KUNIT_ASSERT_NULL_MSG(test, ptr, fmt, ...) \ + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_ASSERTION, \ + ptr, ==, NULL, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_NOT_NULL() - Asserts that pointers @ptr is not null. + * @test: The test context object. + * @ptr: an arbitrary pointer. + * + * Sets an assertion that the values that @ptr evaluates to is not null. This + * is the same as KUNIT_EXPECT_NOT_NULL(), except it causes an assertion + * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_NOT_NULL(test, ptr) \ + KUNIT_ASSERT_NOT_NULL_MSG(test, \ + ptr, \ + NULL) + +#define KUNIT_ASSERT_NOT_NULL_MSG(test, ptr, fmt, ...) \ + KUNIT_BINARY_PTR_ASSERTION(test, \ + KUNIT_ASSERTION, \ + ptr, !=, NULL, \ + fmt, \ + ##__VA_ARGS__) /** * KUNIT_ASSERT_NOT_ERR_OR_NULL() - Assertion that @ptr is not null and not err. @@ -1861,7 +1708,7 @@ do { \ * KUNIT_ASSERT_TRUE()) when the assertion is not met. */ #define KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr) \ - KUNIT_PTR_NOT_ERR_OR_NULL_ASSERTION(test, KUNIT_ASSERTION, ptr) + KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, NULL) #define KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, fmt, ...) \ KUNIT_PTR_NOT_ERR_OR_NULL_MSG_ASSERTION(test, \ @@ -1879,9 +1726,12 @@ do { \ * Define function @name_gen_params which uses @array to generate parameters. */ #define KUNIT_ARRAY_PARAM(name, array, get_desc) \ - static const void *name##_gen_params(const void *prev, char *desc) \ + static const void *name##_gen_params(struct kunit *test, \ + const void *prev, char *desc) \ { \ typeof((array)[0]) *__next = prev ? ((typeof(__next)) prev) + 1 : (array); \ + if (!prev) \ + kunit_register_params_array(test, array, ARRAY_SIZE(array), NULL); \ if (__next - (array) < ARRAY_SIZE((array))) { \ void (*__get_desc)(typeof(__next), char *) = get_desc; \ if (__get_desc) \ @@ -1891,4 +1741,57 @@ do { \ return NULL; \ } +/** + * KUNIT_ARRAY_PARAM_DESC() - Define test parameter generator from an array. + * @name: prefix for the test parameter generator function. + * @array: array of test parameters. + * @desc_member: structure member from array element to use as description + * + * Define function @name_gen_params which uses @array to generate parameters. + */ +#define KUNIT_ARRAY_PARAM_DESC(name, array, desc_member) \ + static const void *name##_gen_params(struct kunit *test, \ + const void *prev, char *desc) \ + { \ + typeof((array)[0]) *__next = prev ? ((typeof(__next)) prev) + 1 : (array); \ + if (!prev) \ + kunit_register_params_array(test, array, ARRAY_SIZE(array), NULL); \ + if (__next - (array) < ARRAY_SIZE((array))) { \ + strscpy(desc, __next->desc_member, KUNIT_PARAM_DESC_SIZE); \ + return __next; \ + } \ + return NULL; \ + } + +/** + * kunit_register_params_array() - Register parameter array for a KUnit test. + * @test: The KUnit test structure to which parameters will be added. + * @array: An array of test parameters. + * @param_count: Number of parameters. + * @get_desc: Function that generates a string description for a given parameter + * element. + * + * This macro initializes the @test's parameter array data, storing information + * including the parameter array, its count, the element size, and the parameter + * description function within `test->params_array`. + * + * Note: If using this macro in param_init(), kunit_array_gen_params() + * will then need to be manually provided as the parameter generator function to + * KUNIT_CASE_PARAM_WITH_INIT(). kunit_array_gen_params() is a KUnit + * function that uses the registered array to generate parameters + */ +#define kunit_register_params_array(test, array, param_count, get_desc) \ + do { \ + struct kunit *_test = (test); \ + const typeof((array)[0]) * _params_ptr = &(array)[0]; \ + _test->params_array.params = _params_ptr; \ + _test->params_array.num_params = (param_count); \ + _test->params_array.elem_size = sizeof(*_params_ptr); \ + _test->params_array.get_description = (get_desc); \ + } while (0) + +// TODO(dlatypov@google.com): consider eventually migrating users to explicitly +// include resource.h themselves if they need it. +#include <kunit/resource.h> + #endif /* _KUNIT_TEST_H */ |
