mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Add module attribute to the test attribute API. This attribute stores the module name associated with the test using KBUILD_MODNAME. The name of a test suite and the module name often do not match. A reference to the module name associated with the suite could be extremely helpful in running tests as modules without needing to check the codebase. This attribute will be printed for each suite. Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: Rae Moar <rmoar@google.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
147 lines
3.8 KiB
C
147 lines
3.8 KiB
C
// 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>
|
|
*/
|
|
|
|
#include <kunit/test.h>
|
|
#include <kunit/attributes.h>
|
|
|
|
/* Options for printing attributes:
|
|
* PRINT_ALWAYS - attribute is printed for every test case and suite if set
|
|
* PRINT_SUITE - attribute is printed for every suite if set but not for test cases
|
|
* PRINT_NEVER - attribute is never printed
|
|
*/
|
|
enum print_ops {
|
|
PRINT_ALWAYS,
|
|
PRINT_SUITE,
|
|
PRINT_NEVER,
|
|
};
|
|
|
|
/**
|
|
* struct kunit_attr - represents a test attribute and holds flexible
|
|
* helper functions to interact with attribute.
|
|
*
|
|
* @name: name of test attribute, eg. speed
|
|
* @get_attr: function to return attribute value given a test
|
|
* @to_string: function to return string representation of given
|
|
* attribute value
|
|
* @filter: function to indicate whether a given attribute value passes a
|
|
* filter
|
|
*/
|
|
struct kunit_attr {
|
|
const char *name;
|
|
void *(*get_attr)(void *test_or_suite, bool is_test);
|
|
const char *(*to_string)(void *attr, bool *to_free);
|
|
int (*filter)(void *attr, const char *input, int *err);
|
|
void *attr_default;
|
|
enum print_ops print;
|
|
};
|
|
|
|
/* String Lists for enum Attributes */
|
|
|
|
static const char * const speed_str_list[] = {"unset", "very_slow", "slow", "normal"};
|
|
|
|
/* To String Methods */
|
|
|
|
static const char *attr_enum_to_string(void *attr, const char * const str_list[], bool *to_free)
|
|
{
|
|
long val = (long)attr;
|
|
|
|
*to_free = false;
|
|
if (!val)
|
|
return NULL;
|
|
return str_list[val];
|
|
}
|
|
|
|
static const char *attr_speed_to_string(void *attr, bool *to_free)
|
|
{
|
|
return attr_enum_to_string(attr, speed_str_list, to_free);
|
|
}
|
|
|
|
static const char *attr_string_to_string(void *attr, bool *to_free)
|
|
{
|
|
*to_free = false;
|
|
return (char *) attr;
|
|
}
|
|
|
|
/* Get Attribute Methods */
|
|
|
|
static void *attr_speed_get(void *test_or_suite, bool is_test)
|
|
{
|
|
struct kunit_suite *suite = is_test ? NULL : test_or_suite;
|
|
struct kunit_case *test = is_test ? test_or_suite : NULL;
|
|
|
|
if (test)
|
|
return ((void *) test->attr.speed);
|
|
else
|
|
return ((void *) suite->attr.speed);
|
|
}
|
|
|
|
static void *attr_module_get(void *test_or_suite, bool is_test)
|
|
{
|
|
struct kunit_suite *suite = is_test ? NULL : test_or_suite;
|
|
struct kunit_case *test = is_test ? test_or_suite : NULL;
|
|
|
|
// Suites get their module attribute from their first test_case
|
|
if (test)
|
|
return ((void *) test->module_name);
|
|
else
|
|
return ((void *) suite->test_cases[0].module_name);
|
|
}
|
|
|
|
/* List of all Test Attributes */
|
|
|
|
static struct kunit_attr kunit_attr_list[] = {
|
|
{
|
|
.name = "speed",
|
|
.get_attr = attr_speed_get,
|
|
.to_string = attr_speed_to_string,
|
|
.attr_default = (void *)KUNIT_SPEED_NORMAL,
|
|
.print = PRINT_ALWAYS,
|
|
},
|
|
{
|
|
.name = "module",
|
|
.get_attr = attr_module_get,
|
|
.to_string = attr_string_to_string,
|
|
.attr_default = (void *)"",
|
|
.print = PRINT_SUITE,
|
|
}
|
|
};
|
|
|
|
/* Helper Functions to Access Attributes */
|
|
|
|
void kunit_print_attr(void *test_or_suite, bool is_test, unsigned int test_level)
|
|
{
|
|
int i;
|
|
bool to_free;
|
|
void *attr;
|
|
const char *attr_name, *attr_str;
|
|
struct kunit_suite *suite = is_test ? NULL : test_or_suite;
|
|
struct kunit_case *test = is_test ? test_or_suite : NULL;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(kunit_attr_list); i++) {
|
|
if (kunit_attr_list[i].print == PRINT_NEVER ||
|
|
(test && kunit_attr_list[i].print == PRINT_SUITE))
|
|
continue;
|
|
attr = kunit_attr_list[i].get_attr(test_or_suite, is_test);
|
|
if (attr) {
|
|
attr_name = kunit_attr_list[i].name;
|
|
attr_str = kunit_attr_list[i].to_string(attr, &to_free);
|
|
if (test) {
|
|
kunit_log(KERN_INFO, test, "%*s# %s.%s: %s",
|
|
KUNIT_INDENT_LEN * test_level, "", test->name,
|
|
attr_name, attr_str);
|
|
} else {
|
|
kunit_log(KERN_INFO, suite, "%*s# %s: %s",
|
|
KUNIT_INDENT_LEN * test_level, "", attr_name, attr_str);
|
|
}
|
|
|
|
/* Free to_string of attribute if needed */
|
|
if (to_free)
|
|
kfree(attr_str);
|
|
}
|
|
}
|
|
}
|