Skip to content

Commit 33d599f

Browse files
M-Vaittinenbroonie
authored andcommitted
lib/test_linear_ranges: add a test for the 'linear_ranges'
Add a KUnit test for the linear_ranges helper. Signed-off-by: Matti Vaittinen <[email protected]> Reviewed-by: Brendan Higgins <[email protected]> Link: https://lore.kernel.org/r/311fea741bafdcd33804d3187c1642e24275e3e5.1588944082.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Mark Brown <[email protected]>
1 parent d2218d4 commit 33d599f

File tree

3 files changed

+241
-0
lines changed

3 files changed

+241
-0
lines changed

lib/Kconfig.debug

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,18 @@ config LIST_KUNIT_TEST
20922092

20932093
If unsure, say N.
20942094

2095+
config LINEAR_RANGES_TEST
2096+
tristate "KUnit test for linear_ranges"
2097+
depends on KUNIT
2098+
select LINEAR_RANGES
2099+
help
2100+
This builds the linear_ranges unit test, which runs on boot.
2101+
Tests the linear_ranges logic correctness.
2102+
For more information on KUnit and unit tests in general please refer
2103+
to the KUnit documentation in Documentation/dev-tools/kunit/.
2104+
2105+
If unsure, say N.
2106+
20952107
config TEST_UDELAY
20962108
tristate "udelay test driver"
20972109
help

lib/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,4 @@ obj-$(CONFIG_OBJAGG) += objagg.o
310310

311311
# KUnit tests
312312
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
313+
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o

