Skip to content

Commit 62b9ef5

Browse files
gbittencourtkees
authored andcommitted
unicode: kunit: refactor selftest to kunit tests
Refactoring 'test' functions into kunit tests, to test utf-8 support in unicode subsystem. This allows the utf8 tests to be run alongside the KUnit test suite using kunit-tool, quickly compiling and running all desired tests as part of the KUnit test suite, instead of compiling the selftest module and loading it. The refactoring kept the original testing logic intact, while adopting a testing pattern across different kernel modules and leveraging KUnit's benefits. Co-developed-by: Pedro Orlando <porlando@lkcamp.dev> Signed-off-by: Pedro Orlando <porlando@lkcamp.dev> Co-developed-by: Danilo Pereira <dpereira@lkcamp.dev> Signed-off-by: Danilo Pereira <dpereira@lkcamp.dev> Signed-off-by: Gabriela Bittencourt <gbittencourt@lkcamp.dev> Reviewed-by: David Gow <davidgow@google.com> Acked-by: Gabriel Krisman Bertazi <krisman@suse.de> Reviewed-by: Rae Moar <rmoar@google.com> Link: https://lore.kernel.org/r/20241202075545.3648096-6-davidgow@google.com Signed-off-by: Kees Cook <kees@kernel.org>
1 parent 4d557cb commit 62b9ef5

5 files changed

Lines changed: 77 additions & 84 deletions

File tree

fs/unicode/.kunitconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_KUNIT=y
2+
CONFIG_UNICODE=y
3+
CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST=y

fs/unicode/Kconfig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ config UNICODE
1010
be a separate loadable module that gets requested only when a file
1111
system actually use it.
1212

13-
config UNICODE_NORMALIZATION_SELFTEST
13+
config UNICODE_NORMALIZATION_KUNIT_TEST
1414
tristate "Test UTF-8 normalization support"
15-
depends on UNICODE
15+
depends on UNICODE && KUNIT
16+
default KUNIT_ALL_TESTS

fs/unicode/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ifneq ($(CONFIG_UNICODE),)
44
obj-y += unicode.o
55
endif
66
obj-$(CONFIG_UNICODE) += utf8data.o
7-
obj-$(CONFIG_UNICODE_NORMALIZATION_SELFTEST) += utf8-selftest.o
7+
obj-$(CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST) += utf8-selftest.o
88

99
unicode-y := utf8-norm.o utf8-core.o
1010

fs/unicode/utf8-norm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ int utf8byte(struct utf8cursor *u8c)
586586
}
587587
}
588588

589-
#ifdef CONFIG_UNICODE_NORMALIZATION_SELFTEST_MODULE
589+
#if IS_MODULE(CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST)
590590
EXPORT_SYMBOL_GPL(utf8version_is_supported);
591591
EXPORT_SYMBOL_GPL(utf8nlen);
592592
EXPORT_SYMBOL_GPL(utf8ncursor);

fs/unicode/utf8-selftest.c

Lines changed: 69 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,15 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Kernel module for testing utf-8 support.
3+
* KUnit tests for utf-8 support.
44
*
55
* Copyright 2017 Collabora Ltd.
66
*/
77

8-
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9-
10-
#include <linux/module.h>
11-
#include <linux/printk.h>
128
#include <linux/unicode.h>
13-
#include <linux/dcache.h>
9+
#include <kunit/test.h>
1410

1511
#include "utf8n.h"
1612

