Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Gabriela Bittencourt and committed by
Kees Cook
62b9ef50 4d557cb4

+77 -84
+3
fs/unicode/.kunitconfig
··· 1 + CONFIG_KUNIT=y 2 + CONFIG_UNICODE=y 3 + CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST=y
+3 -2
fs/unicode/Kconfig
··· 10 10 be a separate loadable module that gets requested only when a file 11 11 system actually use it. 12 12 13 - config UNICODE_NORMALIZATION_SELFTEST 13 + config UNICODE_NORMALIZATION_KUNIT_TEST 14 14 tristate "Test UTF-8 normalization support" 15 - depends on UNICODE 15 + depends on UNICODE && KUNIT 16 + default KUNIT_ALL_TESTS
+1 -1
fs/unicode/Makefile
··· 4 4 obj-y += unicode.o 5 5 endif 6 6 obj-$(CONFIG_UNICODE) += utf8data.o 7 - obj-$(CONFIG_UNICODE_NORMALIZATION_SELFTEST) += utf8-selftest.o 7 + obj-$(CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST) += utf8-selftest.o 8 8 9 9 unicode-y := utf8-norm.o utf8-core.o 10 10
+1 -1
fs/unicode/utf8-norm.c
··· 586 586 } 587 587 } 588 588 589 - #ifdef CONFIG_UNICODE_NORMALIZATION_SELFTEST_MODULE 589 + #if IS_MODULE(CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST) 590 590 EXPORT_SYMBOL_GPL(utf8version_is_supported); 591 591 EXPORT_SYMBOL_GPL(utf8nlen); 592 592 EXPORT_SYMBOL_GPL(utf8ncursor);
+69 -80
fs/unicode/utf8-selftest.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Kernel module for testing utf-8 support. 3 + * KUnit tests for utf-8 support. 4 4 * 5 5 * Copyright 2017 Collabora Ltd. 6 6 */ 7 7 8 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 - 10 - #include <linux/module.h> 11 - #include <linux/printk.h> 12 8 #include <linux/unicode.h> 13 - #include <linux/dcache.h> 9 + #include <kunit/test.h> 14 10 15 11 #include "utf8n.h" 16 - 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 12 33 13 static const struct { 34 14 /* UTF-8 strings in this vector _must_ be NULL-terminated. */ ··· 147 167 return utf8ncursor(u8c, um, n, s, (unsigned int)-1); 148 168 } 149 169 150 - static void check_utf8_nfdi(struct unicode_map *um) 170 + static void check_utf8_nfdi(struct kunit *test) 151 171 { 152 172 int i; 153 173 struct utf8cursor u8c; 174 + struct unicode_map *um = test->priv; 154 175 155 176 for (i = 0; i < ARRAY_SIZE(nfdi_test_data); i++) { 156 177 int len = strlen(nfdi_test_data[i].str); 157 178 int nlen = strlen(nfdi_test_data[i].dec); 158 179 int j = 0; 159 180 unsigned char c; 181 + int ret; 160 182 161 - test((utf8len(um, UTF8_NFDI, nfdi_test_data[i].str) == nlen)); 162 - test((utf8nlen(um, UTF8_NFDI, nfdi_test_data[i].str, len) == 163 - nlen)); 183 + KUNIT_EXPECT_EQ(test, utf8len(um, UTF8_NFDI, nfdi_test_data[i].str), nlen); 184 + KUNIT_EXPECT_EQ(test, utf8nlen(um, UTF8_NFDI, nfdi_test_data[i].str, len), 185 + nlen); 164 186 165 - if (utf8cursor(&u8c, um, UTF8_NFDI, nfdi_test_data[i].str) < 0) 166 - pr_err("can't create cursor\n"); 187 + 188 + ret = utf8cursor(&u8c, um, UTF8_NFDI, nfdi_test_data[i].str); 189 + KUNIT_EXPECT_TRUE_MSG(test, ret >= 0, "Can't create cursor\n"); 167 190 168 191 while ((c = utf8byte(&u8c)) > 0) { 169 - test_f((c == nfdi_test_data[i].dec[j]), 170 - "Unexpected byte 0x%x should be 0x%x\n", 171 - c, nfdi_test_data[i].dec[j]); 192 + KUNIT_EXPECT_EQ_MSG(test, c, nfdi_test_data[i].dec[j], 193 + "Unexpected byte 0x%x should be 0x%x\n", 194 + c, nfdi_test_data[i].dec[j]); 172 195 j++; 173 196 } 174 197 175 - test((j == nlen)); 198 + KUNIT_EXPECT_EQ(test, j, nlen); 176 199 } 177 200 } 178 201 179 - static void check_utf8_nfdicf(struct unicode_map *um) 202 + static void check_utf8_nfdicf(struct kunit *test) 180 203 { 181 204 int i; 182 205 struct utf8cursor u8c; 206 + struct unicode_map *um = test->priv; 183 207 184 208 for (i = 0; i < ARRAY_SIZE(nfdicf_test_data); i++) { 185 209 int len = strlen(nfdicf_test_data[i].str); 186 210 int nlen = strlen(nfdicf_test_data[i].ncf); 187 211 int j = 0; 212 + int ret; 188 213 unsigned char c; 189 214 190 - test((utf8len(um, UTF8_NFDICF, nfdicf_test_data[i].str) == 191 - nlen)); 192 - test((utf8nlen(um, UTF8_NFDICF, nfdicf_test_data[i].str, len) == 193 - nlen)); 215 + KUNIT_EXPECT_EQ(test, utf8len(um, UTF8_NFDICF, nfdicf_test_data[i].str), 216 + nlen); 217 + KUNIT_EXPECT_EQ(test, utf8nlen(um, UTF8_NFDICF, nfdicf_test_data[i].str, len), 218 + nlen); 194 219 195 - if (utf8cursor(&u8c, um, UTF8_NFDICF, 196 - nfdicf_test_data[i].str) < 0) 197 - pr_err("can't create cursor\n"); 220 + ret = utf8cursor(&u8c, um, UTF8_NFDICF, nfdicf_test_data[i].str); 221 + KUNIT_EXPECT_TRUE_MSG(test, ret >= 0, "Can't create cursor\n"); 198 222 199 223 while ((c = utf8byte(&u8c)) > 0) { 200 - test_f((c == nfdicf_test_data[i].ncf[j]), 201 - "Unexpected byte 0x%x should be 0x%x\n", 202 - c, nfdicf_test_data[i].ncf[j]); 224 + KUNIT_EXPECT_EQ_MSG(test, c, nfdicf_test_data[i].ncf[j], 225 + "Unexpected byte 0x%x should be 0x%x\n", 226 + c, nfdicf_test_data[i].ncf[j]); 203 227 j++; 204 228 } 205 229 206 - test((j == nlen)); 230 + KUNIT_EXPECT_EQ(test, j, nlen); 207 231 } 208 232 } 209 233 210 - static void check_utf8_comparisons(struct unicode_map *table) 234 + static void check_utf8_comparisons(struct kunit *test) 211 235 { 212 236 int i; 237 + struct unicode_map *um = test->priv; 213 238 214 239 for (i = 0; i < ARRAY_SIZE(nfdi_test_data); i++) { 215 240 const struct qstr s1 = {.name = nfdi_test_data[i].str, ··· 222 237 const struct qstr s2 = {.name = nfdi_test_data[i].dec, 223 238 .len = sizeof(nfdi_test_data[i].dec)}; 224 239 225 - test_f(!utf8_strncmp(table, &s1, &s2), 226 - "%s %s comparison mismatch\n", s1.name, s2.name); 240 + /* strncmp returns 0 when strings are equal */ 241 + KUNIT_EXPECT_TRUE_MSG(test, utf8_strncmp(um, &s1, &s2) == 0, 242 + "%s %s comparison mismatch\n", s1.name, s2.name); 227 243 } 228 244 229 245 for (i = 0; i < ARRAY_SIZE(nfdicf_test_data); i++) { ··· 233 247 const struct qstr s2 = {.name = nfdicf_test_data[i].ncf, 234 248 .len = sizeof(nfdicf_test_data[i].ncf)}; 235 249 236 - test_f(!utf8_strncasecmp(table, &s1, &s2), 237 - "%s %s comparison mismatch\n", s1.name, s2.name); 250 + /* strncasecmp returns 0 when strings are equal */ 251 + KUNIT_EXPECT_TRUE_MSG(test, utf8_strncasecmp(um, &s1, &s2) == 0, 252 + "%s %s comparison mismatch\n", s1.name, s2.name); 238 253 } 239 254 } 240 255 241 - static void check_supported_versions(struct unicode_map *um) 256 + static void check_supported_versions(struct kunit *test) 242 257 { 258 + struct unicode_map *um = test->priv; 243 259 /* Unicode 7.0.0 should be supported. */ 244 - test(utf8version_is_supported(um, UNICODE_AGE(7, 0, 0))); 260 + KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UNICODE_AGE(7, 0, 0))); 245 261 246 262 /* Unicode 9.0.0 should be supported. */ 247 - test(utf8version_is_supported(um, UNICODE_AGE(9, 0, 0))); 263 + KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UNICODE_AGE(9, 0, 0))); 248 264 249 265 /* Unicode 1x.0.0 (the latest version) should be supported. */ 250 - test(utf8version_is_supported(um, UTF8_LATEST)); 266 + KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UTF8_LATEST)); 251 267 252 268 /* Next versions don't exist. */ 253 - test(!utf8version_is_supported(um, UNICODE_AGE(13, 0, 0))); 254 - test(!utf8version_is_supported(um, UNICODE_AGE(0, 0, 0))); 255 - test(!utf8version_is_supported(um, UNICODE_AGE(-1, -1, -1))); 269 + KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(13, 0, 0))); 270 + KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(0, 0, 0))); 271 + KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(-1, -1, -1))); 256 272 } 257 273 258 - static int __init init_test_ucd(void) 274 + static struct kunit_case unicode_normalization_test_cases[] = { 275 + KUNIT_CASE(check_supported_versions), 276 + KUNIT_CASE(check_utf8_comparisons), 277 + KUNIT_CASE(check_utf8_nfdicf), 278 + KUNIT_CASE(check_utf8_nfdi), 279 + {} 280 + }; 281 + 282 + static int init_test_ucd(struct kunit *test) 259 283 { 260 - struct unicode_map *um; 284 + struct unicode_map *um = utf8_load(UTF8_LATEST); 261 285 262 - failed_tests = 0; 263 - total_tests = 0; 286 + test->priv = um; 264 287 265 - um = utf8_load(UTF8_LATEST); 266 - if (IS_ERR(um)) { 267 - pr_err("%s: Unable to load utf8 table.\n", __func__); 268 - return PTR_ERR(um); 269 - } 288 + KUNIT_EXPECT_EQ_MSG(test, IS_ERR(um), 0, 289 + "%s: Unable to load utf8 table.\n", __func__); 270 290 271 - check_supported_versions(um); 272 - check_utf8_nfdi(um); 273 - check_utf8_nfdicf(um); 274 - check_utf8_comparisons(um); 275 - 276 - if (!failed_tests) 277 - pr_info("All %u tests passed\n", total_tests); 278 - else 279 - pr_err("%u out of %u tests failed\n", failed_tests, 280 - total_tests); 281 - utf8_unload(um); 282 291 return 0; 283 292 } 284 293 285 - static void __exit exit_test_ucd(void) 294 + static void exit_test_ucd(struct kunit *test) 286 295 { 296 + utf8_unload(test->priv); 287 297 } 288 298 289 - module_init(init_test_ucd); 290 - module_exit(exit_test_ucd); 299 + static struct kunit_suite unicode_normalization_test_suite = { 300 + .name = "unicode_normalization", 301 + .test_cases = unicode_normalization_test_cases, 302 + .init = init_test_ucd, 303 + .exit = exit_test_ucd, 304 + }; 305 + 306 + kunit_test_suite(unicode_normalization_test_suite); 307 + 291 308 292 309 MODULE_AUTHOR("Gabriel Krisman Bertazi <krisman@collabora.co.uk>"); 293 - MODULE_DESCRIPTION("Kernel module for testing utf-8 support"); 310 + MODULE_DESCRIPTION("KUnit tests for utf-8 support."); 294 311 MODULE_LICENSE("GPL");