blob: a2419ecaa0d439611fb82b7afb676a226ac3b224 [file] [log] [blame]
#ifndef _TEST_TEST_H
#define _TEST_TEST_H
#include <linux/types.h>
#include <linux/slab.h>
#include <test/test-stream.h>
/**
* struct test_resource - represents a *test managed resource*
* @allocation: for the user to store arbitrary data.
* @free: a user supplied function to free the resource. Populated by
* test_alloc_resource().
*
* Represents a *test managed resource*, a resource which will automatically be
* cleaned up at the end of a test case.
*
* Example:
*
* .. code-block:: c
*
* struct test_kmalloc_params {
* size_t size;
* gfp_t gfp;
* };
*
* static int test_kmalloc_init(struct test_resource *res, void *context)
* {
* struct test_kmalloc_params *params = context;
* res->allocation = kmalloc(params->size, params->gfp);
*
* if (!res->allocation)
* return -ENOMEM;
*
* return 0;
* }
*
* static void test_kmalloc_free(struct test_resource *res)
* {
* kfree(res->allocation);
* }
*
* void *test_kmalloc(struct test *test, size_t size, gfp_t gfp)
* {
* struct test_kmalloc_params params;
* struct test_resource *res;
*
* params.size = size;
* params.gfp = gfp;
*
* // TODO(felixguo@google.com): The & gets interpreted via
* // Kerneldoc but we don't want that.
* res = test_alloc_resource(test, test_kmalloc_init,
* test_kmalloc_free, & params);
* if (res)
* return res->allocation;
* else
* return NULL;
* }
*/
struct test_resource {
void *allocation;
void (*free)(struct test_resource *res);
/* private: internal use only. */
struct list_head node;
};
struct test;
/**
* struct test_case - represents an individual test case.
* @run_case: the function representing the actual test case.
* @name: the name of the test case.
*
* A test case is a function with the signature, ``void (*)(struct test *)``
* that makes expectations (see EXPECT_TRUE()) about code under test. Each test
* case is associated with a &struct test_module and will be run after the
* module's init function and followed by the module's exit function.
*
* A test case should be static and should only be created with the TEST_CASE()
* macro; additionally, every array of test cases should be terminated with an
* empty test case.
*
* Example:
*
* .. code-block:: c
*
* void add_test_basic(struct test *test)
* {
* EXPECT_EQ(test, 1, add(1, 0));
* EXPECT_EQ(test, 2, add(1, 1));
* EXPECT_EQ(test, 0, add(-1, 1));
* EXPECT_EQ(test, INT_MAX, add(0, INT_MAX));
* EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN));
* }
*
* static struct test_case example_test_cases[] = {
* TEST_CASE(add_test_basic),
* {},
* };
*
*/
struct test_case {
void (*run_case)(struct test *test);
const char name[256];
/* private: internal use only. */
bool success;
};
/**
* TEST_CASE - A helper for creating a &struct test_case
* @test_name: a reference to a test case function.
*
* Takes a symbol for a function representing a test case and creates a &struct
* test_case object from it. See the documentation for &struct test_case for an
* example on how to use it.
*/
#define TEST_CASE(test_name) { .run_case = test_name, .name = #test_name }
/**
* struct test_module - describes a related collection of &struct test_case s.
* @name: the name of the test. Purely informational.
* @init: called before every test case.
* @exit: called after every test case.
* @test_cases: a null terminated array of test cases.
*
* A test_module is a collection of related &struct test_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.
*
* Every &struct test_case must be associated with a test_module for KUnit to
* run it.
*/
struct test_module {
const char name[256];
int (*init)(struct test *test);
void (*exit)(struct test *test);
struct test_case *test_cases;
};
/**
* struct test - represents a running instance of a test.
* @priv: for user to store arbitrary data. Commonly used to pass data created
* in the init function (see &struct test_module).
*
* 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.
*/
struct test {
void *priv;
/* private: internal use only. */
struct list_head resources;
const char *name;
bool success;
void (*vprintk)(const struct test *test,
const char *level,
struct va_format *vaf);
void (*fail)(struct test *test, struct test_stream *stream);
};
int test_init_test(struct test *test, const char *name);
int test_run_tests(struct test_module *module);
/**
* module_test() - used to register a &struct test_module with KUnit.
* @module: a statically allocated &struct test_module.
*
* Registers @module with the test framework. See &struct test_module for more
* information.
*/
#define module_test(module) \
static int module_test_init##module(void) \
{ \
return test_run_tests(&module); \
} \
late_initcall(module_test_init##module)
/**
* test_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.
* @context: for the user to pass in arbitrary data.
*
* Allocates a *test managed resource*, a resource which will automatically be
* cleaned up at the end of a test case. See &struct test_resource for an
* example.
*/
struct test_resource *test_alloc_resource(struct test *test,
int (*init)(struct test_resource *,
void *),
void (*free)(struct test_resource *),
void *context);
void test_free_resource(struct test *test, struct test_resource *res);
/**
* test_kmalloc() - Just like kmalloc() except the allocation is *test managed*.
* @test: The test context object.
* @size: The size in bytes of the desired memory.
* @gfp: flags passed to underlying kmalloc().
*
* Just like `kmalloc(...)`, except the allocation is managed by the test case
* and is automatically cleaned up after the test case concludes. See &struct
* test_resource for more information.
*/
void *test_kmalloc(struct test *test, size_t size, gfp_t gfp);
/**
* test_kzalloc() - Just like test_kmalloc(), but zeroes the allocation.
* @test: The test context object.
* @size: The size in bytes of the desired memory.
* @gfp: flags passed to underlying kmalloc().
*
* See kzalloc() and test_kmalloc() for more information.
*/
static inline void *test_kzalloc(struct test *test, size_t size, gfp_t gfp)
{
return test_kmalloc(test, size, gfp | __GFP_ZERO);
}
void test_cleanup(struct test *test);
void test_printk(const char *level,
const struct test *test,
const char *fmt, ...);
/**
* test_info() - Prints an INFO level message associated with the current test.
* @test: The test context object.
* @fmt: A printk() style format string.
*
* Prints an info level message associated with the test module being run. Takes
* a variable number of format parameters just like printk().
*/
#define test_info(test, fmt, ...) \
test_printk(KERN_INFO, test, fmt, ##__VA_ARGS__)
/**
* test_warn() - Prints a WARN level message associated with the current test.
* @test: The test context object.
* @fmt: A printk() style format string.
*
* See test_info().
*/
#define test_warn(test, fmt, ...) \
test_printk(KERN_WARNING, test, fmt, ##__VA_ARGS__)
/**
* test_err() - Prints an ERROR level message associated with the current test.
* @test: The test context object.
* @fmt: A printk() style format string.
*
* See test_info().
*/
#define test_err(test, fmt, ...) \
test_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
static inline struct test_stream *test_expect_start(struct test *test,
const char *file,
const char *line)
{
struct test_stream *stream = test_new_stream(test);
stream->add(stream, "EXPECTATION FAILED at %s:%s\n\t", file, line);
return stream;
}
static inline void test_expect_end(struct test *test,
bool success,
struct test_stream *stream)
{
if (!success)
test->fail(test, stream);
else
stream->clear(stream);
}
#define EXPECT_START(test) \
test_expect_start(test, __FILE__, __stringify(__LINE__))
#define EXPECT_END(test, success, stream) test_expect_end(test, success, stream)
#define EXPECT(test, success, message) do {\
struct test_stream *__stream = EXPECT_START(test); \
\
__stream->add(__stream, message); \
EXPECT_END(test, success, __stream); \
} while (0)
/**
* SUCCEED() - A no-op expectation. Only exists for code clarity.
* @test: The test context object.
*
* The opposite of FAIL(), it is an expectation that cannot fail. In other
* words, it does nothing and only exists for code clarity. See EXPECT_TRUE()
* for more information.
*/
#define SUCCEED(test) do {} while (0)
/**
* FAIL() - Always causes a test to fail when evaluated.
* @test: The test context object.
* @message: an informational message to be printed when the assertion is made.
*
* The opposite of SUCCEED(), it is an expectation that always fails. In other
* words, it always results in a failed expectation, and consequently always
* causes the test case to fail when evaluated. See EXPECT_TRUE() for more
* information.
*/
#define FAIL(test, message) EXPECT(test, false, message)
/**
* EXPECT_TRUE() - Causes a test failure when the given expression is not true.
* @test: The test context object.
* @condition: an arbitrary boolean expression. The test fails when this does
* not evaluate to true.
*
* This and expectations of the form `EXPECT_*` will cause the test case to fail
* when the specified condition is not met; however, it will not prevent the
* test case from continuing to run; this is otherwise known as an *expectation
* failure*.
*/
#define EXPECT_TRUE(test, condition) \
EXPECT(test, (condition), \
"Expected " #condition " is true, but is false.")
/**
* EXPECT_FALSE() - Causes a test failure when the expression is not false.
* @test: The test context object.
* @condition: an arbitrary boolean expression. The test fails when this does
* not evaluate to false.
*
* Sets an expectation that @condition evaluates to false. See EXPECT_TRUE() for
* more information.
*/
#define EXPECT_FALSE(test, condition) \
EXPECT(test, !(condition), \
"Expected " #condition " is false, but is true.")
static inline void test_expect_binary(struct test *test,
long long left, const char *left_name,
long long right, const char *right_name,
bool compare_result,
const char *compare_name,
const char *file,
const char *line)
{
struct test_stream *stream = test_expect_start(test, file, line);
stream->add(stream,
"Expected %s %s %s, but\n",
left_name, compare_name, right_name);
stream->add(stream, "\t\t%s == %lld\n", left_name, left);
stream->add(stream, "\t\t%s == %lld", right_name, right);
test_expect_end(test, compare_result, stream);
}
/*
* A factory macro for defining the expectations for the basic comparisons
* defined for the built in types.
*
* Unfortunately, there is no common type that all types can be promoted to for
* which all the binary operators behave the same way as for the actual types
* (for example, there is no type that long long and unsigned long long can
* both be cast to where the comparison result is preserved for all values). So
* the best we can do is do the comparison in the original types and then coerce
* everything to long long for printing; this way, the comparison behaves
* correctly and the printed out value usually makes sense without
* interpretation, but can always be interpretted to figure out the actual
* value.
*/
#define EXPECT_BINARY(test, left, condition, right) do { \
typeof(left) __left = (left); \
typeof(right) __right = (right); \
test_expect_binary(test, \
(long long) __left, #left, \
(long long) __right, #right, \
__left condition __right, #condition, \
__FILE__, __stringify(__LINE__)); \
} while (0)
/**
* EXPECT_EQ() - Sets an expectation that @left and @right are equal.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a primitive C type.
* @right: an arbitrary expression that evaluates to a primitive C type.
*
* Sets an expectation that the values that @left and @right evaluate to are
* equal. This is semantically equivalent to EXPECT_TRUE(@test, (@left) ==
* (@right)). See EXPECT_TRUE() for more information.
*/
#define EXPECT_EQ(test, left, right) EXPECT_BINARY(test, left, ==, right)
/**
* EXPECT_NE() - An expectation that @left and @right are not equal.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a primitive C type.
* @right: an arbitrary expression that evaluates to a primitive C type.
*
* Sets an expectation that the values that @left and @right evaluate to are not
* equal. This is semantically equivalent to EXPECT_TRUE(@test, (@left) !=
* (@right)). See EXPECT_TRUE() for more information.
*/
#define EXPECT_NE(test, left, right) EXPECT_BINARY(test, left, !=, right)
/**
* EXPECT_LT() - An expectation that @left is less than @right.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a primitive C type.
* @right: an arbitrary expression that evaluates to a primitive C type.
*
* Sets an expectation that the value that @left evaluates to is less than the
* value that @right evaluates to. This is semantically equivalent to
* EXPECT_TRUE(@test, (@left) < (@right)). See EXPECT_TRUE() for more
* information.
*/
#define EXPECT_LT(test, left, right) EXPECT_BINARY(test, left, <, right)
/**
* EXPECT_LE() - An expectation that @left is less than or equal to @right.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a primitive C type.
* @right: an arbitrary expression that evaluates to a primitive C type.
*
* Sets an expectation that the value that @left evaluates to is less than or
* equal to the value that @right evaluates to. Semantically this is equivalent
* to EXPECT_TRUE(@test, (@left) <= (@right)). See EXPECT_TRUE() for more
* information.
*/
#define EXPECT_LE(test, left, right) EXPECT_BINARY(test, left, <=, right)
/**
* EXPECT_GT() - An expectation that @left is greater than @right.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a primitive C type.
* @right: an arbitrary expression that evaluates to a primitive C type.
*
* Sets an expectation that the value that @left evaluates to is greater than
* the value that @right evaluates to. This is semantically equivalent to
* EXPECT_TRUE(@test, (@left) > (@right)). See EXPECT_TRUE() for more
* information.
*/
#define EXPECT_GT(test, left, right) EXPECT_BINARY(test, left, >, right)
/**
* EXPECT_GE() - An expectation that @left is greater than or equal to @right.
* @test: The test context object.
* @left: an arbitrary expression that evaluates to a primitive C type.
* @right: an arbitrary expression that evaluates to a primitive C type.
*
* Sets an expectation that the value that @left evaluates to is greater than
* the value that @right evaluates to. This is semantically equivalent to
* EXPECT_TRUE(@test, (@left) >= (@right)). See EXPECT_TRUE() for more
* information.
*/
#define EXPECT_GE(test, left, right) EXPECT_BINARY(test, left, >=, right)
/**
* EXPECT_STREQ() - An expectation that strings @left and @right are 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
* equal. This is semantically equivalent to
* EXPECT_TRUE(@test, !strcmp((@left), (@right))). See EXPECT_TRUE() for more
* information.
*/
#define EXPECT_STREQ(test, left, right) do { \
struct test_stream *__stream = EXPECT_START(test); \
typeof(left) __left = (left); \
typeof(right) __right = (right); \
\
__stream->add(__stream, "Expected " #left " == " #right ", but\n"); \
__stream->add(__stream, "\t\t%s == %s\n", #left, __left); \
__stream->add(__stream, "\t\t%s == %s\n", #right, __right); \
\
EXPECT_END(test, !strcmp(left, right), __stream); \
} while (0)
/**
* EXPECT_NOT_ERR_OR_NULL() - An expectation that @ptr is not null and not err.
* @test: The test context object.
* @ptr: an arbitrary pointer.
*
* Sets an expectation that the value that @ptr evaluates to is not null and not
* an errno stored in a pointer. This is semantically equivalent to
* EXPECT_TRUE(@test, !IS_ERR_OR_NULL(@ptr)). See EXPECT_TRUE() for more
* information.
*/
#define EXPECT_NOT_ERR_OR_NULL(test, ptr) do { \
struct test_stream *__stream = EXPECT_START(test); \
typeof(ptr) __ptr = (ptr); \
\
if (!__ptr) \
__stream->add(__stream, \
"Expected " #ptr " is not null, but is."); \
if (IS_ERR(__ptr)) \
__stream->add(__stream, \
"Expected " #ptr " is not error, but is: %ld", \
PTR_ERR(__ptr)); \
\
EXPECT_END(test, !IS_ERR_OR_NULL(__ptr), __stream); \
} while (0)
#endif /* _TEST_TEST_H */