17-
static unsigned int failed_tests;
18-
static unsigned int total_tests;
19-
20-
#define _test(cond, func, line, fmt, ...) do { \
21-
total_tests++; \
22-
if (!cond) { \
23-
failed_tests++; \
24-
pr_err("test %s:%d Failed: %s%s", \
25-
func, line, #cond, (fmt?":":".")); \
26-
if (fmt) \
27-
pr_err(fmt, ##__VA_ARGS__); \
28-
} \
29-
} while (0)
30-
#define test_f(cond, fmt, ...) _test(cond, __func__, __LINE__, fmt, ##__VA_ARGS__)
31-
#define test(cond) _test(cond, __func__, __LINE__, "")
32-
3313
static const struct {
3414
/* UTF-8 strings in this vector _must_ be NULL-terminated. */
3515
unsigned char str[10];
@@ -167,78 +147,84 @@ static int utf8cursor(struct utf8cursor *u8c, const struct unicode_map *um,
167147
return utf8ncursor(u8c, um, n, s, (unsigned int)-1);
168148
}
169149

170-
static void check_utf8_nfdi(struct unicode_map *um)
150+
static void check_utf8_nfdi(struct kunit *test)
171151
{
172152
int i;
173153
struct utf8cursor u8c;
154+
struct unicode_map *um = test->priv;
174155

175156
for (i = 0; i < ARRAY_SIZE(nfdi_test_data); i++) {
176157
int len = strlen(nfdi_test_data[i].str);
177158
int nlen = strlen(nfdi_test_data[i].dec);
178159
int j = 0;
179160
unsigned char c;
161+
int ret;
162+
163+
KUNIT_EXPECT_EQ(test, utf8len(um, UTF8_NFDI, nfdi_test_data[i].str), nlen);
164+
KUNIT_EXPECT_EQ(test, utf8nlen(um, UTF8_NFDI, nfdi_test_data[i].str, len),
165+
nlen);
180166

181-
test((utf8len(um, UTF8_NFDI, nfdi_test_data[i].str) == nlen));
182-
test((utf8nlen(um, UTF8_NFDI, nfdi_test_data[i].str, len) ==
183-
nlen));
184167

185-
if (utf8cursor(&u8c, um, UTF8_NFDI, nfdi_test_data[i].str) < 0)
186-
pr_err("can't create cursor\n");
168+
ret = utf8cursor(&u8c, um, UTF8_NFDI, nfdi_test_data[i].str);
169+
KUNIT_EXPECT_TRUE_MSG(test, ret >= 0, "Can't create cursor\n");
187170

188171
while ((c = utf8byte(&u8c)) > 0) {
189-
test_f((c == nfdi_test_data[i].dec[j]),
190-
"Unexpected byte 0x%x should be 0x%x\n",
191-
c, nfdi_test_data[i].dec[j]);
172+
KUNIT_EXPECT_EQ_MSG(test, c, nfdi_test_data[i].dec[j],
173+
"Unexpected byte 0x%x should be 0x%x\n",
174+
c, nfdi_test_data[i].dec[j]);
192175
j++;
193176
}
194177

195-
test((j == nlen));
178+
KUNIT_EXPECT_EQ(test, j, nlen);
196179
}
197180
}
198181

199-
static void check_utf8_nfdicf(struct unicode_map *um)
182+
static void check_utf8_nfdicf(struct kunit *test)
200183
{
201184
int i;
202185
struct utf8cursor u8c;
186+
struct unicode_map *um = test->priv;
203187

204188
for (i = 0; i < ARRAY_SIZE(nfdicf_test_data); i++) {
205189
int len = strlen(nfdicf_test_data[i].str);
206190
int nlen = strlen(nfdicf_test_data[i].ncf);
207191
int j = 0;
192+
int ret;
208193
unsigned char c;
209194

210-
test((utf8len(um, UTF8_NFDICF, nfdicf_test_data[i].str) ==
211-
nlen));
212-
test((utf8nlen(um, UTF8_NFDICF, nfdicf_test_data[i].str, len) ==
213-
nlen));
195+
KUNIT_EXPECT_EQ(test, utf8len(um, UTF8_NFDICF, nfdicf_test_data[i].str),
196+
nlen);
197+
KUNIT_EXPECT_EQ(test, utf8nlen(um, UTF8_NFDICF, nfdicf_test_data[i].str, len),
198+
nlen);
214199

215-
if (utf8cursor(&u8c, um, UTF8_NFDICF,
216-
nfdicf_test_data[i].str) < 0)
217-
pr_err("can't create cursor\n");
200+
ret = utf8cursor(&u8c, um, UTF8_NFDICF, nfdicf_test_data[i].str);
201+
KUNIT_EXPECT_TRUE_MSG(test, ret >= 0, "Can't create cursor\n");
218202

219203
while ((c = utf8byte(&u8c)) > 0) {
220-
test_f((c == nfdicf_test_data[i].ncf[j]),
221-
"Unexpected byte 0x%x should be 0x%x\n",
222-
c, nfdicf_test_data[i].ncf[j]);
204+
KUNIT_EXPECT_EQ_MSG(test, c, nfdicf_test_data[i].ncf[j],
205+
"Unexpected byte 0x%x should be 0x%x\n",
206+
c, nfdicf_test_data[i].ncf[j]);
223207
j++;
224208
}
225209

226-
test((j == nlen));
210+
KUNIT_EXPECT_EQ(test, j, nlen);
227211
}
228212
}
229213

230-
static void check_utf8_comparisons(struct unicode_map *table)
214+
static void check_utf8_comparisons(struct kunit *test)
231215
{
232216
int i;
217+
struct unicode_map *um = test->priv;
233218

234219
for (i = 0; i < ARRAY_SIZE(nfdi_test_data); i++) {
235220
const struct qstr s1 = {.name = nfdi_test_data[i].str,
236221
.len = sizeof(nfdi_test_data[i].str)};
237222
const struct qstr s2 = {.name = nfdi_test_data[i].dec,
238223
.len = sizeof(nfdi_test_data[i].dec)};
239224

240-
test_f(!utf8_strncmp(table, &s1, &s2),
241-
"%s %s comparison mismatch\n", s1.name, s2.name);
225+
/* strncmp returns 0 when strings are equal */
226+
KUNIT_EXPECT_TRUE_MSG(test, utf8_strncmp(um, &s1, &s2) == 0,
227+
"%s %s comparison mismatch\n", s1.name, s2.name);
242228
}
243229

244230
for (i = 0; i < ARRAY_SIZE(nfdicf_test_data); i++) {
@@ -247,62 +233,65 @@ static void check_utf8_comparisons(struct unicode_map *table)
247233
const struct qstr s2 = {.name = nfdicf_test_data[i].ncf,
248234
.len = sizeof(nfdicf_test_data[i].ncf)};
249235

250-
test_f(!utf8_strncasecmp(table, &s1, &s2),
251-
"%s %s comparison mismatch\n", s1.name, s2.name);
236+
/* strncasecmp returns 0 when strings are equal */
237+
KUNIT_EXPECT_TRUE_MSG(test, utf8_strncasecmp(um, &s1, &s2) == 0,
238+
"%s %s comparison mismatch\n", s1.name, s2.name);
252239
}
253240
}
254241

255-
static void check_supported_versions(struct unicode_map *um)
242+
static void check_supported_versions(struct kunit *test)
256243
{
244+
struct unicode_map *um = test->priv;
257245
/* Unicode 7.0.0 should be supported. */
258-
test(utf8version_is_supported(um, UNICODE_AGE(7, 0, 0)));
246+
KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UNICODE_AGE(7, 0, 0)));
259247

260248
/* Unicode 9.0.0 should be supported. */
261-
test(utf8version_is_supported(um, UNICODE_AGE(9, 0, 0)));
249+
KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UNICODE_AGE(9, 0, 0)));
262250

