summaryrefslogtreecommitdiff
path: root/lib/kunit/attributes.c
blob: ffd0d692b334d18c0f4e5d7769876b5ada97af27 (plain)
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
// 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);
}

/* 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);
}

/* 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,
	},
};

/* 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);
		}
	}
}