lib/test_linear_ranges.c

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* KUnit test for the linear_ranges helper.
4+
*
5+
* Copyright (C) 2020, ROHM Semiconductors.
6+
* Author: Matti Vaittinen <[email protected]>
7+
*/
8+
#include <kunit/test.h>
9+
10+
#include <linux/linear_range.h>
11+
12+
/* First things first. I deeply dislike unit-tests. I have seen all the hell
13+
* breaking loose when people who think the unit tests are "the silver bullet"
14+
* to kill bugs get to decide how a company should implement testing strategy...
15+
*
16+
* Believe me, it may get _really_ ridiculous. It is tempting to think that
17+
* walking through all the possible execution branches will nail down 100% of
18+
* bugs. This may lead to ideas about demands to get certain % of "test
19+
* coverage" - measured as line coverage. And that is one of the worst things
20+
* you can do.
21+
*
22+
* Ask people to provide line coverage and they do. I've seen clever tools
23+
* which generate test cases to test the existing functions - and by default
24+
* these tools expect code to be correct and just generate checks which are
25+
* passing when ran against current code-base. Run this generator and you'll get
26+
* tests that do not test code is correct but just verify nothing changes.
27+
* Problem is that testing working code is pointless. And if it is not
28+
* working, your test must not assume it is working. You won't catch any bugs
29+
* by such tests. What you can do is to generate a huge amount of tests.
30+
* Especially if you were are asked to proivde 100% line-coverage x_x. So what
31+
* does these tests - which are not finding any bugs now - do?
32+
*
33+
* They add inertia to every future development. I think it was Terry Pratchet
34+
* who wrote someone having same impact as thick syrup has to chronometre.
35+
* Excessive amount of unit-tests have this effect to development. If you do
36+
* actually find _any_ bug from code in such environment and try fixing it...
37+
* ...chances are you also need to fix the test cases. In sunny day you fix one
38+
* test. But I've done refactoring which resulted 500+ broken tests (which had
39+
* really zero value other than proving to managers that we do do "quality")...
40+
*
41+
* After this being said - there are situations where UTs can be handy. If you
42+
* have algorithms which take some input and should produce output - then you
43+
* can implement few, carefully selected simple UT-cases which test this. I've
44+
* previously used this for example for netlink and device-tree data parsing
45+
* functions. Feed some data examples to functions and verify the output is as
46+
* expected. I am not covering all the cases but I will see the logic should be
47+
* working.
48+
*
49+
* Here we also do some minor testing. I don't want to go through all branches
50+
* or test more or less obvious things - but I want to see the main logic is
51+
* working. And I definitely don't want to add 500+ test cases that break when
52+
* some simple fix is done x_x. So - let's only add few, well selected tests
53+
* which ensure as much logic is good as possible.
54+
*/
55+
56+
/*
57+
* Test Range 1:
58+
* selectors: 2 3 4 5 6
59+
* values (5): 10 20 30 40 50
60+
*
61+
* Test Range 2:
62+
* selectors: 7 8 9 10
63+
* values (4): 100 150 200 250
64+
*/
65+
66+
#define RANGE1_MIN 10
67+
#define RANGE1_MIN_SEL 2
68+
#define RANGE1_STEP 10
69+
70+
/* 2, 3, 4, 5, 6 */
71+
static const unsigned int range1_sels[] = { RANGE1_MIN_SEL, RANGE1_MIN_SEL + 1,
72+
RANGE1_MIN_SEL + 2,
73+
RANGE1_MIN_SEL + 3,
74+
RANGE1_MIN_SEL + 4 };
75+
/* 10, 20, 30, 40, 50 */
76+
static const unsigned int range1_vals[] = { RANGE1_MIN, RANGE1_MIN +
77+
RANGE1_STEP,
78+
RANGE1_MIN + RANGE1_STEP * 2,
79+
RANGE1_MIN + RANGE1_STEP * 3,
80+
RANGE1_MIN + RANGE1_STEP * 4 };
81+
82+
#define RANGE2_MIN 100
83+
#define RANGE2_MIN_SEL 7
84+
#define RANGE2_STEP 50
85+
86+
/* 7, 8, 9, 10 */
87+
static const unsigned int range2_sels[] = { RANGE2_MIN_SEL, RANGE2_MIN_SEL + 1,
88+
RANGE2_MIN_SEL + 2,
89+
RANGE2_MIN_SEL + 3 };
90+
/* 100, 150, 200, 250 */
91+
static const unsigned int range2_vals[] = { RANGE2_MIN, RANGE2_MIN +
92+
RANGE2_STEP,
93+
RANGE2_MIN + RANGE2_STEP * 2,
94+
RANGE2_MIN + RANGE2_STEP * 3 };
95+
96+
#define RANGE1_NUM_VALS (ARRAY_SIZE(range1_vals))
97+
#define RANGE2_NUM_VALS (ARRAY_SIZE(range2_vals))
98+
#define RANGE_NUM_VALS (RANGE1_NUM_VALS + RANGE2_NUM_VALS)
99+
100+
#define RANGE1_MAX_SEL (RANGE1_MIN_SEL + RANGE1_NUM_VALS - 1)
101+
#define RANGE1_MAX_VAL (range1_vals[RANGE1_NUM_VALS - 1])
102+
103+
#define RANGE2_MAX_SEL (RANGE2_MIN_SEL + RANGE2_NUM_VALS - 1)
104+
#define RANGE2_MAX_VAL (range2_vals[RANGE2_NUM_VALS - 1])
105+
106+
#define SMALLEST_SEL RANGE1_MIN_SEL
107+
#define SMALLEST_VAL RANGE1_MIN
108+
109+
static struct linear_range testr[] = {
110+
{
111+
.min = RANGE1_MIN,
112+
.min_sel = RANGE1_MIN_SEL,
113+
.max_sel = RANGE1_MAX_SEL,
114+
.step = RANGE1_STEP,
115+
}, {
116+
.min = RANGE2_MIN,
117+
.min_sel = RANGE2_MIN_SEL,
118+
.max_sel = RANGE2_MAX_SEL,
119+
.step = RANGE2_STEP
120+
},
121+
};
122+
123+
static void range_test_get_value(struct kunit *test)
124+
{
125+
int ret, i;
126+
unsigned int sel, val;
127+
128+
for (i = 0; i < RANGE1_NUM_VALS; i++) {
129+
sel = range1_sels[i];
130+
ret = linear_range_get_value_array(&testr[0], 2, sel, &val);
131+
KUNIT_EXPECT_EQ(test, 0, ret);
132+
KUNIT_EXPECT_EQ(test, val, range1_vals[i]);
133+
}
134+
for (i = 0; i < RANGE2_NUM_VALS; i++) {
135+
sel = range2_sels[i];
136+
ret = linear_range_get_value_array(&testr[0], 2, sel, &val);
137+
KUNIT_EXPECT_EQ(test, 0, ret);
138+
KUNIT_EXPECT_EQ(test, val, range2_vals[i]);
139+
}
140+
ret = linear_range_get_value_array(&testr[0], 2, sel + 1, &val);
141+
KUNIT_EXPECT_NE(test, 0, ret);
142+
}
143+
144+
static void range_test_get_selector_high(struct kunit *test)
145+
{
146+
int ret, i;
147+
unsigned int sel;
148+
bool found;
149+
150+
for (i = 0; i < RANGE1_NUM_VALS; i++) {
151+
ret = linear_range_get_selector_high(&testr[0], range1_vals[i],
152+
&sel, &found);
153+
KUNIT_EXPECT_EQ(test, 0, ret);
154+
KUNIT_EXPECT_EQ(test, sel, range1_sels[i]);
155+
KUNIT_EXPECT_TRUE(test, found);
156+
}
157+
158+
ret = linear_range_get_selector_high(&testr[0], RANGE1_MAX_VAL + 1,
159+
&sel, &found);
160+
KUNIT_EXPECT_LE(test, ret, 0);
161+
162+
ret = linear_range_get_selector_high(&testr[0], RANGE1_MIN - 1,
163+
&sel, &found);
164+
KUNIT_EXPECT_EQ(test, 0, ret);
165+
KUNIT_EXPECT_FALSE(test, found);
166+
KUNIT_EXPECT_EQ(test, sel, range1_sels[0]);
167+
}
168+
169+
static void range_test_get_value_amount(struct kunit *test)
170+
{
171+
int ret;
172+
173+
ret = linear_range_values_in_range_array(&testr[0], 2);
174+
KUNIT_EXPECT_EQ(test, (int)RANGE_NUM_VALS, ret);
175+
}
176+
177+
static void range_test_get_selector_low(struct kunit *test)
178+
{
179+
int i, ret;
180+
unsigned int sel;
181+
bool found;
182+
183+
for (i = 0; i < RANGE1_NUM_VALS; i++) {
184+
ret = linear_range_get_selector_low_array(&testr[0], 2,
185+
range1_vals[i], &sel,
186+
&found);
187+
KUNIT_EXPECT_EQ(test, 0, ret);
188+
KUNIT_EXPECT_EQ(test, sel, range1_sels[i]);
189+
KUNIT_EXPECT_TRUE(test, found);
190+
}
191+
for (i = 0; i < RANGE2_NUM_VALS; i++) {
192+
ret = linear_range_get_selector_low_array(&testr[0], 2,
193+
range2_vals[i], &sel,
194+
&found);
195+
KUNIT_EXPECT_EQ(test, 0, ret);
196+
KUNIT_EXPECT_EQ(test, sel, range2_sels[i]);
197+
KUNIT_EXPECT_TRUE(test, found);
198+
}
199+
200+
/*
201+
* Seek value greater than range max => get_selector_*_low should
202+
* return Ok - but set found to false as value is not in range
203+
*/
204+
ret = linear_range_get_selector_low_array(&testr[0], 2,
205+
range2_vals[RANGE2_NUM_VALS - 1] + 1,
206+
&sel, &found);
207+
208+
KUNIT_EXPECT_EQ(test, 0, ret);
209+
KUNIT_EXPECT_EQ(test, sel, range2_sels[RANGE2_NUM_VALS - 1]);
210+
KUNIT_EXPECT_FALSE(test, found);
211+
}
212+
213+
static struct kunit_case range_test_cases[] = {
214+
KUNIT_CASE(range_test_get_value_amount),
215+
KUNIT_CASE(range_test_get_selector_high),
216+
KUNIT_CASE(range_test_get_selector_low),
217+
KUNIT_CASE(range_test_get_value),
218+
{},
219+
};
220+
221+
static struct kunit_suite range_test_module = {
222+
.name = "linear-ranges-test",
223+
.test_cases = range_test_cases,
224+
};
225+
226+
kunit_test_suites(&range_test_module);
227+
228+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)