summaryrefslogtreecommitdiffstats
path: root/lib/cpumask_kunit.c
blob: 6b62a6bdd50e3ec002ca5ad4bafaeb34401d22c0 (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
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
148
149
150
151
152
153
154
155
156
// SPDX-License-Identifier: GPL-2.0-only
/*
 * KUnit tests for cpumask.
 *
 * Author: Sander Vanheule <sander@svanheule.net>
 */

#include <kunit/test.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>

#define MASK_MSG(m) \
	"%s contains %sCPUs %*pbl", #m, (cpumask_weight(m) ? "" : "no "), \
	nr_cpumask_bits, cpumask_bits(m)

#define EXPECT_FOR_EACH_CPU_EQ(test, mask)			\
	do {							\
		const cpumask_t *m = (mask);			\
		int mask_weight = cpumask_weight(m);		\
		int cpu, iter = 0;				\
		for_each_cpu(cpu, m)				\
			iter++;					\
		KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(mask));	\
	} while (0)

#define EXPECT_FOR_EACH_CPU_OP_EQ(test, op, mask1, mask2)			\
	do {									\
		const cpumask_t *m1 = (mask1);					\
		const cpumask_t *m2 = (mask2);					\
		int weight;                                                     \
		int cpu, iter = 0;						\
		cpumask_##op(&mask_tmp, m1, m2);                                \
		weight = cpumask_weight(&mask_tmp);				\
		for_each_cpu_##op(cpu, mask1, mask2)				\
			iter++;							\
		KUNIT_EXPECT_EQ((test), weight, iter);				\
	} while (0)

#define EXPECT_FOR_EACH_CPU_WRAP_EQ(test, mask)			\
	do {							\
		const cpumask_t *m = (mask);			\
		int mask_weight = cpumask_weight(m);		\
		int cpu, iter = 0;				\
		for_each_cpu_wrap(cpu, m, nr_cpu_ids / 2)	\
			iter++;					\
		KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(mask));	\
	} while (0)

#define EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, name)		\
	do {							\
		int mask_weight = num_##name##_cpus();		\
		int cpu, iter = 0;				\
		for_each_##name##_cpu(cpu)			\
			iter++;					\
		KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(cpu_##name##_mask));	\
	} while (0)

static cpumask_t mask_empty;
static cpumask_t mask_all;
static cpumask_t mask_tmp;

static void test_cpumask_weight(struct kunit *test)
{
	KUNIT_EXPECT_TRUE_MSG(test, cpumask_empty(&mask_empty), MASK_MSG(&mask_empty));
	KUNIT_EXPECT_TRUE_MSG(test, cpumask_full(&mask_all), MASK_MSG(&mask_all));

	KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_weight(&mask_empty), MASK_MSG(&mask_empty));
	KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids, cpumask_weight(cpu_possible_mask),
			    MASK_MSG(cpu_possible_mask));
	KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids, cpumask_weight(&mask_all), MASK_MSG(&mask_all));
}

static void test_cpumask_first(struct kunit *test)
{
	KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_first(&mask_empty), MASK_MSG(&mask_empty));
	KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_first(cpu_possible_mask), MASK_MSG(cpu_possible_mask));

	KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_first_zero(&mask_empty), MASK_MSG(&mask_empty));
	KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_first_zero(cpu_possible_mask),
			    MASK_MSG(cpu_possible_mask));
}

static void test_cpumask_last(struct kunit *test)
{
	KUNIT_EXPECT_LE_MSG(test, nr_cpumask_bits, cpumask_last(&mask_empty),
			    MASK_MSG(&mask_empty));
	KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids - 1, cpumask_last(cpu_possible_mask),
			    MASK_MSG(cpu_possible_mask));
}

static void test_cpumask_next(struct kunit *test)
{
	KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_next_zero(-1, &mask_empty), MASK_MSG(&mask_empty));
	KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_next_zero(-1, cpu_possible_mask),
			    MASK_MSG(cpu_possible_mask));

	KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_next(-1, &mask_empty),
			    MASK_MSG(&mask_empty));
	KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_next(-1, cpu_possible_mask),
			    MASK_MSG(cpu_possible_mask));
}

static void test_cpumask_iterators(struct kunit *test)
{
	EXPECT_FOR_EACH_CPU_EQ(test, &mask_empty);
	EXPECT_FOR_EACH_CPU_WRAP_EQ(test, &mask_empty);
	EXPECT_FOR_EACH_CPU_OP_EQ(test, and, &mask_empty, &mask_empty);
	EXPECT_FOR_EACH_CPU_OP_EQ(test, and, cpu_possible_mask, &mask_empty);
	EXPECT_FOR_EACH_CPU_OP_EQ(test, andnot, &mask_empty, &mask_empty);

	EXPECT_FOR_EACH_CPU_EQ(test, cpu_possible_mask);
	EXPECT_FOR_EACH_CPU_WRAP_EQ(test, cpu_possible_mask);
	EXPECT_FOR_EACH_CPU_OP_EQ(test, and, cpu_possible_mask, cpu_possible_mask);
	EXPECT_FOR_EACH_CPU_OP_EQ(test, andnot, cpu_possible_mask, &mask_empty);
}

static void test_cpumask_iterators_builtin(struct kunit *test)
{
	EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, possible);

	/* Ensure the dynamic masks are stable while running the tests */
	cpu_hotplug_disable();

	EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, online);
	EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, present);

	cpu_hotplug_enable();
}

static int test_cpumask_init(struct kunit *test)
{
	cpumask_clear(&mask_empty);
	cpumask_setall(&mask_all);

	return 0;
}

static struct kunit_case test_cpumask_cases[] = {
	KUNIT_CASE(test_cpumask_weight),
	KUNIT_CASE(test_cpumask_first),
	KUNIT_CASE(test_cpumask_last),
	KUNIT_CASE(test_cpumask_next),
	KUNIT_CASE(test_cpumask_iterators),
	KUNIT_CASE(test_cpumask_iterators_builtin),
	{}
};

static struct kunit_suite test_cpumask_suite = {
	.name = "cpumask",
	.init = test_cpumask_init,
	.test_cases = test_cpumask_cases,
};
kunit_test_suite(test_cpumask_suite);

MODULE_DESCRIPTION("KUnit tests for cpumask");
MODULE_LICENSE("GPL");