Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Assertion and expectation serialization API.
*
* Copyright (C) 2019, Google LLC.
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
#ifndef _KUNIT_ASSERT_H
#define _KUNIT_ASSERT_H
#include <linux/err.h>
#include <linux/printk.h>
struct kunit;
struct string_stream;
/**
* enum kunit_assert_type - Type of expectation/assertion.
* @KUNIT_ASSERTION: Used to denote that a kunit_assert represents an assertion.
* @KUNIT_EXPECTATION: Denotes that a kunit_assert represents an expectation.
*
* Used in conjunction with a &struct kunit_assert to denote whether it
* represents an expectation or an assertion.
*/
enum kunit_assert_type {
KUNIT_ASSERTION,
KUNIT_EXPECTATION,
};
/**
* struct kunit_loc - Identifies the source location of a line of code.
* @line: the line number in the file.
* @file: the file name.
*/
struct kunit_loc {
int line;
const char *file;
};
#define KUNIT_CURRENT_LOC { .file = __FILE__, .line = __LINE__ }
/**
* struct kunit_assert - Data for printing a failed assertion or expectation.
*
* Represents a failed expectation/assertion. Contains all the data necessary to
* format a string to a user reporting the failure.
*/
struct kunit_assert {};
typedef void (*assert_format_t)(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
void kunit_assert_prologue(const struct kunit_loc *loc,
enum kunit_assert_type type,
struct string_stream *stream);
/**
* struct kunit_fail_assert - Represents a plain fail expectation/assertion.
* @assert: The parent of this type.
*
* Represents a simple KUNIT_FAIL/KUNIT_FAIL_AND_ABORT that always fails.
*/
struct kunit_fail_assert {
struct kunit_assert assert;
};
void kunit_fail_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
/**
* struct kunit_unary_assert - Represents a KUNIT_{EXPECT|ASSERT}_{TRUE|FALSE}
* @assert: The parent of this type.
* @condition: A string representation of a conditional expression.
* @expected_true: True if of type KUNIT_{EXPECT|ASSERT}_TRUE, false otherwise.
*
* Represents a simple expectation or assertion that simply asserts something is
* true or false. In other words, represents the expectations:
* KUNIT_{EXPECT|ASSERT}_{TRUE|FALSE}
*/
struct kunit_unary_assert {
struct kunit_assert assert;
const char *condition;
bool expected_true;
};
void kunit_unary_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
/**
* struct kunit_ptr_not_err_assert - An expectation/assertion that a pointer is
* not NULL and not a -errno.
* @assert: The parent of this type.
* @text: A string representation of the expression passed to the expectation.
* @value: The actual evaluated pointer value of the expression.
*
* Represents an expectation/assertion that a pointer is not null and is does
* not contain a -errno. (See IS_ERR_OR_NULL().)
*/
struct kunit_ptr_not_err_assert {
struct kunit_assert assert;
const char *text;
const void *value;
};
void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
/**
* struct kunit_binary_assert_text - holds strings for &struct
* kunit_binary_assert and friends to try and make the structs smaller.
* @operation: A string representation of the comparison operator (e.g. "==").
* @left_text: A string representation of the left expression (e.g. "2+2").
* @right_text: A string representation of the right expression (e.g. "2+2").
*/
struct kunit_binary_assert_text {
const char *operation;
const char *left_text;
const char *right_text;
};
/**
* struct kunit_binary_assert - An expectation/assertion that compares two
* non-pointer values (for example, KUNIT_EXPECT_EQ(test, 1 + 1, 2)).
* @assert: The parent of this type.
* @text: Holds the textual representations of the operands and op (e.g. "==").
* @left_value: The actual evaluated value of the expression in the left slot.
* @right_value: The actual evaluated value of the expression in the right slot.
*
* Represents an expectation/assertion that compares two non-pointer values. For
* example, to expect that 1 + 1 == 2, you can use the expectation
* KUNIT_EXPECT_EQ(test, 1 + 1, 2);
*/
struct kunit_binary_assert {
struct kunit_assert assert;
const struct kunit_binary_assert_text *text;
long long left_value;
long long right_value;
};
void kunit_binary_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
/**
* struct kunit_binary_ptr_assert - An expectation/assertion that compares two
* pointer values (for example, KUNIT_EXPECT_PTR_EQ(test, foo, bar)).
* @assert: The parent of this type.
* @text: Holds the textual representations of the operands and op (e.g. "==").
* @left_value: The actual evaluated value of the expression in the left slot.
* @right_value: The actual evaluated value of the expression in the right slot.
*
* Represents an expectation/assertion that compares two pointer values. For
* example, to expect that foo and bar point to the same thing, you can use the
* expectation KUNIT_EXPECT_PTR_EQ(test, foo, bar);
*/
struct kunit_binary_ptr_assert {
struct kunit_assert assert;
const struct kunit_binary_assert_text *text;
const void *left_value;
const void *right_value;
};
void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
/**
* struct kunit_binary_str_assert - An expectation/assertion that compares two
* string values (for example, KUNIT_EXPECT_STREQ(test, foo, "bar")).
* @assert: The parent of this type.
* @text: Holds the textual representations of the operands and comparator.
* @left_value: The actual evaluated value of the expression in the left slot.
* @right_value: The actual evaluated value of the expression in the right slot.
*
* Represents an expectation/assertion that compares two string values. For
* example, to expect that the string in foo is equal to "bar", you can use the
* expectation KUNIT_EXPECT_STREQ(test, foo, "bar");
*/
struct kunit_binary_str_assert {
struct kunit_assert assert;
const struct kunit_binary_assert_text *text;
const char *left_value;
const char *right_value;
};
void kunit_binary_str_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
/**
* struct kunit_mem_assert - An expectation/assertion that compares two
* memory blocks.
* @assert: The parent of this type.
* @text: Holds the textual representations of the operands and comparator.
* @left_value: The actual evaluated value of the expression in the left slot.
* @right_value: The actual evaluated value of the expression in the right slot.
* @size: Size of the memory block analysed in bytes.
*
* Represents an expectation/assertion that compares two memory blocks. For
* example, to expect that the first three bytes of foo is equal to the
* first three bytes of bar, you can use the expectation
* KUNIT_EXPECT_MEMEQ(test, foo, bar, 3);
*/
struct kunit_mem_assert {
struct kunit_assert assert;
const struct kunit_binary_assert_text *text;
const void *left_value;
const void *right_value;
const size_t size;
};
void kunit_mem_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream);
#if IS_ENABLED(CONFIG_KUNIT)
void kunit_assert_print_msg(const struct va_format *message,
struct string_stream *stream);
bool is_literal(const char *text, long long value);
bool is_str_literal(const char *text, const char *value);
void kunit_assert_hexdump(struct string_stream *stream,
const void *buf,
const void *compared_buf,
const size_t len);
#endif
#endif /* _KUNIT_ASSERT_H */
+50
View File
@@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit API to save and access test attributes
*
* Copyright (C) 2023, Google LLC.
* Author: Rae Moar <rmoar@google.com>
*/
#ifndef _KUNIT_ATTRIBUTES_H
#define _KUNIT_ATTRIBUTES_H
/*
* struct kunit_attr_filter - representation of attributes filter with the
* attribute object and string input
*/
struct kunit_attr_filter {
struct kunit_attr *attr;
char *input;
};
/*
* Returns the name of the filter's attribute.
*/
const char *kunit_attr_filter_name(struct kunit_attr_filter filter);
/*
* Print all test attributes for a test case or suite.
* Output format for test cases: "# <test_name>.<attribute>: <value>"
* Output format for test suites: "# <attribute>: <value>"
*/
void kunit_print_attr(void *test_or_suite, bool is_test, unsigned int test_level);
/*
* Returns the number of fitlers in input.
*/
int kunit_get_filter_count(char *input);
/*
* Parse attributes filter input and return an objects containing the
* attribute object and the string input of the next filter.
*/
struct kunit_attr_filter kunit_next_attr_filter(char **filters, int *err);
/*
* Returns a copy of the suite containing only tests that pass the filter.
*/
struct kunit_suite *kunit_filter_attr_tests(const struct kunit_suite *const suite,
struct kunit_attr_filter filter, char *action, int *err);
#endif /* _KUNIT_ATTRIBUTES_H */
+33
View File
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _CLK_KUNIT_H
#define _CLK_KUNIT_H
struct clk;
struct clk_hw;
struct device;
struct device_node;
struct of_phandle_args;
struct kunit;
struct clk *
clk_get_kunit(struct kunit *test, struct device *dev, const char *con_id);
struct clk *
of_clk_get_kunit(struct kunit *test, struct device_node *np, int index);
struct clk *
clk_hw_get_clk_kunit(struct kunit *test, struct clk_hw *hw, const char *con_id);
struct clk *
clk_hw_get_clk_prepared_enabled_kunit(struct kunit *test, struct clk_hw *hw,
const char *con_id);
int clk_prepare_enable_kunit(struct kunit *test, struct clk *clk);
int clk_hw_register_kunit(struct kunit *test, struct device *dev, struct clk_hw *hw);
int of_clk_hw_register_kunit(struct kunit *test, struct device_node *node,
struct clk_hw *hw);
int of_clk_add_hw_provider_kunit(struct kunit *test, struct device_node *np,
struct clk_hw *(*get)(struct of_phandle_args *clkspec, void *data),
void *data);
#endif
+80
View File
@@ -0,0 +1,80 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit basic device implementation
*
* Helpers for creating and managing fake devices for KUnit tests.
*
* Copyright (C) 2023, Google LLC.
* Author: David Gow <davidgow@google.com>
*/
#ifndef _KUNIT_DEVICE_H
#define _KUNIT_DEVICE_H
#if IS_ENABLED(CONFIG_KUNIT)
#include <kunit/test.h>
struct device;
struct device_driver;
/**
* kunit_driver_create() - Create a struct device_driver attached to the kunit_bus
* @test: The test context object.
* @name: The name to give the created driver.
*
* Creates a struct device_driver attached to the kunit_bus, with the name @name.
* This driver will automatically be cleaned up on test exit.
*
* Return: a stub struct device_driver, managed by KUnit, with the name @name.
*/
struct device_driver *kunit_driver_create(struct kunit *test, const char *name);
/**
* kunit_device_register() - Create a struct device for use in KUnit tests
* @test: The test context object.
* @name: The name to give the created device.
*
* Creates a struct kunit_device (which is a struct device) with the given name,
* and a corresponding driver. The device and driver will be cleaned up on test
* exit, or when kunit_device_unregister is called. See also
* kunit_device_register_with_driver, if you wish to provide your own
* struct device_driver.
*
* Return: a pointer to a struct device which will be cleaned up when the test
* exits, or an error pointer if the device could not be allocated or registered.
*/
struct device *kunit_device_register(struct kunit *test, const char *name);
/**
* kunit_device_register_with_driver() - Create a struct device for use in KUnit tests
* @test: The test context object.
* @name: The name to give the created device.
* @drv: The struct device_driver to associate with the device.
*
* Creates a struct kunit_device (which is a struct device) with the given
* name, and driver. The device will be cleaned up on test exit, or when
* kunit_device_unregister is called. See also kunit_device_register, if you
* wish KUnit to create and manage a driver for you.
*
* Return: a pointer to a struct device which will be cleaned up when the test
* exits, or an error pointer if the device could not be allocated or registered.
*/
struct device *kunit_device_register_with_driver(struct kunit *test,
const char *name,
const struct device_driver *drv);
/**
* kunit_device_unregister() - Unregister a KUnit-managed device
* @test: The test context object which created the device
* @dev: The device.
*
* Unregisters and destroys a struct device which was created with
* kunit_device_register or kunit_device_register_with_driver. If KUnit created
* a driver, cleans it up as well.
*/
void kunit_device_unregister(struct kunit *test, struct device *dev);
#endif
#endif
+121
View File
@@ -0,0 +1,121 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _KUNIT_OF_H
#define _KUNIT_OF_H
#include <kunit/test.h>
struct device_node;
#ifdef CONFIG_OF
void of_node_put_kunit(struct kunit *test, struct device_node *node);
#else
static inline
void of_node_put_kunit(struct kunit *test, struct device_node *node)
{
kunit_skip(test, "requires CONFIG_OF");
}
#endif /* !CONFIG_OF */
#if defined(CONFIG_OF) && defined(CONFIG_OF_OVERLAY) && defined(CONFIG_OF_EARLY_FLATTREE)
int of_overlay_fdt_apply_kunit(struct kunit *test, void *overlay_fdt,
u32 overlay_fdt_size, int *ovcs_id);
#else
static inline int
of_overlay_fdt_apply_kunit(struct kunit *test, void *overlay_fdt,
u32 overlay_fdt_size, int *ovcs_id)
{
kunit_skip(test, "requires CONFIG_OF and CONFIG_OF_OVERLAY and CONFIG_OF_EARLY_FLATTREE for root node");
return -EINVAL;
}
#endif
/**
* __of_overlay_apply_kunit() - Test managed of_overlay_fdt_apply() variant
* @test: test context
* @overlay_begin: start address of overlay to apply
* @overlay_end: end address of overlay to apply
*
* This is mostly internal API. See of_overlay_apply_kunit() for the wrapper
* that makes this easier to use.
*
* Similar to of_overlay_fdt_apply(), except the overlay is managed by the test
* case and is automatically removed with of_overlay_remove() after the test
* case concludes.
*
* Return: 0 on success, negative errno on failure
*/
static inline int __of_overlay_apply_kunit(struct kunit *test,
u8 *overlay_begin,
const u8 *overlay_end)
{
int unused;
return of_overlay_fdt_apply_kunit(test, overlay_begin,
overlay_end - overlay_begin,
&unused);
}
#define of_overlay_begin(overlay_name) __dtbo_##overlay_name##_begin
#define of_overlay_end(overlay_name) __dtbo_##overlay_name##_end
#define OF_OVERLAY_DECLARE(overlay_name) \
extern uint8_t of_overlay_begin(overlay_name)[]; \
extern uint8_t of_overlay_end(overlay_name)[] \
/**
* of_overlay_apply_kunit() - Test managed of_overlay_fdt_apply() for built-in overlays
* @test: test context
* @overlay_name: name of overlay to apply
*
* This macro is used to apply a device tree overlay built with the
* cmd_dt_S_dtbo rule in scripts/Makefile.lib that has been compiled into the
* kernel image or KUnit test module. The overlay is automatically removed when
* the test is finished.
*
* Unit tests that need device tree nodes should compile an overlay file with
* @overlay_name\.dtbo.o in their Makefile along with their unit test and then
* load the overlay during their test. The @overlay_name matches the filename
* of the overlay without the dtbo filename extension. If CONFIG_OF_OVERLAY is
* not enabled, the @test will be skipped.
*
* In the Makefile
*
* .. code-block:: none
*
* obj-$(CONFIG_OF_OVERLAY_KUNIT_TEST) += overlay_test.o kunit_overlay_test.dtbo.o
*
* In the test
*
* .. code-block:: c
*
* static void of_overlay_kunit_of_overlay_apply(struct kunit *test)
* {
* struct device_node *np;
*
* KUNIT_ASSERT_EQ(test, 0,
* of_overlay_apply_kunit(test, kunit_overlay_test));
*
* np = of_find_node_by_name(NULL, "test-kunit");
* KUNIT_EXPECT_NOT_ERR_OR_NULL(test, np);
* of_node_put(np);
* }
*
* Return: 0 on success, negative errno on failure.
*/
#define of_overlay_apply_kunit(test, overlay_name) \
({ \
OF_OVERLAY_DECLARE(overlay_name); \
\
__of_overlay_apply_kunit((test), \
of_overlay_begin(overlay_name), \
of_overlay_end(overlay_name)); \
})
#endif
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _KUNIT_PLATFORM_DRIVER_H
#define _KUNIT_PLATFORM_DRIVER_H
struct completion;
struct kunit;
struct platform_device;
struct platform_driver;
struct platform_device_info;
struct platform_device *
kunit_platform_device_alloc(struct kunit *test, const char *name, int id);
int kunit_platform_device_add(struct kunit *test, struct platform_device *pdev);
struct platform_device *
kunit_platform_device_register_full(struct kunit *test,
const struct platform_device_info *pdevinfo);
void kunit_platform_device_unregister(struct kunit *test,
struct platform_device *pdev);
int kunit_platform_device_prepare_wait_for_probe(struct kunit *test,
struct platform_device *pdev,
struct completion *x);
int kunit_platform_driver_register(struct kunit *test,
struct platform_driver *drv);
#endif
+503
View File
@@ -0,0 +1,503 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit resource API for test managed resources (allocations, etc.).
*
* Copyright (C) 2022, Google LLC.
* Author: Daniel Latypov <dlatypov@google.com>
*/
#ifndef _KUNIT_RESOURCE_H
#define _KUNIT_RESOURCE_H
#include <kunit/test.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/spinlock.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.
*
* Represents a *test managed resource*, a resource which will automatically be
* cleaned up at the end of a test case. This cleanup is performed by the 'free'
* function. The struct kunit_resource itself is freed automatically with
* kfree() if it was allocated by KUnit (e.g., by kunit_alloc_resource()), but
* must be freed by the user otherwise.
*
* 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, gfp, &params);
* }
*
* 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;
bool should_kfree;
};
/**
* 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_resource();
* 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 (res->free)
res->free(res);
/* 'res' is valid here, as if should_kfree is set, res->free may not free
* 'res' itself, just res->data
*/
if (res->should_kfree)
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() - Internal helper to add a resource.
*
* res->should_kfree is not initialised.
* @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_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.
*/
static inline int kunit_add_resource(struct kunit *test,
kunit_resource_init_t init,
kunit_resource_free_t free,
struct kunit_resource *res,
void *data)
{
res->should_kfree = false;
return __kunit_add_resource(test, init, free, res, data);
}
static inline struct kunit_resource *
kunit_find_named_resource(struct kunit *test, const char *name);
/**
* 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.
*/
static inline 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)
{
struct kunit_resource *existing;
if (!name)
return -EINVAL;
existing = kunit_find_named_resource(test, name);
if (existing) {
kunit_put_resource(existing);
return -EEXIST;
}
res->name = name;
res->should_kfree = false;
return __kunit_add_resource(test, init, free, res, data);
}
/**
* kunit_alloc_and_get_resource() - Allocates and returns 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 (if needed).
* @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.
*
* This is effectively identical to kunit_alloc_resource, but returns the
* struct kunit_resource pointer, not just the 'data' pointer. It therefore
* also increments the resource's refcount, so kunit_put_resource() should be
* called when you've finished with it.
*
* 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 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)
{
struct kunit_resource *res;
int ret;
res = kzalloc_obj(*res, internal_gfp);
if (!res)
return NULL;
res->should_kfree = true;
ret = __kunit_add_resource(test, init, free, res, context);
if (!ret) {
/*
* bump refcount for get; kunit_resource_put() should be called
* when done.
*/
kunit_get_resource(res);
return res;
}
return NULL;
}
/**
* 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 (if needed).
* @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_obj(*res, internal_gfp);
if (!res)
return NULL;
res->should_kfree = true;
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);
/**
* 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.
*
* RETURNS:
* 0 if kunit_resource is found and freed, -ENOENT if not found.
*/
int kunit_destroy_resource(struct kunit *test,
kunit_resource_match_t match,
void *match_data);
static inline int kunit_destroy_named_resource(struct kunit *test,
const char *name)
{
return kunit_destroy_resource(test, kunit_resource_name_match,
(void *)name);
}
/**
* 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);
/* A 'deferred action' function to be used with kunit_add_action. */
typedef void (kunit_action_t)(void *);
/**
* KUNIT_DEFINE_ACTION_WRAPPER() - Wrap a function for use as a deferred action.
*
* @wrapper: The name of the new wrapper function define.
* @orig: The original function to wrap.
* @arg_type: The type of the argument accepted by @orig.
*
* Defines a wrapper for a function which accepts a single, pointer-sized
* argument. This wrapper can then be passed to kunit_add_action() and
* similar. This should be used in preference to casting a function
* directly to kunit_action_t, as casting function pointers will break
* control flow integrity (CFI), leading to crashes.
*/
#define KUNIT_DEFINE_ACTION_WRAPPER(wrapper, orig, arg_type) \
static void wrapper(void *in) \
{ \
arg_type arg = (arg_type)in; \
orig(arg); \
}
/**
* kunit_add_action() - Call a function when the test ends.
* @test: Test case to associate the action with.
* @action: The function to run on test exit
* @ctx: Data passed into @func
*
* Defer the execution of a function until the test exits, either normally or
* due to a failure. @ctx is passed as additional context. All functions
* registered with kunit_add_action() will execute in the opposite order to that
* they were registered in.
*
* This is useful for cleaning up allocated memory and resources, as these
* functions are called even if the test aborts early due to, e.g., a failed
* assertion.
*
* See also: devm_add_action() for the devres equivalent.
*
* Returns:
* 0 on success, an error if the action could not be deferred.
*/
int kunit_add_action(struct kunit *test, kunit_action_t *action, void *ctx);
/**
* kunit_add_action_or_reset() - Call a function when the test ends.
* @test: Test case to associate the action with.
* @action: The function to run on test exit
* @ctx: Data passed into @func
*
* Defer the execution of a function until the test exits, either normally or
* due to a failure. @ctx is passed as additional context. All functions
* registered with kunit_add_action() will execute in the opposite order to that
* they were registered in.
*
* This is useful for cleaning up allocated memory and resources, as these
* functions are called even if the test aborts early due to, e.g., a failed
* assertion.
*
* If the action cannot be created (e.g., due to the system being out of memory),
* then action(ctx) will be called immediately, and an error will be returned.
*
* See also: devm_add_action_or_reset() for the devres equivalent.
*
* Returns:
* 0 on success, an error if the action could not be deferred.
*/
int kunit_add_action_or_reset(struct kunit *test, kunit_action_t *action,
void *ctx);
/**
* kunit_remove_action() - Cancel a matching deferred action.
* @test: Test case the action is associated with.
* @action: The deferred function to cancel.
* @ctx: The context passed to the deferred function to trigger.
*
* Prevent an action deferred via kunit_add_action() from executing when the
* test terminates.
*
* If the function/context pair was deferred multiple times, only the most
* recent one will be cancelled.
*
* See also: devm_remove_action() for the devres equivalent.
*/
void kunit_remove_action(struct kunit *test,
kunit_action_t *action,
void *ctx);
/**
* kunit_release_action() - Run a matching action call immediately.
* @test: Test case the action is associated with.
* @action: The deferred function to trigger.
* @ctx: The context passed to the deferred function to trigger.
*
* Execute a function deferred via kunit_add_action()) immediately, rather than
* when the test ends.
*
* If the function/context pair was deferred multiple times, it will only be
* executed once here. The most recent deferral will no longer execute when
* the test ends.
*
* kunit_release_action(test, func, ctx);
* is equivalent to
* func(ctx);
* kunit_remove_action(test, func, ctx);
*
* See also: devm_release_action() for the devres equivalent.
*/
void kunit_release_action(struct kunit *test,
kunit_action_t *action,
void *ctx);
#endif /* _KUNIT_RESOURCE_H */
@@ -0,0 +1,156 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Helper function for testing code in interrupt contexts
*
* Copyright 2025 Google LLC
*/
#ifndef _KUNIT_RUN_IN_IRQ_CONTEXT_H
#define _KUNIT_RUN_IN_IRQ_CONTEXT_H
#include <kunit/test.h>
#include <linux/timekeeping.h>
#include <linux/hrtimer.h>
#include <linux/workqueue.h>
struct kunit_irq_test_state {
bool (*func)(void *test_specific_state);
void *test_specific_state;
bool task_func_reported_failure;
bool hardirq_func_reported_failure;
bool softirq_func_reported_failure;
atomic_t task_func_calls;
atomic_t hardirq_func_calls;
atomic_t softirq_func_calls;
ktime_t interval;
struct hrtimer timer;
struct work_struct bh_work;
};
static enum hrtimer_restart kunit_irq_test_timer_func(struct hrtimer *timer)
{
struct kunit_irq_test_state *state =
container_of(timer, typeof(*state), timer);
int task_calls, hardirq_calls, softirq_calls;
WARN_ON_ONCE(!in_hardirq());
task_calls = atomic_read(&state->task_func_calls);
hardirq_calls = atomic_inc_return(&state->hardirq_func_calls);
softirq_calls = atomic_read(&state->softirq_func_calls);
/*
* If the hrtimer is running much faster than the bh_work or the task,
* then it is firing too fast and might be starving those contexts as
* well as the actual system timer tick. Increase the interval.
*/
if (hardirq_calls >= 20 &&
(hardirq_calls / 2 > softirq_calls ||
hardirq_calls / 2 > task_calls))
state->interval = ktime_add_ns(state->interval, 250);
if (!state->func(state->test_specific_state))
state->hardirq_func_reported_failure = true;
hrtimer_forward_now(&state->timer, state->interval);
queue_work(system_bh_wq, &state->bh_work);
return HRTIMER_RESTART;
}
static void kunit_irq_test_bh_work_func(struct work_struct *work)
{
struct kunit_irq_test_state *state =
container_of(work, typeof(*state), bh_work);
WARN_ON_ONCE(!in_serving_softirq());
atomic_inc(&state->softirq_func_calls);
if (!state->func(state->test_specific_state))
state->softirq_func_reported_failure = true;
}
/*
* Helper function which repeatedly runs the given @func in task, softirq, and
* hardirq context concurrently, and reports a failure to KUnit if any
* invocation of @func in any context returns false. @func is passed
* @test_specific_state as its argument. At most 3 invocations of @func will
* run concurrently: one in each of task, softirq, and hardirq context. @func
* will continue running until either @max_iterations calls have been made (so
* long as at least one each runs in task, softirq, and hardirq contexts), or
* one second has passed.
*
* The main purpose of this interrupt context testing is to validate fallback
* code paths that run in contexts where the normal code path cannot be used,
* typically due to the FPU or vector registers already being in-use in kernel
* mode. These code paths aren't covered when the test code is executed only by
* the KUnit test runner thread in task context. The reason for the concurrency
* is because merely using hardirq context is not sufficient to reach a fallback
* code path on some architectures; the hardirq actually has to occur while the
* FPU or vector unit was already in-use in kernel mode.
*
* Another purpose of this testing is to detect issues with the architecture's
* irq_fpu_usable() and kernel_fpu_begin/end() or equivalent functions,
* especially in softirq context when the softirq may have interrupted a task
* already using kernel-mode FPU or vector (if the arch didn't prevent that).
* Crypto functions are often executed in softirqs, so this is important.
*/
static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
int max_iterations,
void *test_specific_state)
{
struct kunit_irq_test_state state = {
.func = func,
.test_specific_state = test_specific_state,
/*
* Start with a 5us timer interval. If the system can't keep
* up, kunit_irq_test_timer_func() will increase it.
*/
.interval = us_to_ktime(5),
};
unsigned long end_jiffies;
int task_calls, hardirq_calls, softirq_calls;
/*
* Set up a hrtimer (the way we access hardirq context) and a work
* struct for the BH workqueue (the way we access softirq context).
*/
hrtimer_setup_on_stack(&state.timer, kunit_irq_test_timer_func,
CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
INIT_WORK_ONSTACK(&state.bh_work, kunit_irq_test_bh_work_func);
/*
* Run for up to max_iterations (including at least one task, softirq,
* and hardirq), or 1 second, whichever comes first.
*/
end_jiffies = jiffies + HZ;
hrtimer_start(&state.timer, state.interval, HRTIMER_MODE_REL_HARD);
do {
if (!func(test_specific_state))
state.task_func_reported_failure = true;
task_calls = atomic_inc_return(&state.task_func_calls);
hardirq_calls = atomic_read(&state.hardirq_func_calls);
softirq_calls = atomic_read(&state.softirq_func_calls);
} while ((task_calls + hardirq_calls + softirq_calls < max_iterations ||
(task_calls == 0 || hardirq_calls == 0 ||
softirq_calls == 0)) &&
!time_after(jiffies, end_jiffies));
/* Cancel the timer and work. */
hrtimer_cancel(&state.timer);
flush_work(&state.bh_work);
/* Sanity check: the timer and BH functions should have been run. */
KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.hardirq_func_calls), 0,
"Timer function was not called");
KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.softirq_func_calls), 0,
"BH work function was not called");
/* Check for failure reported from any context. */
KUNIT_EXPECT_FALSE_MSG(test, state.task_func_reported_failure,
"Failure reported from task context");
KUNIT_EXPECT_FALSE_MSG(test, state.hardirq_func_reported_failure,
"Failure reported from hardirq context");
KUNIT_EXPECT_FALSE_MSG(test, state.softirq_func_reported_failure,
"Failure reported from softirq context");
}
#endif /* _KUNIT_RUN_IN_IRQ_CONTEXT_H */
+57
View File
@@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit resource management helpers for SKBs (skbuff).
*
* Copyright (C) 2023 Intel Corporation
*/
#ifndef _KUNIT_SKBUFF_H
#define _KUNIT_SKBUFF_H
#include <kunit/resource.h>
#include <linux/skbuff.h>
static void kunit_action_kfree_skb(void *p)
{
kfree_skb((struct sk_buff *)p);
}
/**
* kunit_zalloc_skb() - Allocate and initialize a resource managed skb.
* @test: The test case to which the skb belongs
* @len: size to allocate
* @gfp: allocation flags
*
* Allocate a new struct sk_buff with gfp flags, zero fill the given length
* and add it as a resource to the kunit test for automatic cleanup.
*
* Returns: newly allocated SKB, or %NULL on error
*/
static inline struct sk_buff *kunit_zalloc_skb(struct kunit *test, int len,
gfp_t gfp)
{
struct sk_buff *res = alloc_skb(len, gfp);
if (!res || skb_pad(res, len))
return NULL;
if (kunit_add_action_or_reset(test, kunit_action_kfree_skb, res))
return NULL;
return res;
}
/**
* kunit_kfree_skb() - Like kfree_skb except for allocations managed by KUnit.
* @test: The test case to which the resource belongs.
* @skb: The SKB to free.
*/
static inline void kunit_kfree_skb(struct kunit *test, struct sk_buff *skb)
{
if (!skb)
return;
kunit_release_action(test, kunit_action_kfree_skb, (void *)skb);
}
#endif /* _KUNIT_SKBUFF_H */
+113
View File
@@ -0,0 +1,113 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit function redirection (static stubbing) API.
*
* Copyright (C) 2022, Google LLC.
* Author: David Gow <davidgow@google.com>
*/
#ifndef _KUNIT_STATIC_STUB_H
#define _KUNIT_STATIC_STUB_H
#if !IS_ENABLED(CONFIG_KUNIT)
/* If CONFIG_KUNIT is not enabled, these stubs quietly disappear. */
#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) do {} while (0)
#else
#include <kunit/test.h>
#include <kunit/test-bug.h>
#include <linux/compiler.h> /* for {un,}likely() */
#include <linux/sched.h> /* for task_struct */
/**
* KUNIT_STATIC_STUB_REDIRECT() - call a replacement 'static stub' if one exists
* @real_fn_name: The name of this function (as an identifier, not a string)
* @args: All of the arguments passed to this function
*
* This is a function prologue which is used to allow calls to the current
* function to be redirected by a KUnit test. KUnit tests can call
* kunit_activate_static_stub() to pass a replacement function in. The
* replacement function will be called by KUNIT_STATIC_STUB_REDIRECT(), which
* will then return from the function. If the caller is not in a KUnit context,
* the function will continue execution as normal.
*
* Example:
*
* .. code-block:: c
*
* int real_func(int n)
* {
* KUNIT_STATIC_STUB_REDIRECT(real_func, n);
* return 0;
* }
*
* int replacement_func(int n)
* {
* return 42;
* }
*
* void example_test(struct kunit *test)
* {
* kunit_activate_static_stub(test, real_func, replacement_func);
* KUNIT_EXPECT_EQ(test, real_func(1), 42);
* }
*
*/
#define KUNIT_STATIC_STUB_REDIRECT(real_fn_name, args...) \
do { \
typeof(&real_fn_name) replacement; \
struct kunit *current_test = kunit_get_current_test(); \
\
if (likely(!current_test)) \
break; \
\
replacement = kunit_hooks.get_static_stub_address(current_test, \
&real_fn_name); \
\
if (unlikely(replacement)) \
return replacement(args); \
} while (0)
/* Helper function for kunit_activate_static_stub(). The macro does
* typechecking, so use it instead.
*/
void __kunit_activate_static_stub(struct kunit *test,
void *real_fn_addr,
void *replacement_addr);
/**
* kunit_activate_static_stub() - replace a function using static stubs.
* @test: A pointer to the 'struct kunit' test context for the current test.
* @real_fn_addr: The address of the function to replace.
* @replacement_addr: The address of the function to replace it with.
*
* When activated, calls to real_fn_addr from within this test (even if called
* indirectly) will instead call replacement_addr. The function pointed to by
* real_fn_addr must begin with the static stub prologue in
* KUNIT_STATIC_STUB_REDIRECT() for this to work. real_fn_addr and
* replacement_addr must have the same type.
*
* The redirection can be disabled again with kunit_deactivate_static_stub().
*/
#define kunit_activate_static_stub(test, real_fn_addr, replacement_addr) do { \
typecheck_fn(typeof(&replacement_addr), real_fn_addr); \
__kunit_activate_static_stub(test, real_fn_addr, replacement_addr); \
} while (0)
/**
* kunit_deactivate_static_stub() - disable a function redirection
* @test: A pointer to the 'struct kunit' test context for the current test.
* @real_fn_addr: The address of the function to no-longer redirect
*
* Deactivates a redirection configured with kunit_activate_static_stub(). After
* this function returns, calls to real_fn_addr() will execute the original
* real_fn, not any previously-configured replacement.
*/
void kunit_deactivate_static_stub(struct kunit *test, void *real_fn_addr);
#endif
#endif
+97
View File
@@ -0,0 +1,97 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit API providing hooks for non-test code to interact with tests.
*
* Copyright (C) 2020, Google LLC.
* Author: Uriel Guajardo <urielguajardo@google.com>
*/
#ifndef _KUNIT_TEST_BUG_H
#define _KUNIT_TEST_BUG_H
#include <linux/stddef.h> /* for NULL */
#include <linux/types.h> /* for bool */
#if IS_ENABLED(CONFIG_KUNIT)
#include <linux/jump_label.h> /* For static branch */
#include <linux/sched.h>
/* Static key if KUnit is running any tests. */
DECLARE_STATIC_KEY_FALSE(kunit_running);
/* Hooks table: a table of function pointers filled in when kunit loads */
extern struct kunit_hooks_table {
__printf(3, 4) void (*fail_current_test)(const char*, int, const char*, ...);
void *(*get_static_stub_address)(struct kunit *test, void *real_fn_addr);
bool (*is_suppressed_warning)(bool count);
} kunit_hooks;
/**
* kunit_get_current_test() - Return a pointer to the currently running
* KUnit test.
*
* If a KUnit test is running in the current task, returns a pointer to its
* associated struct kunit. This pointer can then be passed to any KUnit
* function or assertion. If no test is running (or a test is running in a
* different task), returns NULL.
*
* This function is safe to call even when KUnit is disabled. If CONFIG_KUNIT
* is not enabled, it will compile down to nothing and will return quickly no
* test is running.
*/
static inline struct kunit *kunit_get_current_test(void)
{
if (!static_branch_unlikely(&kunit_running))
return NULL;
return current->kunit_test;
}
/**
* kunit_fail_current_test() - If a KUnit test is running, fail it.
*
* If a KUnit test is running in the current task, mark that test as failed.
*/
#define kunit_fail_current_test(fmt, ...) do { \
if (static_branch_unlikely(&kunit_running)) { \
/* Guaranteed to be non-NULL when kunit_running true*/ \
kunit_hooks.fail_current_test(__FILE__, __LINE__, \
fmt, ##__VA_ARGS__); \
} \
} while (0)
/**
* kunit_is_suppressed_warning() - Check if warnings are being suppressed
* by the current KUnit test.
* @count: if true, increment the suppression counter on match.
*
* Returns true if the current task has active warning suppression.
* Uses the kunit_running static branch for zero overhead when no tests run.
*
* A single WARN*() may traverse multiple call sites in the warning path
* (e.g., __warn_printk() and __report_bug()). Pass @count = true at the
* primary suppression point to count each warning exactly once, and
* @count = false at secondary points to suppress output without
* inflating the count.
*/
static inline bool kunit_is_suppressed_warning(bool count)
{
if (!static_branch_unlikely(&kunit_running))
return false;
return kunit_hooks.is_suppressed_warning &&
kunit_hooks.is_suppressed_warning(count);
}
#else
static inline struct kunit *kunit_get_current_test(void) { return NULL; }
static inline bool kunit_is_suppressed_warning(bool count) { return false; }
#define kunit_fail_current_test(fmt, ...) do {} while (0)
#endif
#endif /* _KUNIT_TEST_BUG_H */
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* An API to allow a function, that may fail, to be executed, and recover in a
* controlled manner.
*
* Copyright (C) 2019, Google LLC.
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
#ifndef _KUNIT_TRY_CATCH_H
#define _KUNIT_TRY_CATCH_H
#include <linux/types.h>
typedef void (*kunit_try_catch_func_t)(void *);
struct kunit;
/**
* struct kunit_try_catch - provides a generic way to run code which might fail.
* @test: The test case that is currently being executed.
* @try_result: Contains any errno obtained while running test case.
* @try: The function, the test case, to attempt to run.
* @catch: The function called if @try bails out.
* @context: used to pass user data to the try and catch functions.
*
* kunit_try_catch provides a generic, architecture independent way to execute
* an arbitrary function of type kunit_try_catch_func_t which may bail out by
* calling kunit_try_catch_throw(). If kunit_try_catch_throw() is called, @try
* is stopped at the site of invocation and @catch is called.
*
* struct kunit_try_catch provides a generic interface for the functionality
* needed to implement kunit->abort() which in turn is needed for implementing
* assertions. Assertions allow stating a precondition for a test simplifying
* how test cases are written and presented.
*
* Assertions are like expectations, except they abort (call
* kunit_try_catch_throw()) when the specified condition is not met. This is
* useful when you look at a test case as a logical statement about some piece
* of code, where assertions are the premises for the test case, and the
* conclusion is a set of predicates, rather expectations, that must all be
* true. If your premises are violated, it does not makes sense to continue.
*/
struct kunit_try_catch {
/* private: internal use only. */
struct kunit *test;
int try_result;
kunit_try_catch_func_t try;
kunit_try_catch_func_t catch;
unsigned long timeout;
void *context;
};
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch);
static inline int kunit_try_catch_get_result(struct kunit_try_catch *try_catch)
{
return try_catch->try_result;
}
#endif /* _KUNIT_TRY_CATCH_H */
+33
View File
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KUnit API to allow symbols to be conditionally visible during KUnit
* testing
*
* Copyright (C) 2022, Google LLC.
* Author: Rae Moar <rmoar@google.com>
*/
#ifndef _KUNIT_VISIBILITY_H
#define _KUNIT_VISIBILITY_H
#if IS_ENABLED(CONFIG_KUNIT)
/**
* VISIBLE_IF_KUNIT - A macro that sets symbols to be static if
* CONFIG_KUNIT is not enabled. Otherwise if CONFIG_KUNIT is enabled
* there is no change to the symbol definition.
*/
#define VISIBLE_IF_KUNIT
/**
* EXPORT_SYMBOL_IF_KUNIT(symbol) - Exports symbol into
* EXPORTED_FOR_KUNIT_TESTING namespace only if CONFIG_KUNIT is
* enabled. Must use MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING")
* in test file in order to use symbols.
* @symbol: the symbol identifier to export
*/
#define EXPORT_SYMBOL_IF_KUNIT(symbol) EXPORT_SYMBOL_NS(symbol, "EXPORTED_FOR_KUNIT_TESTING")
#else
#define VISIBLE_IF_KUNIT static
#define EXPORT_SYMBOL_IF_KUNIT(symbol)
#endif
#endif /* _KUNIT_VISIBILITY_H */