263251
/* Unicode 1x.0.0 (the latest version) should be supported. */
264-
test(utf8version_is_supported(um, UTF8_LATEST));
252+
KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UTF8_LATEST));
265253

266254
/* Next versions don't exist. */
267-
test(!utf8version_is_supported(um, UNICODE_AGE(13, 0, 0)));
268-
test(!utf8version_is_supported(um, UNICODE_AGE(0, 0, 0)));
269-
test(!utf8version_is_supported(um, UNICODE_AGE(-1, -1, -1)));
255+
KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(13, 0, 0)));
256+
KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(0, 0, 0)));
257+
KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(-1, -1, -1)));
270258
}
271259

272-
static int __init init_test_ucd(void)
260+
static struct kunit_case unicode_normalization_test_cases[] = {
261+
KUNIT_CASE(check_supported_versions),
262+
KUNIT_CASE(check_utf8_comparisons),
263+
KUNIT_CASE(check_utf8_nfdicf),
264+
KUNIT_CASE(check_utf8_nfdi),
265+
{}
266+
};
267+
268+
static int init_test_ucd(struct kunit *test)
273269
{
274-
struct unicode_map *um;
270+
struct unicode_map *um = utf8_load(UTF8_LATEST);
275271

276-
failed_tests = 0;
277-
total_tests = 0;
272+
test->priv = um;
278273

279-
um = utf8_load(UTF8_LATEST);
280-
if (IS_ERR(um)) {
281-
pr_err("%s: Unable to load utf8 table.\n", __func__);
282-
return PTR_ERR(um);
283-
}
274+
KUNIT_EXPECT_EQ_MSG(test, IS_ERR(um), 0,
275+
"%s: Unable to load utf8 table.\n", __func__);
284276

285-
check_supported_versions(um);
286-
check_utf8_nfdi(um);
287-
check_utf8_nfdicf(um);
288-
check_utf8_comparisons(um);
289-
290-
if (!failed_tests)
291-
pr_info("All %u tests passed\n", total_tests);
292-
else
293-
pr_err("%u out of %u tests failed\n", failed_tests,
294-
total_tests);
295-
utf8_unload(um);
296277
return 0;
297278
}
298279

299-
static void __exit exit_test_ucd(void)
280+
static void exit_test_ucd(struct kunit *test)
300281
{
282+
utf8_unload(test->priv);
301283
}
302284

303-
module_init(init_test_ucd);
304-
module_exit(exit_test_ucd);
285+
static struct kunit_suite unicode_normalization_test_suite = {
286+
.name = "unicode_normalization",
287+
.test_cases = unicode_normalization_test_cases,
288+
.init = init_test_ucd,
289+
.exit = exit_test_ucd,
290+
};
291+
292+
kunit_test_suite(unicode_normalization_test_suite);
293+
305294

306295
MODULE_AUTHOR("Gabriel Krisman Bertazi <krisman@collabora.co.uk>");
307-
MODULE_DESCRIPTION("Kernel module for testing utf-8 support");
296+
MODULE_DESCRIPTION("KUnit tests for utf-8 support.");
308297
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)