1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
// 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);
}
}
}
|