mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
move-lib-kunit for v6.15-rc1
- move lib/ selftests into lib/tests/ (Kees Cook, Gabriela Bittencourt, Luis Felipe Hernandez, Lukas Bulwahn, Tamir Duberstein) - lib/math: Add int_log test suite (Bruno Sobreira França) - lib/math: Add Kunit test suite for gcd() (Yu-Chun Lin) - lib/tests/kfifo_kunit.c: add tests for the kfifo structure (Diego Vieira) - unicode: refactor selftests into KUnit (Gabriela Bittencourt) - lib/prime_numbers: convert self-test to KUnit (Tamir Duberstein) - printf: convert self-test to KUnit (Tamir Duberstein) - scanf: convert self-test to KUnit (Tamir Duberstein) -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCZ9hCvgAKCRA2KwveOeQk u1nzAP9F/vQZUPkU9ADuqdcbyyEXlTzNk8R5rC2e1w+uKzJx+QD9EAbeCv9ZLdC0 KQF0pWVYCJtiSMEhkiMS/bMmpRCgwQ8= =VYZG -----END PGP SIGNATURE----- Merge tag 'move-lib-kunit-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux Pull lib kunit selftest move from Kees Cook: "This is a one-off tree to coordinate the move of selftests out of lib/ and into lib/tests/. A separate tree was used for this to keep the paths sane with all the work in the same place. - move lib/ selftests into lib/tests/ (Kees Cook, Gabriela Bittencourt, Luis Felipe Hernandez, Lukas Bulwahn, Tamir Duberstein) - lib/math: Add int_log test suite (Bruno Sobreira França) - lib/math: Add Kunit test suite for gcd() (Yu-Chun Lin) - lib/tests/kfifo_kunit.c: add tests for the kfifo structure (Diego Vieira) - unicode: refactor selftests into KUnit (Gabriela Bittencourt) - lib/prime_numbers: convert self-test to KUnit (Tamir Duberstein) - printf: convert self-test to KUnit (Tamir Duberstein) - scanf: convert self-test to KUnit (Tamir Duberstein)" * tag 'move-lib-kunit-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (21 commits) scanf: break kunit into test cases scanf: convert self-test to KUnit scanf: remove redundant debug logs scanf: implicate test line in failure messages printf: implicate test line in failure messages printf: break kunit into test cases printf: convert self-test to KUnit kunit/fortify: Replace "volatile" with OPTIMIZER_HIDE_VAR() kunit/fortify: Expand testing of __compiletime_strlen() kunit/stackinit: Use fill byte different from Clang i386 pattern kunit/overflow: Fix DEFINE_FLEX tests for counted_by selftests: remove reference to prime_numbers.sh MAINTAINERS: adjust entries in FORTIFY_SOURCE and KERNEL HARDENING lib/prime_numbers: convert self-test to KUnit lib/math: Add Kunit test suite for gcd() unicode: kunit: change tests filename and path unicode: kunit: refactor selftest to kunit tests lib/tests/kfifo_kunit.c: add tests for the kfifo structure lib: Move KUnit tests into tests/ subdirectory lib/math: Add int_log test suite ...
This commit is contained in:
commit
06961fbbbd
|
@ -661,7 +661,7 @@ Do *not* use it from C.
|
|||
Thanks
|
||||
======
|
||||
|
||||
If you add other %p extensions, please extend <lib/test_printf.c> with
|
||||
one or more test cases, if at all feasible.
|
||||
If you add other %p extensions, please extend <lib/tests/printf_kunit.c>
|
||||
with one or more test cases, if at all feasible.
|
||||
|
||||
Thank you for your cooperation and attention.
|
||||
|
|
|
@ -347,7 +347,7 @@ kselftest. We use kselftests for lib/ as an example.
|
|||
1. Create the test module
|
||||
|
||||
2. Create the test script that will run (load/unload) the module
|
||||
e.g. ``tools/testing/selftests/lib/printf.sh``
|
||||
e.g. ``tools/testing/selftests/lib/bitmap.sh``
|
||||
|
||||
3. Add line to config file e.g. ``tools/testing/selftests/lib/config``
|
||||
|
||||
|
|
24
MAINTAINERS
24
MAINTAINERS
|
@ -4014,10 +4014,10 @@ F: include/vdso/bits.h
|
|||
F: lib/bitmap-str.c
|
||||
F: lib/bitmap.c
|
||||
F: lib/cpumask.c
|
||||
F: lib/cpumask_kunit.c
|
||||
F: lib/find_bit.c
|
||||
F: lib/find_bit_benchmark.c
|
||||
F: lib/test_bitmap.c
|
||||
F: lib/tests/cpumask_kunit.c
|
||||
F: tools/include/linux/bitfield.h
|
||||
F: tools/include/linux/bitmap.h
|
||||
F: tools/include/linux/bits.h
|
||||
|
@ -9075,9 +9075,9 @@ L: linux-hardening@vger.kernel.org
|
|||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
|
||||
F: include/linux/fortify-string.h
|
||||
F: lib/fortify_kunit.c
|
||||
F: lib/memcpy_kunit.c
|
||||
F: lib/test_fortify/*
|
||||
F: lib/tests/fortify_kunit.c
|
||||
F: lib/tests/memcpy_kunit.c
|
||||
K: \bunsafe_memcpy\b
|
||||
K: \b__NO_FORTIFY\b
|
||||
|
||||
|
@ -9762,9 +9762,9 @@ F: include/linux/string.h
|
|||
F: include/linux/string_choices.h
|
||||
F: include/linux/string_helpers.h
|
||||
F: lib/string.c
|
||||
F: lib/string_kunit.c
|
||||
F: lib/string_helpers.c
|
||||
F: lib/string_helpers_kunit.c
|
||||
F: lib/tests/string_helpers_kunit.c
|
||||
F: lib/tests/string_kunit.c
|
||||
F: scripts/coccinelle/api/string_choices.cocci
|
||||
|
||||
GENERIC UIO DRIVER FOR PCI DEVICES
|
||||
|
@ -12592,7 +12592,7 @@ F: arch/*/configs/hardening.config
|
|||
F: include/linux/overflow.h
|
||||
F: include/linux/randomize_kstack.h
|
||||
F: kernel/configs/hardening.config
|
||||
F: lib/usercopy_kunit.c
|
||||
F: lib/tests/usercopy_kunit.c
|
||||
F: mm/usercopy.c
|
||||
F: security/Kconfig.hardening
|
||||
K: \b(add|choose)_random_kstack_offset\b
|
||||
|
@ -12990,7 +12990,7 @@ F: Documentation/trace/kprobes.rst
|
|||
F: include/asm-generic/kprobes.h
|
||||
F: include/linux/kprobes.h
|
||||
F: kernel/kprobes.c
|
||||
F: lib/test_kprobes.c
|
||||
F: lib/tests/test_kprobes.c
|
||||
F: samples/kprobes
|
||||
|
||||
KS0108 LCD CONTROLLER DRIVER
|
||||
|
@ -13320,7 +13320,7 @@ M: Mark Brown <broonie@kernel.org>
|
|||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
F: include/linux/linear_range.h
|
||||
F: lib/linear_ranges.c
|
||||
F: lib/test_linear_ranges.c
|
||||
F: lib/tests/test_linear_ranges.c
|
||||
|
||||
LINUX FOR POWER MACINTOSH
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
|
@ -13448,7 +13448,7 @@ M: David Gow <davidgow@google.com>
|
|||
L: linux-kselftest@vger.kernel.org
|
||||
L: kunit-dev@googlegroups.com
|
||||
S: Maintained
|
||||
F: lib/list-test.c
|
||||
F: lib/tests/list-test.c
|
||||
|
||||
LITEX PLATFORM
|
||||
M: Karol Gugala <kgugala@antmicro.com>
|
||||
|
@ -21778,7 +21778,7 @@ M: Jason A. Donenfeld <Jason@zx2c4.com>
|
|||
S: Maintained
|
||||
F: include/linux/siphash.h
|
||||
F: lib/siphash.c
|
||||
F: lib/siphash_kunit.c
|
||||
F: lib/tests/siphash_kunit.c
|
||||
|
||||
SIS 190 ETHERNET DRIVER
|
||||
M: Francois Romieu <romieu@fr.zoreil.com>
|
||||
|
@ -25453,8 +25453,8 @@ R: Sergey Senozhatsky <senozhatsky@chromium.org>
|
|||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git
|
||||
F: Documentation/core-api/printk-formats.rst
|
||||
F: lib/test_printf.c
|
||||
F: lib/test_scanf.c
|
||||
F: lib/tests/printf_kunit.c
|
||||
F: lib/tests/scanf_kunit.c
|
||||
F: lib/vsprintf.c
|
||||
|
||||
VT1211 HARDWARE MONITOR DRIVER
|
||||
|
|
|
@ -10,6 +10,7 @@ config UNICODE
|
|||
be a separate loadable module that gets requested only when a file
|
||||
system actually use it.
|
||||
|
||||
config UNICODE_NORMALIZATION_SELFTEST
|
||||
config UNICODE_NORMALIZATION_KUNIT_TEST
|
||||
tristate "Test UTF-8 normalization support"
|
||||
depends on UNICODE
|
||||
depends on UNICODE && KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
|
|
|
@ -4,7 +4,7 @@ ifneq ($(CONFIG_UNICODE),)
|
|||
obj-y += unicode.o
|
||||
endif
|
||||
obj-$(CONFIG_UNICODE) += utf8data.o
|
||||
obj-$(CONFIG_UNICODE_NORMALIZATION_SELFTEST) += utf8-selftest.o
|
||||
obj-$(CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST) += tests/utf8_kunit.o
|
||||
|
||||
unicode-y := utf8-norm.o utf8-core.o
|
||||
|
||||
|
|
3
fs/unicode/tests/.kunitconfig
Normal file
3
fs/unicode/tests/.kunitconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_KUNIT=y
|
||||
CONFIG_UNICODE=y
|
||||
CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST=y
|
|
@ -1,34 +1,14 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Kernel module for testing utf-8 support.
|
||||
* KUnit tests for utf-8 support.
|
||||
*
|
||||
* Copyright 2017 Collabora Ltd.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/unicode.h>
|
||||
#include <linux/dcache.h>
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include "utf8n.h"
|
||||
|
||||
static unsigned int failed_tests;
|
||||
static unsigned int total_tests;
|
||||
|
||||
#define _test(cond, func, line, fmt, ...) do { \
|
||||
total_tests++; \
|
||||
if (!cond) { \
|
||||
failed_tests++; \
|
||||
pr_err("test %s:%d Failed: %s%s", \
|
||||
func, line, #cond, (fmt?":":".")); \
|
||||
if (fmt) \
|
||||
pr_err(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define test_f(cond, fmt, ...) _test(cond, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define test(cond) _test(cond, __func__, __LINE__, "")
|
||||
#include "../utf8n.h"
|
||||
|
||||
static const struct {
|
||||
/* UTF-8 strings in this vector _must_ be NULL-terminated. */
|
||||
|
@ -167,69 +147,74 @@ static int utf8cursor(struct utf8cursor *u8c, const struct unicode_map *um,
|
|||
return utf8ncursor(u8c, um, n, s, (unsigned int)-1);
|
||||
}
|
||||
|
||||
static void check_utf8_nfdi(struct unicode_map *um)
|
||||
static void check_utf8_nfdi(struct kunit *test)
|
||||
{
|
||||
int i;
|
||||
struct utf8cursor u8c;
|
||||
struct unicode_map *um = test->priv;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nfdi_test_data); i++) {
|
||||
int len = strlen(nfdi_test_data[i].str);
|
||||
int nlen = strlen(nfdi_test_data[i].dec);
|
||||
int j = 0;
|
||||
unsigned char c;
|
||||
int ret;
|
||||
|
||||
test((utf8len(um, UTF8_NFDI, nfdi_test_data[i].str) == nlen));
|
||||
test((utf8nlen(um, UTF8_NFDI, nfdi_test_data[i].str, len) ==
|
||||
nlen));
|
||||
KUNIT_EXPECT_EQ(test, utf8len(um, UTF8_NFDI, nfdi_test_data[i].str), nlen);
|
||||
KUNIT_EXPECT_EQ(test, utf8nlen(um, UTF8_NFDI, nfdi_test_data[i].str, len),
|
||||
nlen);
|
||||
|
||||
if (utf8cursor(&u8c, um, UTF8_NFDI, nfdi_test_data[i].str) < 0)
|
||||
pr_err("can't create cursor\n");
|
||||
|
||||
ret = utf8cursor(&u8c, um, UTF8_NFDI, nfdi_test_data[i].str);
|
||||
KUNIT_EXPECT_TRUE_MSG(test, ret >= 0, "Can't create cursor\n");
|
||||
|
||||
while ((c = utf8byte(&u8c)) > 0) {
|
||||
test_f((c == nfdi_test_data[i].dec[j]),
|
||||
"Unexpected byte 0x%x should be 0x%x\n",
|
||||
c, nfdi_test_data[i].dec[j]);
|
||||
KUNIT_EXPECT_EQ_MSG(test, c, nfdi_test_data[i].dec[j],
|
||||
"Unexpected byte 0x%x should be 0x%x\n",
|
||||
c, nfdi_test_data[i].dec[j]);
|
||||
j++;
|
||||
}
|
||||
|
||||
test((j == nlen));
|
||||
KUNIT_EXPECT_EQ(test, j, nlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_utf8_nfdicf(struct unicode_map *um)
|
||||
static void check_utf8_nfdicf(struct kunit *test)
|
||||
{
|
||||
int i;
|
||||
struct utf8cursor u8c;
|
||||
struct unicode_map *um = test->priv;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nfdicf_test_data); i++) {
|
||||
int len = strlen(nfdicf_test_data[i].str);
|
||||
int nlen = strlen(nfdicf_test_data[i].ncf);
|
||||
int j = 0;
|
||||
int ret;
|
||||
unsigned char c;
|
||||
|
||||
test((utf8len(um, UTF8_NFDICF, nfdicf_test_data[i].str) ==
|
||||
nlen));
|
||||
test((utf8nlen(um, UTF8_NFDICF, nfdicf_test_data[i].str, len) ==
|
||||
nlen));
|
||||
KUNIT_EXPECT_EQ(test, utf8len(um, UTF8_NFDICF, nfdicf_test_data[i].str),
|
||||
nlen);
|
||||
KUNIT_EXPECT_EQ(test, utf8nlen(um, UTF8_NFDICF, nfdicf_test_data[i].str, len),
|
||||
nlen);
|
||||
|
||||
if (utf8cursor(&u8c, um, UTF8_NFDICF,
|
||||
nfdicf_test_data[i].str) < 0)
|
||||
pr_err("can't create cursor\n");
|
||||
ret = utf8cursor(&u8c, um, UTF8_NFDICF, nfdicf_test_data[i].str);
|
||||
KUNIT_EXPECT_TRUE_MSG(test, ret >= 0, "Can't create cursor\n");
|
||||
|
||||
while ((c = utf8byte(&u8c)) > 0) {
|
||||
test_f((c == nfdicf_test_data[i].ncf[j]),
|
||||
"Unexpected byte 0x%x should be 0x%x\n",
|
||||
c, nfdicf_test_data[i].ncf[j]);
|
||||
KUNIT_EXPECT_EQ_MSG(test, c, nfdicf_test_data[i].ncf[j],
|
||||
"Unexpected byte 0x%x should be 0x%x\n",
|
||||
c, nfdicf_test_data[i].ncf[j]);
|
||||
j++;
|
||||
}
|
||||
|
||||
test((j == nlen));
|
||||
KUNIT_EXPECT_EQ(test, j, nlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_utf8_comparisons(struct unicode_map *table)
|
||||
static void check_utf8_comparisons(struct kunit *test)
|
||||
{
|
||||
int i;
|
||||
struct unicode_map *um = test->priv;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nfdi_test_data); i++) {
|
||||
const struct qstr s1 = {.name = nfdi_test_data[i].str,
|
||||
|
@ -237,8 +222,9 @@ static void check_utf8_comparisons(struct unicode_map *table)
|
|||
const struct qstr s2 = {.name = nfdi_test_data[i].dec,
|
||||
.len = sizeof(nfdi_test_data[i].dec)};
|
||||
|
||||
test_f(!utf8_strncmp(table, &s1, &s2),
|
||||
"%s %s comparison mismatch\n", s1.name, s2.name);
|
||||
/* strncmp returns 0 when strings are equal */
|
||||
KUNIT_EXPECT_TRUE_MSG(test, utf8_strncmp(um, &s1, &s2) == 0,
|
||||
"%s %s comparison mismatch\n", s1.name, s2.name);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nfdicf_test_data); i++) {
|
||||
|
@ -247,62 +233,65 @@ static void check_utf8_comparisons(struct unicode_map *table)
|
|||
const struct qstr s2 = {.name = nfdicf_test_data[i].ncf,
|
||||
.len = sizeof(nfdicf_test_data[i].ncf)};
|
||||
|
||||
test_f(!utf8_strncasecmp(table, &s1, &s2),
|
||||
"%s %s comparison mismatch\n", s1.name, s2.name);
|
||||
/* strncasecmp returns 0 when strings are equal */
|
||||
KUNIT_EXPECT_TRUE_MSG(test, utf8_strncasecmp(um, &s1, &s2) == 0,
|
||||
"%s %s comparison mismatch\n", s1.name, s2.name);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_supported_versions(struct unicode_map *um)
|
||||
static void check_supported_versions(struct kunit *test)
|
||||
{
|
||||
struct unicode_map *um = test->priv;
|
||||
/* Unicode 7.0.0 should be supported. */
|
||||
test(utf8version_is_supported(um, UNICODE_AGE(7, 0, 0)));
|
||||
KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UNICODE_AGE(7, 0, 0)));
|
||||
|
||||
/* Unicode 9.0.0 should be supported. */
|
||||
test(utf8version_is_supported(um, UNICODE_AGE(9, 0, 0)));
|
||||
KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UNICODE_AGE(9, 0, 0)));
|
||||
|
||||
/* Unicode 1x.0.0 (the latest version) should be supported. */
|
||||
test(utf8version_is_supported(um, UTF8_LATEST));
|
||||
KUNIT_EXPECT_TRUE(test, utf8version_is_supported(um, UTF8_LATEST));
|
||||
|
||||
/* Next versions don't exist. */
|
||||
test(!utf8version_is_supported(um, UNICODE_AGE(13, 0, 0)));
|
||||
test(!utf8version_is_supported(um, UNICODE_AGE(0, 0, 0)));
|
||||
test(!utf8version_is_supported(um, UNICODE_AGE(-1, -1, -1)));
|
||||
KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(13, 0, 0)));
|
||||
KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(0, 0, 0)));
|
||||
KUNIT_EXPECT_FALSE(test, utf8version_is_supported(um, UNICODE_AGE(-1, -1, -1)));
|
||||
}
|
||||
|
||||
static int __init init_test_ucd(void)
|
||||
static struct kunit_case unicode_normalization_test_cases[] = {
|
||||
KUNIT_CASE(check_supported_versions),
|
||||
KUNIT_CASE(check_utf8_comparisons),
|
||||
KUNIT_CASE(check_utf8_nfdicf),
|
||||
KUNIT_CASE(check_utf8_nfdi),
|
||||
{}
|
||||
};
|
||||
|
||||
static int init_test_ucd(struct kunit *test)
|
||||
{
|
||||
struct unicode_map *um;
|
||||
struct unicode_map *um = utf8_load(UTF8_LATEST);
|
||||
|
||||
failed_tests = 0;
|
||||
total_tests = 0;
|
||||
test->priv = um;
|
||||
|
||||
um = utf8_load(UTF8_LATEST);
|
||||
if (IS_ERR(um)) {
|
||||
pr_err("%s: Unable to load utf8 table.\n", __func__);
|
||||
return PTR_ERR(um);
|
||||
}
|
||||
KUNIT_EXPECT_EQ_MSG(test, IS_ERR(um), 0,
|
||||
"%s: Unable to load utf8 table.\n", __func__);
|
||||
|
||||
check_supported_versions(um);
|
||||
check_utf8_nfdi(um);
|
||||
check_utf8_nfdicf(um);
|
||||
check_utf8_comparisons(um);
|
||||
|
||||
if (!failed_tests)
|
||||
pr_info("All %u tests passed\n", total_tests);
|
||||
else
|
||||
pr_err("%u out of %u tests failed\n", failed_tests,
|
||||
total_tests);
|
||||
utf8_unload(um);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_test_ucd(void)
|
||||
static void exit_test_ucd(struct kunit *test)
|
||||
{
|
||||
utf8_unload(test->priv);
|
||||
}
|
||||
|
||||
module_init(init_test_ucd);
|
||||
module_exit(exit_test_ucd);
|
||||
static struct kunit_suite unicode_normalization_test_suite = {
|
||||
.name = "unicode_normalization",
|
||||
.test_cases = unicode_normalization_test_cases,
|
||||
.init = init_test_ucd,
|
||||
.exit = exit_test_ucd,
|
||||
};
|
||||
|
||||
kunit_test_suite(unicode_normalization_test_suite);
|
||||
|
||||
|
||||
MODULE_AUTHOR("Gabriel Krisman Bertazi <krisman@collabora.co.uk>");
|
||||
MODULE_DESCRIPTION("Kernel module for testing utf-8 support");
|
||||
MODULE_DESCRIPTION("KUnit tests for utf-8 support.");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -586,7 +586,7 @@ ccc_mismatch:
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UNICODE_NORMALIZATION_SELFTEST_MODULE
|
||||
#if IS_MODULE(CONFIG_UNICODE_NORMALIZATION_KUNIT_TEST)
|
||||
EXPORT_SYMBOL_GPL(utf8version_is_supported);
|
||||
EXPORT_SYMBOL_GPL(utf8nlen);
|
||||
EXPORT_SYMBOL_GPL(utf8ncursor);
|
||||
|
|
|
@ -2436,6 +2436,24 @@ config ASYNC_RAID6_TEST
|
|||
config TEST_HEXDUMP
|
||||
tristate "Test functions located in the hexdump module at runtime"
|
||||
|
||||
config PRINTF_KUNIT_TEST
|
||||
tristate "KUnit test printf() family of functions at runtime" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable this option to test the printf functions at runtime.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SCANF_KUNIT_TEST
|
||||
tristate "KUnit test scanf() family of functions at runtime" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable this option to test the scanf functions at runtime.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config STRING_KUNIT_TEST
|
||||
tristate "KUnit test string functions at runtime" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
|
@ -2449,12 +2467,6 @@ config STRING_HELPERS_KUNIT_TEST
|
|||
config TEST_KSTRTOX
|
||||
tristate "Test kstrto*() family of functions at runtime"
|
||||
|
||||
config TEST_PRINTF
|
||||
tristate "Test printf() family of functions at runtime"
|
||||
|
||||
config TEST_SCANF
|
||||
tristate "Test scanf() family of functions at runtime"
|
||||
|
||||
config TEST_BITMAP
|
||||
tristate "Test bitmap_*() family of functions at runtime"
|
||||
help
|
||||
|
@ -2700,6 +2712,20 @@ config SYSCTL_KUNIT_TEST
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config KFIFO_KUNIT_TEST
|
||||
tristate "KUnit Test for the generic kernel FIFO implementation" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This builds the generic FIFO implementation KUnit test suite.
|
||||
It tests that the API and basic functionality of the kfifo type
|
||||
and associated macros.
|
||||
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config LIST_KUNIT_TEST
|
||||
tristate "KUnit Test for Kernel Linked-list structures" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
|
@ -3175,7 +3201,7 @@ config TEST_OBJPOOL
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config INT_POW_TEST
|
||||
config INT_POW_KUNIT_TEST
|
||||
tristate "Integer exponentiation (int_pow) test" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
|
@ -3206,6 +3232,44 @@ config INT_SQRT_KUNIT_TEST
|
|||
|
||||
If unsure, say N
|
||||
|
||||
config INT_LOG_KUNIT_TEST
|
||||
tristate "Integer log (int_log) test" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This option enables the KUnit test suite for the int_log library, which
|
||||
provides two functions to compute the integer logarithm in base 2 and
|
||||
base 10, called respectively as intlog2 and intlog10.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
config GCD_KUNIT_TEST
|
||||
tristate "Greatest common divisor test" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This option enables the KUnit test suite for the gcd() function,
|
||||
which computes the greatest common divisor of two numbers.
|
||||
|
||||
This test suite verifies the correctness of gcd() across various
|
||||
scenarios, including edge cases.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
config PRIME_NUMBERS_KUNIT_TEST
|
||||
tristate "Prime number generator test" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
select PRIME_NUMBERS
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This option enables the KUnit test suite for the {is,next}_prime_number
|
||||
functions.
|
||||
|
||||
Enabling this option will include tests that compare the prime number
|
||||
generator functions against a brute force implementation.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
endif # RUNTIME_TESTING_MENU
|
||||
|
||||
config ARCH_USE_MEMTEST
|
||||
|
|
41
lib/Makefile
41
lib/Makefile
|
@ -52,9 +52,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
|
|||
percpu-refcount.o rhashtable.o base64.o \
|
||||
once.o refcount.o rcuref.o usercopy.o errseq.o bucket_locks.o \
|
||||
generic-radix-tree.o bitmap-str.o
|
||||
obj-$(CONFIG_STRING_KUNIT_TEST) += string_kunit.o
|
||||
obj-y += string_helpers.o
|
||||
obj-$(CONFIG_STRING_HELPERS_KUNIT_TEST) += string_helpers_kunit.o
|
||||
obj-y += hexdump.o
|
||||
obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
|
||||
obj-y += kstrtox.o
|
||||
|
@ -65,27 +63,20 @@ obj-$(CONFIG_TEST_DHRY) += test_dhry.o
|
|||
obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
|
||||
obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
|
||||
CFLAGS_test_bitops.o += -Werror
|
||||
obj-$(CONFIG_CPUMASK_KUNIT_TEST) += cpumask_kunit.o
|
||||
obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
|
||||
obj-$(CONFIG_TEST_IOV_ITER) += kunit_iov_iter.o
|
||||
obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o
|
||||
obj-$(CONFIG_TEST_IDA) += test_ida.o
|
||||
obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o
|
||||
CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla)
|
||||
CFLAGS_test_ubsan.o += $(call cc-disable-warning, unused-but-set-variable)
|
||||
UBSAN_SANITIZE_test_ubsan.o := y
|
||||
obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
|
||||
obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
|
||||
obj-$(CONFIG_TEST_MIN_HEAP) += test_min_heap.o
|
||||
obj-$(CONFIG_TEST_LKM) += test_module.o
|
||||
obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o
|
||||
obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
|
||||
obj-$(CONFIG_TEST_SORT) += test_sort.o
|
||||
obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
|
||||
obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
|
||||
obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o
|
||||
obj-$(CONFIG_TEST_PRINTF) += test_printf.o
|
||||
obj-$(CONFIG_TEST_SCANF) += test_scanf.o
|
||||
|
||||
obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
|
||||
ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_KASAN),yy)
|
||||
|
@ -98,7 +89,6 @@ obj-$(CONFIG_TEST_XARRAY) += test_xarray.o
|
|||
obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o
|
||||
obj-$(CONFIG_TEST_PARMAN) += test_parman.o
|
||||
obj-$(CONFIG_TEST_KMOD) += test_kmod.o
|
||||
obj-$(CONFIG_TEST_RUNTIME) += tests/
|
||||
obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o
|
||||
obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o
|
||||
obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o
|
||||
|
@ -107,10 +97,7 @@ obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o
|
|||
obj-$(CONFIG_TEST_LOCKUP) += test_lockup.o
|
||||
obj-$(CONFIG_TEST_HMM) += test_hmm.o
|
||||
obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o
|
||||
obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
|
||||
obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o
|
||||
CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE)
|
||||
obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o
|
||||
obj-$(CONFIG_TEST_OBJPOOL) += test_objpool.o
|
||||
|
||||
obj-$(CONFIG_TEST_FPU) += test_fpu.o
|
||||
|
@ -132,7 +119,7 @@ endif
|
|||
obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o
|
||||
CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any)
|
||||
|
||||
obj-y += math/ crypto/
|
||||
obj-y += math/ crypto/ tests/
|
||||
|
||||
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
|
||||
obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
|
||||
|
@ -368,32 +355,6 @@ obj-$(CONFIG_OBJAGG) += objagg.o
|
|||
# pldmfw library
|
||||
obj-$(CONFIG_PLDMFW) += pldmfw/
|
||||
|
||||
# KUnit tests
|
||||
CFLAGS_bitfield_kunit.o := $(DISABLE_STRUCTLEAK_PLUGIN)
|
||||
obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
|
||||
obj-$(CONFIG_CHECKSUM_KUNIT) += checksum_kunit.o
|
||||
obj-$(CONFIG_UTIL_MACROS_KUNIT) += util_macros_kunit.o
|
||||
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
|
||||
obj-$(CONFIG_HASHTABLE_KUNIT_TEST) += hashtable_test.o
|
||||
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
|
||||
obj-$(CONFIG_BITS_TEST) += test_bits.o
|
||||
obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o
|
||||
obj-$(CONFIG_SLUB_KUNIT_TEST) += slub_kunit.o
|
||||
obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
|
||||
obj-$(CONFIG_IS_SIGNED_TYPE_KUNIT_TEST) += is_signed_type_kunit.o
|
||||
CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
|
||||
obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
|
||||
CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)
|
||||
obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o
|
||||
CFLAGS_fortify_kunit.o += $(call cc-disable-warning, unsequenced)
|
||||
CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-overread)
|
||||
CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-truncation)
|
||||
CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN)
|
||||
obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
|
||||
obj-$(CONFIG_CRC_KUNIT_TEST) += crc_kunit.o
|
||||
obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
|
||||
obj-$(CONFIG_USERCOPY_KUNIT_TEST) += usercopy_kunit.o
|
||||
|
||||
obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
|
||||
|
||||
obj-$(CONFIG_FIRMWARE_TABLE) += fw_table.o
|
||||
|
|
|
@ -5,8 +5,7 @@ obj-$(CONFIG_CORDIC) += cordic.o
|
|||
obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o
|
||||
obj-$(CONFIG_RATIONAL) += rational.o
|
||||
|
||||
obj-$(CONFIG_INT_POW_TEST) += tests/int_pow_kunit.o
|
||||
obj-$(CONFIG_TEST_DIV64) += test_div64.o
|
||||
obj-$(CONFIG_TEST_MULDIV64) += test_mul_u64_u64_div_u64.o
|
||||
obj-$(CONFIG_RATIONAL_KUNIT_TEST) += rational-test.o
|
||||
obj-$(CONFIG_INT_SQRT_KUNIT_TEST) += tests/int_sqrt_kunit.o
|
||||
|
||||
obj-y += tests/
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#define pr_fmt(fmt) "prime numbers: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/prime_numbers.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct primes {
|
||||
struct rcu_head rcu;
|
||||
unsigned long last, sz;
|
||||
unsigned long primes[];
|
||||
};
|
||||
#include "prime_numbers_private.h"
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
static const struct primes small_primes = {
|
||||
|
@ -62,9 +57,25 @@ static const struct primes small_primes = {
|
|||
static DEFINE_MUTEX(lock);
|
||||
static const struct primes __rcu *primes = RCU_INITIALIZER(&small_primes);
|
||||
|
||||
static unsigned long selftest_max;
|
||||
#if IS_ENABLED(CONFIG_PRIME_NUMBERS_KUNIT_TEST)
|
||||
/*
|
||||
* Calls the callback under RCU lock. The callback must not retain
|
||||
* the primes pointer.
|
||||
*/
|
||||
void with_primes(void *ctx, primes_fn fn)
|
||||
{
|
||||
rcu_read_lock();
|
||||
fn(ctx, rcu_dereference(primes));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(with_primes);
|
||||
|
||||
static bool slow_is_prime_number(unsigned long x)
|
||||
EXPORT_SYMBOL(slow_is_prime_number);
|
||||
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
bool slow_is_prime_number(unsigned long x)
|
||||
{
|
||||
unsigned long y = int_sqrt(x);
|
||||
|
||||
|
@ -239,77 +250,13 @@ bool is_prime_number(unsigned long x)
|
|||
}
|
||||
EXPORT_SYMBOL(is_prime_number);
|
||||
|
||||
static void dump_primes(void)
|
||||
{
|
||||
const struct primes *p;
|
||||
char *buf;
|
||||
|
||||
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
|
||||
rcu_read_lock();
|
||||
p = rcu_dereference(primes);
|
||||
|
||||
if (buf)
|
||||
bitmap_print_to_pagebuf(true, buf, p->primes, p->sz);
|
||||
pr_info("primes.{last=%lu, .sz=%lu, .primes[]=...x%lx} = %s\n",
|
||||
p->last, p->sz, p->primes[BITS_TO_LONGS(p->sz) - 1], buf);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static int selftest(unsigned long max)
|
||||
{
|
||||
unsigned long x, last;
|
||||
|
||||
if (!max)
|
||||
return 0;
|
||||
|
||||
for (last = 0, x = 2; x < max; x++) {
|
||||
bool slow = slow_is_prime_number(x);
|
||||
bool fast = is_prime_number(x);
|
||||
|
||||
if (slow != fast) {
|
||||
pr_err("inconsistent result for is-prime(%lu): slow=%s, fast=%s!\n",
|
||||
x, slow ? "yes" : "no", fast ? "yes" : "no");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!slow)
|
||||
continue;
|
||||
|
||||
if (next_prime_number(last) != x) {
|
||||
pr_err("incorrect result for next-prime(%lu): expected %lu, got %lu\n",
|
||||
last, x, next_prime_number(last));
|
||||
goto err;
|
||||
}
|
||||
last = x;
|
||||
}
|
||||
|
||||
pr_info("%s(%lu) passed, last prime was %lu\n", __func__, x, last);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dump_primes();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __init primes_init(void)
|
||||
{
|
||||
return selftest(selftest_max);
|
||||
}
|
||||
|
||||
static void __exit primes_exit(void)
|
||||
{
|
||||
free_primes();
|
||||
}
|
||||
|
||||
module_init(primes_init);
|
||||
module_exit(primes_exit);
|
||||
|
||||
module_param_named(selftest, selftest_max, ulong, 0400);
|
||||
|
||||
MODULE_AUTHOR("Intel Corporation");
|
||||
MODULE_DESCRIPTION("Prime number library");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
16
lib/math/prime_numbers_private.h
Normal file
16
lib/math/prime_numbers_private.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct primes {
|
||||
struct rcu_head rcu;
|
||||
unsigned long last, sz;
|
||||
unsigned long primes[];
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_PRIME_NUMBERS_KUNIT_TEST)
|
||||
typedef void (*primes_fn)(void *, const struct primes *);
|
||||
|
||||
void with_primes(void *ctx, primes_fn fn);
|
||||
bool slow_is_prime_number(unsigned long x);
|
||||
#endif
|
|
@ -1,4 +1,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_INT_POW_TEST) += int_pow_kunit.o
|
||||
obj-$(CONFIG_INT_SQRT_KUNIT_TEST) += int_sqrt_kunit.o
|
||||
obj-$(CONFIG_GCD_KUNIT_TEST) += gcd_kunit.o
|
||||
obj-$(CONFIG_INT_LOG_KUNIT_TEST) += int_log_kunit.o
|
||||
obj-$(CONFIG_INT_POW_KUNIT_TEST) += int_pow_kunit.o
|
||||
obj-$(CONFIG_INT_SQRT_KUNIT_TEST) += int_sqrt_kunit.o
|
||||
obj-$(CONFIG_PRIME_NUMBERS_KUNIT_TEST) += prime_numbers_kunit.o
|
||||
obj-$(CONFIG_RATIONAL_KUNIT_TEST) += rational_kunit.o
|
||||
|
|
56
lib/math/tests/gcd_kunit.c
Normal file
56
lib/math/tests/gcd_kunit.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/gcd.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
struct test_case_params {
|
||||
unsigned long val1;
|
||||
unsigned long val2;
|
||||
unsigned long expected_result;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct test_case_params params[] = {
|
||||
{ 48, 18, 6, "GCD of 48 and 18" },
|
||||
{ 18, 48, 6, "GCD of 18 and 48" },
|
||||
{ 56, 98, 14, "GCD of 56 and 98" },
|
||||
{ 17, 13, 1, "Coprime numbers" },
|
||||
{ 101, 103, 1, "Coprime numbers" },
|
||||
{ 270, 192, 6, "GCD of 270 and 192" },
|
||||
{ 0, 5, 5, "GCD with zero" },
|
||||
{ 7, 0, 7, "GCD with zero reversed" },
|
||||
{ 36, 36, 36, "GCD of identical numbers" },
|
||||
{ ULONG_MAX, 1, 1, "GCD of max ulong and 1" },
|
||||
{ ULONG_MAX, ULONG_MAX, ULONG_MAX, "GCD of max ulong values" },
|
||||
};
|
||||
|
||||
static void get_desc(const struct test_case_params *tc, char *desc)
|
||||
{
|
||||
strscpy(desc, tc->name, KUNIT_PARAM_DESC_SIZE);
|
||||
}
|
||||
|
||||
KUNIT_ARRAY_PARAM(gcd, params, get_desc);
|
||||
|
||||
static void gcd_test(struct kunit *test)
|
||||
{
|
||||
const struct test_case_params *tc = (const struct test_case_params *)test->param_value;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, tc->expected_result, gcd(tc->val1, tc->val2));
|
||||
}
|
||||
|
||||
static struct kunit_case math_gcd_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(gcd_test, gcd_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite gcd_test_suite = {
|
||||
.name = "math-gcd",
|
||||
.test_cases = math_gcd_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(gcd_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("math.gcd KUnit test suite");
|
||||
MODULE_AUTHOR("Yu-Chun Lin <eleanor15x@gmail.com>");
|
74
lib/math/tests/int_log_kunit.c
Normal file
74
lib/math/tests/int_log_kunit.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <kunit/test.h>
|
||||
#include <linux/int_log.h>
|
||||
|
||||
struct test_case_params {
|
||||
u32 value;
|
||||
unsigned int expected_result;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
|
||||
/* The expected result takes into account the log error */
|
||||
static const struct test_case_params intlog2_params[] = {
|
||||
{0, 0, "Log base 2 of 0"},
|
||||
{1, 0, "Log base 2 of 1"},
|
||||
{2, 16777216, "Log base 2 of 2"},
|
||||
{3, 26591232, "Log base 2 of 3"},
|
||||
{4, 33554432, "Log base 2 of 4"},
|
||||
{8, 50331648, "Log base 2 of 8"},
|
||||
{16, 67108864, "Log base 2 of 16"},
|
||||
{32, 83886080, "Log base 2 of 32"},
|
||||
{U32_MAX, 536870911, "Log base 2 of MAX"},
|
||||
};
|
||||
|
||||
static const struct test_case_params intlog10_params[] = {
|
||||
{0, 0, "Log base 10 of 0"},
|
||||
{1, 0, "Log base 10 of 1"},
|
||||
{6, 13055203, "Log base 10 of 6"},
|
||||
{10, 16777225, "Log base 10 of 10"},
|
||||
{100, 33554450, "Log base 10 of 100"},
|
||||
{1000, 50331675, "Log base 10 of 1000"},
|
||||
{10000, 67108862, "Log base 10 of 10000"},
|
||||
{U32_MAX, 161614247, "Log base 10 of MAX"}
|
||||
};
|
||||
|
||||
static void get_desc(const struct test_case_params *tc, char *desc)
|
||||
{
|
||||
strscpy(desc, tc->name, KUNIT_PARAM_DESC_SIZE);
|
||||
}
|
||||
|
||||
|
||||
KUNIT_ARRAY_PARAM(intlog2, intlog2_params, get_desc);
|
||||
|
||||
static void intlog2_test(struct kunit *test)
|
||||
{
|
||||
const struct test_case_params *tc = (const struct test_case_params *)test->param_value;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, tc->expected_result, intlog2(tc->value));
|
||||
}
|
||||
|
||||
KUNIT_ARRAY_PARAM(intlog10, intlog10_params, get_desc);
|
||||
|
||||
static void intlog10_test(struct kunit *test)
|
||||
{
|
||||
const struct test_case_params *tc = (const struct test_case_params *)test->param_value;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, tc->expected_result, intlog10(tc->value));
|
||||
}
|
||||
|
||||
static struct kunit_case math_int_log_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(intlog2_test, intlog2_gen_params),
|
||||
KUNIT_CASE_PARAM(intlog10_test, intlog10_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite int_log_test_suite = {
|
||||
.name = "math-int_log",
|
||||
.test_cases = math_int_log_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&int_log_test_suite);
|
||||
|
||||
MODULE_DESCRIPTION("math.int_log KUnit test suite");
|
||||
MODULE_LICENSE("GPL");
|
59
lib/math/tests/prime_numbers_kunit.c
Normal file
59
lib/math/tests/prime_numbers_kunit.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/prime_numbers.h>
|
||||
|
||||
#include "../prime_numbers_private.h"
|
||||
|
||||
static void dump_primes(void *ctx, const struct primes *p)
|
||||
{
|
||||
static char buf[PAGE_SIZE];
|
||||
struct kunit_suite *suite = ctx;
|
||||
|
||||
bitmap_print_to_pagebuf(true, buf, p->primes, p->sz);
|
||||
kunit_info(suite, "primes.{last=%lu, .sz=%lu, .primes[]=...x%lx} = %s",
|
||||
p->last, p->sz, p->primes[BITS_TO_LONGS(p->sz) - 1], buf);
|
||||
}
|
||||
|
||||
static void prime_numbers_test(struct kunit *test)
|
||||
{
|
||||
const unsigned long max = 65536;
|
||||
unsigned long x, last, next;
|
||||
|
||||
for (last = 0, x = 2; x < max; x++) {
|
||||
const bool slow = slow_is_prime_number(x);
|
||||
const bool fast = is_prime_number(x);
|
||||
|
||||
KUNIT_ASSERT_EQ_MSG(test, slow, fast, "is-prime(%lu)", x);
|
||||
|
||||
if (!slow)
|
||||
continue;
|
||||
|
||||
next = next_prime_number(last);
|
||||
KUNIT_ASSERT_EQ_MSG(test, next, x, "next-prime(%lu)", last);
|
||||
last = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void kunit_suite_exit(struct kunit_suite *suite)
|
||||
{
|
||||
with_primes(suite, dump_primes);
|
||||
}
|
||||
|
||||
static struct kunit_case prime_numbers_cases[] = {
|
||||
KUNIT_CASE(prime_numbers_test),
|
||||
{},
|
||||
};
|
||||
|
||||
static struct kunit_suite prime_numbers_suite = {
|
||||
.name = "math-prime_numbers",
|
||||
.suite_exit = kunit_suite_exit,
|
||||
.test_cases = prime_numbers_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(prime_numbers_suite);
|
||||
|
||||
MODULE_AUTHOR("Intel Corporation");
|
||||
MODULE_DESCRIPTION("Prime number library");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1 +1,44 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for tests of kernel library functions.
|
||||
|
||||
# KUnit tests
|
||||
CFLAGS_bitfield_kunit.o := $(DISABLE_STRUCTLEAK_PLUGIN)
|
||||
obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
|
||||
obj-$(CONFIG_BITS_TEST) += test_bits.o
|
||||
obj-$(CONFIG_CHECKSUM_KUNIT) += checksum_kunit.o
|
||||
obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o
|
||||
obj-$(CONFIG_CPUMASK_KUNIT_TEST) += cpumask_kunit.o
|
||||
obj-$(CONFIG_CRC_KUNIT_TEST) += crc_kunit.o
|
||||
CFLAGS_fortify_kunit.o += $(call cc-disable-warning, unsequenced)
|
||||
CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-overread)
|
||||
CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-truncation)
|
||||
CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN)
|
||||
obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
|
||||
CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE)
|
||||
obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o
|
||||
obj-$(CONFIG_HASHTABLE_KUNIT_TEST) += hashtable_test.o
|
||||
obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o
|
||||
obj-$(CONFIG_TEST_IOV_ITER) += kunit_iov_iter.o
|
||||
obj-$(CONFIG_IS_SIGNED_TYPE_KUNIT_TEST) += is_signed_type_kunit.o
|
||||
obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
|
||||
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
|
||||
obj-$(CONFIG_KFIFO_KUNIT_TEST) += kfifo_kunit.o
|
||||
obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
|
||||
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
|
||||
obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
|
||||
CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
|
||||
obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
|
||||
obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o
|
||||
obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o
|
||||
obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
|
||||
obj-$(CONFIG_SLUB_KUNIT_TEST) += slub_kunit.o
|
||||
obj-$(CONFIG_TEST_SORT) += test_sort.o
|
||||
CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)
|
||||
obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o
|
||||
obj-$(CONFIG_STRING_KUNIT_TEST) += string_kunit.o
|
||||
obj-$(CONFIG_STRING_HELPERS_KUNIT_TEST) += string_helpers_kunit.o
|
||||
obj-$(CONFIG_USERCOPY_KUNIT_TEST) += usercopy_kunit.o
|
||||
obj-$(CONFIG_UTIL_MACROS_KUNIT) += util_macros_kunit.o
|
||||
|
||||
obj-$(CONFIG_TEST_RUNTIME_MODULE) += module/
|
||||
|
|
|
@ -60,6 +60,7 @@ static int fortify_write_overflows;
|
|||
|
||||
static const char array_of_10[] = "this is 10";
|
||||
static const char *ptr_of_11 = "this is 11!";
|
||||
static const char * const unchanging_12 = "this is 12!!";
|
||||
static char array_unknown[] = "compiler thinks I might change";
|
||||
|
||||
void fortify_add_kunit_error(int write)
|
||||
|
@ -83,12 +84,28 @@ void fortify_add_kunit_error(int write)
|
|||
|
||||
static void fortify_test_known_sizes(struct kunit *test)
|
||||
{
|
||||
char stack[80] = "Test!";
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, __is_constexpr(__builtin_strlen(stack)));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen(stack), 5);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, __is_constexpr(__builtin_strlen("88888888")));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, __is_constexpr(__builtin_strlen(array_of_10)));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen(array_of_10), 10);
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, __is_constexpr(__builtin_strlen(ptr_of_11)));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen(ptr_of_11), 11);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, __is_constexpr(__builtin_strlen(unchanging_12)));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen(unchanging_12), 12);
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, __is_constexpr(__builtin_strlen(array_unknown)));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen(array_unknown), SIZE_MAX);
|
||||
|
||||
/* Externally defined and dynamically sized string pointer: */
|
||||
KUNIT_EXPECT_FALSE(test, __is_constexpr(__builtin_strlen(test->name)));
|
||||
KUNIT_EXPECT_EQ(test, __compiletime_strlen(test->name), SIZE_MAX);
|
||||
}
|
||||
|
||||
|
@ -394,8 +411,6 @@ struct fortify_padding {
|
|||
char buf[32];
|
||||
unsigned long bytes_after;
|
||||
};
|
||||
/* Force compiler into not being able to resolve size at compile-time. */
|
||||
static volatile int unconst;
|
||||
|
||||
static void fortify_test_strlen(struct kunit *test)
|
||||
{
|
||||
|
@ -520,57 +535,56 @@ static void fortify_test_strncpy(struct kunit *test)
|
|||
{
|
||||
struct fortify_padding pad = { };
|
||||
char src[] = "Copy me fully into a small buffer and I will overflow!";
|
||||
size_t sizeof_buf = sizeof(pad.buf);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(sizeof_buf);
|
||||
|
||||
/* Destination is %NUL-filled to start with. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 3], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
|
||||
/* Legitimate strncpy() 1 less than of max size. */
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst - 1)
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf - 1)
|
||||
== pad.buf);
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
|
||||
/* Only last byte should be %NUL */
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 3], '\0');
|
||||
|
||||
/* Legitimate (though unterminated) max-size strncpy. */
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst)
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf)
|
||||
== pad.buf);
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
|
||||
/* No trailing %NUL -- thanks strncpy API. */
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
/* But we will not have gone beyond. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
|
||||
/* Now verify that FORTIFY is working... */
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst + 1)
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf + 1)
|
||||
== pad.buf);
|
||||
/* Should catch the overflow. */
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
/* And we will not have gone beyond. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
|
||||
/* And further... */
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst + 2)
|
||||
KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, sizeof_buf + 2)
|
||||
== pad.buf);
|
||||
/* Should catch the overflow. */
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
/* And we will not have gone beyond. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
}
|
||||
|
@ -579,55 +593,56 @@ static void fortify_test_strscpy(struct kunit *test)
|
|||
{
|
||||
struct fortify_padding pad = { };
|
||||
char src[] = "Copy me fully into a small buffer and I will overflow!";
|
||||
size_t sizeof_buf = sizeof(pad.buf);
|
||||
size_t sizeof_src = sizeof(src);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(sizeof_buf);
|
||||
OPTIMIZER_HIDE_VAR(sizeof_src);
|
||||
|
||||
/* Destination is %NUL-filled to start with. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 3], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
|
||||
/* Legitimate strscpy() 1 less than of max size. */
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst - 1),
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_buf - 1),
|
||||
-E2BIG);
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
|
||||
/* Keeping space for %NUL, last two bytes should be %NUL */
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 3], '\0');
|
||||
|
||||
/* Legitimate max-size strscpy. */
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst),
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_buf),
|
||||
-E2BIG);
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
|
||||
/* A trailing %NUL will exist. */
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
|
||||
/* Now verify that FORTIFY is working... */
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
|
||||
sizeof(pad.buf) + unconst + 1),
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_buf + 1),
|
||||
-E2BIG);
|
||||
/* Should catch the overflow. */
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
/* And we will not have gone beyond. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
|
||||
/* And much further... */
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
|
||||
sizeof(src) * 2 + unconst),
|
||||
KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, sizeof_src * 2),
|
||||
-E2BIG);
|
||||
/* Should catch the overflow. */
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[sizeof_buf - 1], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
KUNIT_EXPECT_NE(test, pad.buf[sizeof_buf - 2], '\0');
|
||||
/* And we will not have gone beyond. */
|
||||
KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
|
||||
}
|
||||
|
@ -767,7 +782,9 @@ static void fortify_test_strlcat(struct kunit *test)
|
|||
struct fortify_padding pad = { };
|
||||
char src[sizeof(pad.buf)] = { };
|
||||
int i, partial;
|
||||
int len = sizeof(pad.buf) + unconst;
|
||||
int len = sizeof(pad.buf);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(len);
|
||||
|
||||
/* Fill 15 bytes with valid characters. */
|
||||
partial = sizeof(src) / 2 - 1;
|
||||
|
@ -857,28 +874,32 @@ struct fortify_zero_sized {
|
|||
#define __fortify_test(memfunc) \
|
||||
static void fortify_test_##memfunc(struct kunit *test) \
|
||||
{ \
|
||||
struct fortify_zero_sized zero = { }; \
|
||||
struct fortify_zero_sized empty = { }; \
|
||||
struct fortify_padding pad = { }; \
|
||||
char srcA[sizeof(pad.buf) + 2]; \
|
||||
char srcB[sizeof(pad.buf) + 2]; \
|
||||
size_t len = sizeof(pad.buf) + unconst; \
|
||||
size_t len = sizeof(pad.buf); \
|
||||
size_t zero = 0; \
|
||||
\
|
||||
OPTIMIZER_HIDE_VAR(len); \
|
||||
OPTIMIZER_HIDE_VAR(zero); \
|
||||
\
|
||||
memset(srcA, 'A', sizeof(srcA)); \
|
||||
KUNIT_ASSERT_EQ(test, srcA[0], 'A'); \
|
||||
memset(srcB, 'B', sizeof(srcB)); \
|
||||
KUNIT_ASSERT_EQ(test, srcB[0], 'B'); \
|
||||
\
|
||||
memfunc(pad.buf, srcA, 0 + unconst); \
|
||||
memfunc(pad.buf, srcA, zero); \
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[0], '\0'); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); \
|
||||
memfunc(pad.buf + 1, srcB, 1 + unconst); \
|
||||
memfunc(pad.buf + 1, srcB, zero + 1); \
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[0], '\0'); \
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[1], 'B'); \
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[2], '\0'); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); \
|
||||
memfunc(pad.buf, srcA, 1 + unconst); \
|
||||
memfunc(pad.buf, srcA, zero + 1); \
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[0], 'A'); \
|
||||
KUNIT_EXPECT_EQ(test, pad.buf[1], 'B'); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \
|
||||
|
@ -904,10 +925,10 @@ static void fortify_test_##memfunc(struct kunit *test) \
|
|||
/* Reset error counter. */ \
|
||||
fortify_write_overflows = 0; \
|
||||
/* Copy nothing into nothing: no errors. */ \
|
||||
memfunc(zero.buf, srcB, 0 + unconst); \
|
||||
memfunc(empty.buf, srcB, zero); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); \
|
||||
memfunc(zero.buf, srcB, 1 + unconst); \
|
||||
memfunc(empty.buf, srcB, zero + 1); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); \
|
||||
KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); \
|
||||
}
|
||||
|
@ -919,7 +940,9 @@ static void fortify_test_memscan(struct kunit *test)
|
|||
char haystack[] = "Where oh where is my memory range?";
|
||||
char *mem = haystack + strlen("Where oh where is ");
|
||||
char needle = 'm';
|
||||
size_t len = sizeof(haystack) + unconst;
|
||||
size_t len = sizeof(haystack);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(len);
|
||||
|
||||
KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len),
|
||||
mem);
|
||||
|
@ -938,7 +961,9 @@ static void fortify_test_memchr(struct kunit *test)
|
|||
char haystack[] = "Where oh where is my memory range?";
|
||||
char *mem = haystack + strlen("Where oh where is ");
|
||||
char needle = 'm';
|
||||
size_t len = sizeof(haystack) + unconst;
|
||||
size_t len = sizeof(haystack);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(len);
|
||||
|
||||
KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len),
|
||||
mem);
|
||||
|
@ -957,7 +982,9 @@ static void fortify_test_memchr_inv(struct kunit *test)
|
|||
char haystack[] = "Where oh where is my memory range?";
|
||||
char *mem = haystack + 1;
|
||||
char needle = 'W';
|
||||
size_t len = sizeof(haystack) + unconst;
|
||||
size_t len = sizeof(haystack);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(len);
|
||||
|
||||
/* Normal search is okay. */
|
||||
KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len),
|
||||
|
@ -976,8 +1003,11 @@ static void fortify_test_memcmp(struct kunit *test)
|
|||
{
|
||||
char one[] = "My mind is going ...";
|
||||
char two[] = "My mind is going ... I can feel it.";
|
||||
size_t one_len = sizeof(one) + unconst - 1;
|
||||
size_t two_len = sizeof(two) + unconst - 1;
|
||||
size_t one_len = sizeof(one) - 1;
|
||||
size_t two_len = sizeof(two) - 1;
|
||||
|
||||
OPTIMIZER_HIDE_VAR(one_len);
|
||||
OPTIMIZER_HIDE_VAR(two_len);
|
||||
|
||||
/* We match the first string (ignoring the %NUL). */
|
||||
KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len), 0);
|
||||
|
@ -998,7 +1028,9 @@ static void fortify_test_kmemdup(struct kunit *test)
|
|||
{
|
||||
char src[] = "I got Doom running on it!";
|
||||
char *copy;
|
||||
size_t len = sizeof(src) + unconst;
|
||||
size_t len = sizeof(src);
|
||||
|
||||
OPTIMIZER_HIDE_VAR(len);
|
||||
|
||||
/* Copy is within bounds. */
|
||||
copy = kmemdup(src, len, GFP_KERNEL);
|
224
lib/tests/kfifo_kunit.c
Normal file
224
lib/tests/kfifo_kunit.c
Normal file
|
@ -0,0 +1,224 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* KUnit test for the generic kernel FIFO implementation.
|
||||
*
|
||||
* Copyright (C) 2024 Diego Vieira <diego.daniel.professional@gmail.com>
|
||||
*/
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
#define KFIFO_SIZE 32
|
||||
#define N_ELEMENTS 5
|
||||
|
||||
static void kfifo_test_reset_should_clear_the_fifo(struct kunit *test)
|
||||
{
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
kfifo_put(&my_fifo, 1);
|
||||
kfifo_put(&my_fifo, 2);
|
||||
kfifo_put(&my_fifo, 3);
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3);
|
||||
|
||||
kfifo_reset(&my_fifo);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0);
|
||||
KUNIT_EXPECT_TRUE(test, kfifo_is_empty(&my_fifo));
|
||||
}
|
||||
|
||||
static void kfifo_test_define_should_define_an_empty_fifo(struct kunit *test)
|
||||
{
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, kfifo_initialized(&my_fifo));
|
||||
KUNIT_EXPECT_TRUE(test, kfifo_is_empty(&my_fifo));
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0);
|
||||
}
|
||||
|
||||
static void kfifo_test_len_should_ret_n_of_stored_elements(struct kunit *test)
|
||||
{
|
||||
u8 buffer1[N_ELEMENTS];
|
||||
|
||||
for (int i = 0; i < N_ELEMENTS; i++)
|
||||
buffer1[i] = i + 1;
|
||||
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0);
|
||||
|
||||
kfifo_in(&my_fifo, buffer1, N_ELEMENTS);
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), N_ELEMENTS);
|
||||
|
||||
kfifo_in(&my_fifo, buffer1, N_ELEMENTS);
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), N_ELEMENTS * 2);
|
||||
|
||||
kfifo_reset(&my_fifo);
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 0);
|
||||
}
|
||||
|
||||
static void kfifo_test_put_should_insert_and_get_should_pop(struct kunit *test)
|
||||
{
|
||||
u8 out_data = 0;
|
||||
int processed_elements;
|
||||
u8 elements[] = { 3, 5, 11 };
|
||||
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
// If the fifo is empty, get returns 0
|
||||
processed_elements = kfifo_get(&my_fifo, &out_data);
|
||||
KUNIT_EXPECT_EQ(test, processed_elements, 0);
|
||||
KUNIT_EXPECT_EQ(test, out_data, 0);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
kfifo_put(&my_fifo, elements[i]);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
processed_elements = kfifo_get(&my_fifo, &out_data);
|
||||
KUNIT_EXPECT_EQ(test, processed_elements, 1);
|
||||
KUNIT_EXPECT_EQ(test, out_data, elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void kfifo_test_in_should_insert_multiple_elements(struct kunit *test)
|
||||
{
|
||||
u8 in_buffer[] = { 11, 25, 65 };
|
||||
u8 out_data;
|
||||
int processed_elements;
|
||||
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
kfifo_in(&my_fifo, in_buffer, 3);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
processed_elements = kfifo_get(&my_fifo, &out_data);
|
||||
KUNIT_EXPECT_EQ(test, processed_elements, 1);
|
||||
KUNIT_EXPECT_EQ(test, out_data, in_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void kfifo_test_out_should_pop_multiple_elements(struct kunit *test)
|
||||
{
|
||||
u8 in_buffer[] = { 11, 25, 65 };
|
||||
u8 out_buffer[3];
|
||||
int copied_elements;
|
||||
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
kfifo_put(&my_fifo, in_buffer[i]);
|
||||
|
||||
copied_elements = kfifo_out(&my_fifo, out_buffer, 3);
|
||||
KUNIT_EXPECT_EQ(test, copied_elements, 3);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
KUNIT_EXPECT_EQ(test, out_buffer[i], in_buffer[i]);
|
||||
KUNIT_EXPECT_TRUE(test, kfifo_is_empty(&my_fifo));
|
||||
}
|
||||
|
||||
static void kfifo_test_dec_init_should_define_an_empty_fifo(struct kunit *test)
|
||||
{
|
||||
DECLARE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
INIT_KFIFO(my_fifo);
|
||||
|
||||
// my_fifo is a struct with an inplace buffer
|
||||
KUNIT_EXPECT_FALSE(test, __is_kfifo_ptr(&my_fifo));
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, kfifo_initialized(&my_fifo));
|
||||
}
|
||||
|
||||
static void kfifo_test_define_should_equal_declare_init(struct kunit *test)
|
||||
{
|
||||
// declare a variable my_fifo of type struct kfifo of u8
|
||||
DECLARE_KFIFO(my_fifo1, u8, KFIFO_SIZE);
|
||||
// initialize the my_fifo variable
|
||||
INIT_KFIFO(my_fifo1);
|
||||
|
||||
// DEFINE_KFIFO declares the variable with the initial value
|
||||
// essentially the same as calling DECLARE_KFIFO and INIT_KFIFO
|
||||
DEFINE_KFIFO(my_fifo2, u8, KFIFO_SIZE);
|
||||
|
||||
// my_fifo1 and my_fifo2 have the same size
|
||||
KUNIT_EXPECT_EQ(test, sizeof(my_fifo1), sizeof(my_fifo2));
|
||||
KUNIT_EXPECT_EQ(test, kfifo_initialized(&my_fifo1),
|
||||
kfifo_initialized(&my_fifo2));
|
||||
KUNIT_EXPECT_EQ(test, kfifo_is_empty(&my_fifo1),
|
||||
kfifo_is_empty(&my_fifo2));
|
||||
}
|
||||
|
||||
static void kfifo_test_alloc_should_initiliaze_a_ptr_fifo(struct kunit *test)
|
||||
{
|
||||
int ret;
|
||||
DECLARE_KFIFO_PTR(my_fifo, u8);
|
||||
|
||||
INIT_KFIFO(my_fifo);
|
||||
|
||||
// kfifo_initialized returns false signaling the buffer pointer is NULL
|
||||
KUNIT_EXPECT_FALSE(test, kfifo_initialized(&my_fifo));
|
||||
|
||||
// kfifo_alloc allocates the buffer
|
||||
ret = kfifo_alloc(&my_fifo, KFIFO_SIZE, GFP_KERNEL);
|
||||
KUNIT_EXPECT_EQ_MSG(test, ret, 0, "Memory allocation should succeed");
|
||||
KUNIT_EXPECT_TRUE(test, kfifo_initialized(&my_fifo));
|
||||
|
||||
// kfifo_free frees the buffer
|
||||
kfifo_free(&my_fifo);
|
||||
}
|
||||
|
||||
static void kfifo_test_peek_should_not_remove_elements(struct kunit *test)
|
||||
{
|
||||
u8 out_data;
|
||||
int processed_elements;
|
||||
|
||||
DEFINE_KFIFO(my_fifo, u8, KFIFO_SIZE);
|
||||
|
||||
// If the fifo is empty, peek returns 0
|
||||
processed_elements = kfifo_peek(&my_fifo, &out_data);
|
||||
KUNIT_EXPECT_EQ(test, processed_elements, 0);
|
||||
|
||||
kfifo_put(&my_fifo, 3);
|
||||
kfifo_put(&my_fifo, 5);
|
||||
kfifo_put(&my_fifo, 11);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3);
|
||||
|
||||
processed_elements = kfifo_peek(&my_fifo, &out_data);
|
||||
KUNIT_EXPECT_EQ(test, processed_elements, 1);
|
||||
KUNIT_EXPECT_EQ(test, out_data, 3);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3);
|
||||
|
||||
// Using peek doesn't remove the element
|
||||
// so the read element and the fifo length
|
||||
// remains the same
|
||||
processed_elements = kfifo_peek(&my_fifo, &out_data);
|
||||
KUNIT_EXPECT_EQ(test, processed_elements, 1);
|
||||
KUNIT_EXPECT_EQ(test, out_data, 3);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, kfifo_len(&my_fifo), 3);
|
||||
}
|
||||
|
||||
static struct kunit_case kfifo_test_cases[] = {
|
||||
KUNIT_CASE(kfifo_test_reset_should_clear_the_fifo),
|
||||
KUNIT_CASE(kfifo_test_define_should_define_an_empty_fifo),
|
||||
KUNIT_CASE(kfifo_test_len_should_ret_n_of_stored_elements),
|
||||
KUNIT_CASE(kfifo_test_put_should_insert_and_get_should_pop),
|
||||
KUNIT_CASE(kfifo_test_in_should_insert_multiple_elements),
|
||||
KUNIT_CASE(kfifo_test_out_should_pop_multiple_elements),
|
||||
KUNIT_CASE(kfifo_test_dec_init_should_define_an_empty_fifo),
|
||||
KUNIT_CASE(kfifo_test_define_should_equal_declare_init),
|
||||
KUNIT_CASE(kfifo_test_alloc_should_initiliaze_a_ptr_fifo),
|
||||
KUNIT_CASE(kfifo_test_peek_should_not_remove_elements),
|
||||
{},
|
||||
};
|
||||
|
||||
static struct kunit_suite kfifo_test_module = {
|
||||
.name = "kfifo",
|
||||
.test_cases = kfifo_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&kfifo_test_module);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Diego Vieira <diego.daniel.professional@gmail.com>");
|
||||
MODULE_DESCRIPTION("KUnit test for the kernel FIFO");
|
|
@ -1185,22 +1185,40 @@ struct bar {
|
|||
|
||||
static void DEFINE_FLEX_test(struct kunit *test)
|
||||
{
|
||||
/* Using _RAW_ on a __counted_by struct will initialize "counter" to zero */
|
||||
DEFINE_RAW_FLEX(struct foo, two_but_zero, array, 2);
|
||||
#ifdef CONFIG_CC_HAS_COUNTED_BY
|
||||
int expected_raw_size = sizeof(struct foo);
|
||||
#else
|
||||
int expected_raw_size = sizeof(struct foo) + 2 * sizeof(s16);
|
||||
#endif
|
||||
/* Without annotation, it will always be on-stack size. */
|
||||
DEFINE_RAW_FLEX(struct bar, two, array, 2);
|
||||
DEFINE_FLEX(struct foo, eight, array, counter, 8);
|
||||
DEFINE_FLEX(struct foo, empty, array, counter, 0);
|
||||
/* Using _RAW_ on a __counted_by struct will initialize "counter" to zero */
|
||||
DEFINE_RAW_FLEX(struct foo, two_but_zero, array, 2);
|
||||
int array_size_override = 0;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(two_but_zero), expected_raw_size);
|
||||
KUNIT_EXPECT_EQ(test, sizeof(*two), sizeof(struct bar));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(two), sizeof(struct bar) + 2 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(eight), 24);
|
||||
KUNIT_EXPECT_EQ(test, __member_size(two), sizeof(struct bar) + 2 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(two->array), 2 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __member_size(two->array), 2 * sizeof(s16));
|
||||
|
||||
KUNIT_EXPECT_EQ(test, sizeof(*eight), sizeof(struct foo));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(eight), sizeof(struct foo) + 8 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __member_size(eight), sizeof(struct foo) + 8 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(eight->array), 8 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __member_size(eight->array), 8 * sizeof(s16));
|
||||
|
||||
KUNIT_EXPECT_EQ(test, sizeof(*empty), sizeof(struct foo));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(empty), sizeof(struct foo));
|
||||
KUNIT_EXPECT_EQ(test, __member_size(empty), sizeof(struct foo));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(empty->array), 0);
|
||||
KUNIT_EXPECT_EQ(test, __member_size(empty->array), 0);
|
||||
|
||||
/* If __counted_by is not being used, array size will have the on-stack size. */
|
||||
if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY))
|
||||
array_size_override = 2 * sizeof(s16);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, sizeof(*two_but_zero), sizeof(struct foo));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(two_but_zero), sizeof(struct foo) + 2 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __member_size(two_but_zero), sizeof(struct foo) + 2 * sizeof(s16));
|
||||
KUNIT_EXPECT_EQ(test, __struct_size(two_but_zero->array), array_size_override);
|
||||
KUNIT_EXPECT_EQ(test, __member_size(two_but_zero->array), array_size_override);
|
||||
}
|
||||
|
||||
static struct kunit_case overflow_test_cases[] = {
|
|
@ -3,9 +3,7 @@
|
|||
* Test cases for printf facility.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <kunit/test.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
|
@ -25,8 +23,6 @@
|
|||
|
||||
#include <linux/property.h>
|
||||
|
||||
#include "../tools/testing/selftests/kselftest_module.h"
|
||||
|
||||
#define BUF_SIZE 256
|
||||
#define PAD_SIZE 16
|
||||
#define FILL_CHAR '$'
|
||||
|
@ -37,14 +33,14 @@
|
|||
block \
|
||||
__diag_pop();
|
||||
|
||||
KSTM_MODULE_GLOBALS();
|
||||
static unsigned int total_tests;
|
||||
|
||||
static char *test_buffer __initdata;
|
||||
static char *alloced_buffer __initdata;
|
||||
static char *test_buffer;
|
||||
static char *alloced_buffer;
|
||||
|
||||
static int __printf(4, 0) __init
|
||||
do_test(int bufsize, const char *expect, int elen,
|
||||
const char *fmt, va_list ap)
|
||||
static void __printf(7, 0)
|
||||
do_test(struct kunit *kunittest, const char *file, const int line, int bufsize, const char *expect,
|
||||
int elen, const char *fmt, va_list ap)
|
||||
{
|
||||
va_list aq;
|
||||
int ret, written;
|
||||
|
@ -57,62 +53,70 @@ do_test(int bufsize, const char *expect, int elen,
|
|||
va_end(aq);
|
||||
|
||||
if (ret != elen) {
|
||||
pr_warn("vsnprintf(buf, %d, \"%s\", ...) returned %d, expected %d\n",
|
||||
bufsize, fmt, ret, elen);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, %d, \"%s\", ...) returned %d, expected %d\n",
|
||||
file, line, bufsize, fmt, ret, elen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memchr_inv(alloced_buffer, FILL_CHAR, PAD_SIZE)) {
|
||||
pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote before buffer\n", bufsize, fmt);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, %d, \"%s\", ...) wrote before buffer\n",
|
||||
file, line, bufsize, fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bufsize) {
|
||||
if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE + PAD_SIZE)) {
|
||||
pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n",
|
||||
fmt);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n",
|
||||
file, line, fmt);
|
||||
}
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
written = min(bufsize-1, elen);
|
||||
if (test_buffer[written]) {
|
||||
pr_warn("vsnprintf(buf, %d, \"%s\", ...) did not nul-terminate buffer\n",
|
||||
bufsize, fmt);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, %d, \"%s\", ...) did not nul-terminate buffer\n",
|
||||
file, line, bufsize, fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memchr_inv(test_buffer + written + 1, FILL_CHAR, bufsize - (written + 1))) {
|
||||
pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n",
|
||||
bufsize, fmt);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n",
|
||||
file, line, bufsize, fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memchr_inv(test_buffer + bufsize, FILL_CHAR, BUF_SIZE + PAD_SIZE - bufsize)) {
|
||||
pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond buffer\n", bufsize, fmt);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, %d, \"%s\", ...) wrote beyond buffer\n",
|
||||
file, line, bufsize, fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(test_buffer, expect, written)) {
|
||||
pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n",
|
||||
bufsize, fmt, test_buffer, written, expect);
|
||||
return 1;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n",
|
||||
file, line, bufsize, fmt, test_buffer, written, expect);
|
||||
return;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __printf(3, 4) __init
|
||||
__test(const char *expect, int elen, const char *fmt, ...)
|
||||
static void __printf(6, 7)
|
||||
__test(struct kunit *kunittest, const char *file, const int line, const char *expect, int elen,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rand;
|
||||
char *p;
|
||||
|
||||
if (elen >= BUF_SIZE) {
|
||||
pr_err("error in test suite: expected output length %d too long. Format was '%s'.\n",
|
||||
elen, fmt);
|
||||
failed_tests++;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: error in test suite: expected length (%d) >= BUF_SIZE (%d). fmt=\"%s\"\n",
|
||||
file, line, elen, BUF_SIZE, fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -124,19 +128,19 @@ __test(const char *expect, int elen, const char *fmt, ...)
|
|||
* enough and 0), and then we also test that kvasprintf would
|
||||
* be able to print it as expected.
|
||||
*/
|
||||
failed_tests += do_test(BUF_SIZE, expect, elen, fmt, ap);
|
||||
do_test(kunittest, file, line, BUF_SIZE, expect, elen, fmt, ap);
|
||||
rand = get_random_u32_inclusive(1, elen + 1);
|
||||
/* Since elen < BUF_SIZE, we have 1 <= rand <= BUF_SIZE. */
|
||||
failed_tests += do_test(rand, expect, elen, fmt, ap);
|
||||
failed_tests += do_test(0, expect, elen, fmt, ap);
|
||||
do_test(kunittest, file, line, rand, expect, elen, fmt, ap);
|
||||
do_test(kunittest, file, line, 0, expect, elen, fmt, ap);
|
||||
|
||||
p = kvasprintf(GFP_KERNEL, fmt, ap);
|
||||
if (p) {
|
||||
total_tests++;
|
||||
if (memcmp(p, expect, elen+1)) {
|
||||
pr_warn("kvasprintf(..., \"%s\", ...) returned '%s', expected '%s'\n",
|
||||
fmt, p, expect);
|
||||
failed_tests++;
|
||||
KUNIT_FAIL(kunittest,
|
||||
"%s:%d: kvasprintf(..., \"%s\", ...) returned '%s', expected '%s'\n",
|
||||
file, line, fmt, p, expect);
|
||||
}
|
||||
kfree(p);
|
||||
}
|
||||
|
@ -144,10 +148,10 @@ __test(const char *expect, int elen, const char *fmt, ...)
|
|||
}
|
||||
|
||||
#define test(expect, fmt, ...) \
|
||||
__test(expect, strlen(expect), fmt, ##__VA_ARGS__)
|
||||
__test(kunittest, __FILE__, __LINE__, expect, strlen(expect), fmt, ##__VA_ARGS__)
|
||||
|
||||
static void __init
|
||||
test_basic(void)
|
||||
static void
|
||||
test_basic(struct kunit *kunittest)
|
||||
{
|
||||
/* Work around annoying "warning: zero-length gnu_printf format string". */
|
||||
char nul = '\0';
|
||||
|
@ -155,11 +159,11 @@ test_basic(void)
|
|||
test("", &nul);
|
||||
test("100%", "100%%");
|
||||
test("xxx%yyy", "xxx%cyyy", '%');
|
||||
__test("xxx\0yyy", 7, "xxx%cyyy", '\0');
|
||||
__test(kunittest, __FILE__, __LINE__, "xxx\0yyy", 7, "xxx%cyyy", '\0');
|
||||
}
|
||||
|
||||
static void __init
|
||||
test_number(void)
|
||||
static void
|
||||
test_number(struct kunit *kunittest)
|
||||
{
|
||||
test("0x1234abcd ", "%#-12x", 0x1234abcd);
|
||||
test(" 0x1234abcd", "%#12x", 0x1234abcd);
|
||||
|
@ -180,8 +184,8 @@ test_number(void)
|
|||
test("00|0|0|0|0", "%.2d|%.1d|%.0d|%.*d|%1.0d", 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void __init
|
||||
test_string(void)
|
||||
static void
|
||||
test_string(struct kunit *kunittest)
|
||||
{
|
||||
test("", "%s%.0s", "", "123");
|
||||
test("ABCD|abc|123", "%s|%.3s|%.*s", "ABCD", "abcdef", 3, "123456");
|
||||
|
@ -218,29 +222,6 @@ test_string(void)
|
|||
#define ZEROS "00000000" /* hex 32 zero bits */
|
||||
#define ONES "ffffffff" /* hex 32 one bits */
|
||||
|
||||
static int __init
|
||||
plain_format(void)
|
||||
{
|
||||
char buf[PLAIN_BUF_SIZE];
|
||||
int nchars;
|
||||
|
||||
nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR);
|
||||
|
||||
if (nchars != PTR_WIDTH)
|
||||
return -1;
|
||||
|
||||
if (strncmp(buf, PTR_VAL_NO_CRNG, PTR_WIDTH) == 0) {
|
||||
pr_warn("crng possibly not yet initialized. plain 'p' buffer contains \"%s\"",
|
||||
PTR_VAL_NO_CRNG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp(buf, ZEROS, strlen(ZEROS)) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define PTR_WIDTH 8
|
||||
|
@ -250,92 +231,47 @@ plain_format(void)
|
|||
#define ZEROS ""
|
||||
#define ONES ""
|
||||
|
||||
static int __init
|
||||
plain_format(void)
|
||||
{
|
||||
/* Format is implicitly tested for 32 bit machines by plain_hash() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* BITS_PER_LONG == 64 */
|
||||
|
||||
static int __init
|
||||
plain_hash_to_buffer(const void *p, char *buf, size_t len)
|
||||
static void
|
||||
plain_hash_to_buffer(struct kunit *kunittest, const void *p, char *buf, size_t len)
|
||||
{
|
||||
int nchars;
|
||||
|
||||
nchars = snprintf(buf, len, "%p", p);
|
||||
|
||||
if (nchars != PTR_WIDTH)
|
||||
return -1;
|
||||
KUNIT_ASSERT_EQ(kunittest, snprintf(buf, len, "%p", p), PTR_WIDTH);
|
||||
|
||||
if (strncmp(buf, PTR_VAL_NO_CRNG, PTR_WIDTH) == 0) {
|
||||
pr_warn("crng possibly not yet initialized. plain 'p' buffer contains \"%s\"",
|
||||
PTR_VAL_NO_CRNG);
|
||||
return 0;
|
||||
kunit_skip(kunittest,
|
||||
"crng possibly not yet initialized. plain 'p' buffer contains \"%s\"\n",
|
||||
PTR_VAL_NO_CRNG);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
plain_hash(void)
|
||||
static void
|
||||
hash_pointer(struct kunit *kunittest)
|
||||
{
|
||||
if (no_hash_pointers)
|
||||
kunit_skip(kunittest, "hash pointers disabled");
|
||||
|
||||
char buf[PLAIN_BUF_SIZE];
|
||||
int ret;
|
||||
|
||||
ret = plain_hash_to_buffer(PTR, buf, PLAIN_BUF_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (strncmp(buf, PTR_STR, PTR_WIDTH) == 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't use test() to test %p because we don't know what output to expect
|
||||
* after an address is hashed.
|
||||
*/
|
||||
static void __init
|
||||
plain(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (no_hash_pointers) {
|
||||
pr_warn("skipping plain 'p' tests");
|
||||
skipped_tests += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
err = plain_hash();
|
||||
if (err) {
|
||||
pr_warn("plain 'p' does not appear to be hashed\n");
|
||||
failed_tests++;
|
||||
return;
|
||||
}
|
||||
|
||||
err = plain_format();
|
||||
if (err) {
|
||||
pr_warn("hashing plain 'p' has unexpected format\n");
|
||||
failed_tests++;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
test_hashed(const char *fmt, const void *p)
|
||||
{
|
||||
char buf[PLAIN_BUF_SIZE];
|
||||
int ret;
|
||||
plain_hash_to_buffer(kunittest, PTR, buf, PLAIN_BUF_SIZE);
|
||||
|
||||
/*
|
||||
* No need to increase failed test counter since this is assumed
|
||||
* to be called after plain().
|
||||
* The hash of %p is unpredictable, therefore test() cannot be used.
|
||||
*
|
||||
* Instead verify that the first 32 bits are zeros on a 64-bit system
|
||||
* and that the non-hashed value is not printed.
|
||||
*/
|
||||
ret = plain_hash_to_buffer(p, buf, PLAIN_BUF_SIZE);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
KUNIT_EXPECT_MEMEQ(kunittest, buf, ZEROS, strlen(ZEROS));
|
||||
KUNIT_EXPECT_MEMNEQ(kunittest, buf, PTR_STR, PTR_WIDTH);
|
||||
}
|
||||
|
||||
static void
|
||||
test_hashed(struct kunit *kunittest, const char *fmt, const void *p)
|
||||
{
|
||||
char buf[PLAIN_BUF_SIZE];
|
||||
|
||||
plain_hash_to_buffer(kunittest, p, buf, PLAIN_BUF_SIZE);
|
||||
|
||||
test(buf, fmt, p);
|
||||
}
|
||||
|
@ -343,8 +279,8 @@ test_hashed(const char *fmt, const void *p)
|
|||
/*
|
||||
* NULL pointers aren't hashed.
|
||||
*/
|
||||
static void __init
|
||||
null_pointer(void)
|
||||
static void
|
||||
null_pointer(struct kunit *kunittest)
|
||||
{
|
||||
test(ZEROS "00000000", "%p", NULL);
|
||||
test(ZEROS "00000000", "%px", NULL);
|
||||
|
@ -354,8 +290,8 @@ null_pointer(void)
|
|||
/*
|
||||
* Error pointers aren't hashed.
|
||||
*/
|
||||
static void __init
|
||||
error_pointer(void)
|
||||
static void
|
||||
error_pointer(struct kunit *kunittest)
|
||||
{
|
||||
test(ONES "fffffff5", "%p", ERR_PTR(-11));
|
||||
test(ONES "fffffff5", "%px", ERR_PTR(-11));
|
||||
|
@ -364,27 +300,27 @@ error_pointer(void)
|
|||
|
||||
#define PTR_INVALID ((void *)0x000000ab)
|
||||
|
||||
static void __init
|
||||
invalid_pointer(void)
|
||||
static void
|
||||
invalid_pointer(struct kunit *kunittest)
|
||||
{
|
||||
test_hashed("%p", PTR_INVALID);
|
||||
test_hashed(kunittest, "%p", PTR_INVALID);
|
||||
test(ZEROS "000000ab", "%px", PTR_INVALID);
|
||||
test("(efault)", "%pE", PTR_INVALID);
|
||||
}
|
||||
|
||||
static void __init
|
||||
symbol_ptr(void)
|
||||
static void
|
||||
symbol_ptr(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init
|
||||
kernel_ptr(void)
|
||||
static void
|
||||
kernel_ptr(struct kunit *kunittest)
|
||||
{
|
||||
/* We can't test this without access to kptr_restrict. */
|
||||
}
|
||||
|
||||
static void __init
|
||||
struct_resource(void)
|
||||
static void
|
||||
struct_resource(struct kunit *kunittest)
|
||||
{
|
||||
struct resource test_resource = {
|
||||
.start = 0xc0ffee00,
|
||||
|
@ -432,8 +368,8 @@ struct_resource(void)
|
|||
"%pR", &test_resource);
|
||||
}
|
||||
|
||||
static void __init
|
||||
struct_range(void)
|
||||
static void
|
||||
struct_range(struct kunit *kunittest)
|
||||
{
|
||||
struct range test_range = DEFINE_RANGE(0xc0ffee00ba5eba11,
|
||||
0xc0ffee00ba5eba11);
|
||||
|
@ -448,18 +384,18 @@ struct_range(void)
|
|||
"%pra", &test_range);
|
||||
}
|
||||
|
||||
static void __init
|
||||
addr(void)
|
||||
static void
|
||||
addr(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init
|
||||
escaped_str(void)
|
||||
static void
|
||||
escaped_str(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init
|
||||
hex_string(void)
|
||||
static void
|
||||
hex_string(struct kunit *kunittest)
|
||||
{
|
||||
const char buf[3] = {0xc0, 0xff, 0xee};
|
||||
|
||||
|
@ -469,8 +405,8 @@ hex_string(void)
|
|||
"%*ph|%*phC|%*phD|%*phN", 3, buf, 3, buf, 3, buf, 3, buf);
|
||||
}
|
||||
|
||||
static void __init
|
||||
mac(void)
|
||||
static void
|
||||
mac(struct kunit *kunittest)
|
||||
{
|
||||
const u8 addr[6] = {0x2d, 0x48, 0xd6, 0xfc, 0x7a, 0x05};
|
||||
|
||||
|
@ -481,8 +417,8 @@ mac(void)
|
|||
test("057afcd6482d", "%pmR", addr);
|
||||
}
|
||||
|
||||
static void __init
|
||||
ip4(void)
|
||||
static void
|
||||
ip4(struct kunit *kunittest)
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
|
||||
|
@ -496,20 +432,13 @@ ip4(void)
|
|||
test("001.002.003.004:12345|1.2.3.4:12345", "%piSp|%pISp", &sa, &sa);
|
||||
}
|
||||
|
||||
static void __init
|
||||
ip6(void)
|
||||
static void
|
||||
ip6(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init
|
||||
ip(void)
|
||||
{
|
||||
ip4();
|
||||
ip6();
|
||||
}
|
||||
|
||||
static void __init
|
||||
uuid(void)
|
||||
static void
|
||||
uuid(struct kunit *kunittest)
|
||||
{
|
||||
const char uuid[16] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
|
||||
|
@ -520,7 +449,7 @@ uuid(void)
|
|||
test("03020100-0504-0706-0809-0A0B0C0D0E0F", "%pUL", uuid);
|
||||
}
|
||||
|
||||
static struct dentry test_dentry[4] __initdata = {
|
||||
static struct dentry test_dentry[4] = {
|
||||
{ .d_parent = &test_dentry[0],
|
||||
.d_name = QSTR_INIT(test_dentry[0].d_iname, 3),
|
||||
.d_iname = "foo" },
|
||||
|
@ -535,8 +464,8 @@ static struct dentry test_dentry[4] __initdata = {
|
|||
.d_iname = "romeo" },
|
||||
};
|
||||
|
||||
static void __init
|
||||
dentry(void)
|
||||
static void
|
||||
dentry(struct kunit *kunittest)
|
||||
{
|
||||
test("foo", "%pd", &test_dentry[0]);
|
||||
test("foo", "%pd2", &test_dentry[0]);
|
||||
|
@ -556,13 +485,13 @@ dentry(void)
|
|||
test(" bravo/alfa| bravo/alfa", "%12pd2|%*pd2", &test_dentry[2], 12, &test_dentry[2]);
|
||||
}
|
||||
|
||||
static void __init
|
||||
struct_va_format(void)
|
||||
static void
|
||||
struct_va_format(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init
|
||||
time_and_date(void)
|
||||
static void
|
||||
time_and_date(struct kunit *kunittest)
|
||||
{
|
||||
/* 1543210543 */
|
||||
const struct rtc_time tm = {
|
||||
|
@ -595,13 +524,13 @@ time_and_date(void)
|
|||
test("15:32:23|0119-00-04", "%ptTtrs|%ptTdrs", &t, &t);
|
||||
}
|
||||
|
||||
static void __init
|
||||
struct_clk(void)
|
||||
static void
|
||||
struct_clk(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init
|
||||
large_bitmap(void)
|
||||
static void
|
||||
large_bitmap(struct kunit *kunittest)
|
||||
{
|
||||
const int nbits = 1 << 16;
|
||||
unsigned long *bits = bitmap_zalloc(nbits, GFP_KERNEL);
|
||||
|
@ -614,8 +543,8 @@ large_bitmap(void)
|
|||
bitmap_free(bits);
|
||||
}
|
||||
|
||||
static void __init
|
||||
bitmap(void)
|
||||
static void
|
||||
bitmap(struct kunit *kunittest)
|
||||
{
|
||||
DECLARE_BITMAP(bits, 20);
|
||||
const int primes[] = {2,3,5,7,11,13,17,19};
|
||||
|
@ -634,11 +563,11 @@ bitmap(void)
|
|||
test("fffff|fffff", "%20pb|%*pb", bits, 20, bits);
|
||||
test("0-19|0-19", "%20pbl|%*pbl", bits, 20, bits);
|
||||
|
||||
large_bitmap();
|
||||
large_bitmap(kunittest);
|
||||
}
|
||||
|
||||
static void __init
|
||||
netdev_features(void)
|
||||
static void
|
||||
netdev_features(struct kunit *kunittest)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -663,9 +592,9 @@ static const struct page_flags_test pft[] = {
|
|||
"%#x", "kasantag"},
|
||||
};
|
||||
|
||||
static void __init
|
||||
page_flags_test(int section, int node, int zone, int last_cpupid,
|
||||
int kasan_tag, unsigned long flags, const char *name,
|
||||
static void
|
||||
page_flags_test(struct kunit *kunittest, int section, int node, int zone,
|
||||
int last_cpupid, int kasan_tag, unsigned long flags, const char *name,
|
||||
char *cmp_buf)
|
||||
{
|
||||
unsigned long values[] = {section, node, zone, last_cpupid, kasan_tag};
|
||||
|
@ -701,26 +630,25 @@ page_flags_test(int section, int node, int zone, int last_cpupid,
|
|||
test(cmp_buf, "%pGp", &flags);
|
||||
}
|
||||
|
||||
static void __init
|
||||
flags(void)
|
||||
static void
|
||||
flags(struct kunit *kunittest)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *cmp_buffer;
|
||||
gfp_t gfp;
|
||||
|
||||
cmp_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
|
||||
if (!cmp_buffer)
|
||||
return;
|
||||
cmp_buffer = kunit_kmalloc(kunittest, BUF_SIZE, GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(kunittest, cmp_buffer);
|
||||
|
||||
flags = 0;
|
||||
page_flags_test(0, 0, 0, 0, 0, flags, "", cmp_buffer);
|
||||
page_flags_test(kunittest, 0, 0, 0, 0, 0, flags, "", cmp_buffer);
|
||||
|
||||
flags = 1UL << NR_PAGEFLAGS;
|
||||
page_flags_test(0, 0, 0, 0, 0, flags, "", cmp_buffer);
|
||||
page_flags_test(kunittest, 0, 0, 0, 0, 0, flags, "", cmp_buffer);
|
||||
|
||||
flags |= 1UL << PG_uptodate | 1UL << PG_dirty | 1UL << PG_lru
|
||||
| 1UL << PG_active | 1UL << PG_swapbacked;
|
||||
page_flags_test(1, 1, 1, 0x1fffff, 1, flags,
|
||||
page_flags_test(kunittest, 1, 1, 1, 0x1fffff, 1, flags,
|
||||
"uptodate|dirty|lru|active|swapbacked",
|
||||
cmp_buffer);
|
||||
|
||||
|
@ -745,11 +673,9 @@ flags(void)
|
|||
(unsigned long) gfp);
|
||||
gfp |= __GFP_HIGH;
|
||||
test(cmp_buffer, "%pGg", &gfp);
|
||||
|
||||
kfree(cmp_buffer);
|
||||
}
|
||||
|
||||
static void __init fwnode_pointer(void)
|
||||
static void fwnode_pointer(struct kunit *kunittest)
|
||||
{
|
||||
const struct software_node first = { .name = "first" };
|
||||
const struct software_node second = { .name = "second", .parent = &first };
|
||||
|
@ -763,8 +689,7 @@ static void __init fwnode_pointer(void)
|
|||
|
||||
rval = software_node_register_node_group(group);
|
||||
if (rval) {
|
||||
pr_warn("cannot register softnodes; rval %d\n", rval);
|
||||
return;
|
||||
kunit_skip(kunittest, "cannot register softnodes; rval %d\n", rval);
|
||||
}
|
||||
|
||||
test(full_name_second, "%pfw", software_node_fwnode(&second));
|
||||
|
@ -776,7 +701,7 @@ static void __init fwnode_pointer(void)
|
|||
software_node_unregister_node_group(group);
|
||||
}
|
||||
|
||||
static void __init fourcc_pointer(void)
|
||||
static void fourcc_pointer(struct kunit *kunittest)
|
||||
{
|
||||
struct {
|
||||
u32 code;
|
||||
|
@ -793,14 +718,14 @@ static void __init fourcc_pointer(void)
|
|||
test(try[i].str, "%p4cc", &try[i].code);
|
||||
}
|
||||
|
||||
static void __init
|
||||
errptr(void)
|
||||
static void
|
||||
errptr(struct kunit *kunittest)
|
||||
{
|
||||
test("-1234", "%pe", ERR_PTR(-1234));
|
||||
|
||||
/* Check that %pe with a non-ERR_PTR gets treated as ordinary %p. */
|
||||
BUILD_BUG_ON(IS_ERR(PTR));
|
||||
test_hashed("%pe", PTR);
|
||||
test_hashed(kunittest, "%pe", PTR);
|
||||
|
||||
#ifdef CONFIG_SYMBOLIC_ERRNAME
|
||||
test("(-ENOTSOCK)", "(%pe)", ERR_PTR(-ENOTSOCK));
|
||||
|
@ -813,51 +738,66 @@ errptr(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void __init
|
||||
test_pointer(void)
|
||||
static int printf_suite_init(struct kunit_suite *suite)
|
||||
{
|
||||
plain();
|
||||
null_pointer();
|
||||
error_pointer();
|
||||
invalid_pointer();
|
||||
symbol_ptr();
|
||||
kernel_ptr();
|
||||
struct_resource();
|
||||
struct_range();
|
||||
addr();
|
||||
escaped_str();
|
||||
hex_string();
|
||||
mac();
|
||||
ip();
|
||||
uuid();
|
||||
dentry();
|
||||
struct_va_format();
|
||||
time_and_date();
|
||||
struct_clk();
|
||||
bitmap();
|
||||
netdev_features();
|
||||
flags();
|
||||
errptr();
|
||||
fwnode_pointer();
|
||||
fourcc_pointer();
|
||||
}
|
||||
total_tests = 0;
|
||||
|
||||
static void __init selftest(void)
|
||||
{
|
||||
alloced_buffer = kmalloc(BUF_SIZE + 2*PAD_SIZE, GFP_KERNEL);
|
||||
if (!alloced_buffer)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
test_buffer = alloced_buffer + PAD_SIZE;
|
||||
|
||||
test_basic();
|
||||
test_number();
|
||||
test_string();
|
||||
test_pointer();
|
||||
|
||||
kfree(alloced_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
KSTM_MODULE_LOADERS(test_printf);
|
||||
static void printf_suite_exit(struct kunit_suite *suite)
|
||||
{
|
||||
kfree(alloced_buffer);
|
||||
|
||||
kunit_info(suite, "ran %u tests\n", total_tests);
|
||||
}
|
||||
|
||||
static struct kunit_case printf_test_cases[] = {
|
||||
KUNIT_CASE(test_basic),
|
||||
KUNIT_CASE(test_number),
|
||||
KUNIT_CASE(test_string),
|
||||
KUNIT_CASE(hash_pointer),
|
||||
KUNIT_CASE(null_pointer),
|
||||
KUNIT_CASE(error_pointer),
|
||||
KUNIT_CASE(invalid_pointer),
|
||||
KUNIT_CASE(symbol_ptr),
|
||||
KUNIT_CASE(kernel_ptr),
|
||||
KUNIT_CASE(struct_resource),
|
||||
KUNIT_CASE(struct_range),
|
||||
KUNIT_CASE(addr),
|
||||
KUNIT_CASE(escaped_str),
|
||||
KUNIT_CASE(hex_string),
|
||||
KUNIT_CASE(mac),
|
||||
KUNIT_CASE(ip4),
|
||||
KUNIT_CASE(ip6),
|
||||
KUNIT_CASE(uuid),
|
||||
KUNIT_CASE(dentry),
|
||||
KUNIT_CASE(struct_va_format),
|
||||
KUNIT_CASE(time_and_date),
|
||||
KUNIT_CASE(struct_clk),
|
||||
KUNIT_CASE(bitmap),
|
||||
KUNIT_CASE(netdev_features),
|
||||
KUNIT_CASE(flags),
|
||||
KUNIT_CASE(errptr),
|
||||
KUNIT_CASE(fwnode_pointer),
|
||||
KUNIT_CASE(fourcc_pointer),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite printf_test_suite = {
|
||||
.name = "printf",
|
||||
.suite_init = printf_suite_init,
|
||||
.suite_exit = printf_suite_exit,
|
||||
.test_cases = printf_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(printf_test_suite);
|
||||
|
||||
MODULE_AUTHOR("Rasmus Villemoes <linux@rasmusvillemoes.dk>");
|
||||
MODULE_DESCRIPTION("Test cases for printf facility");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -3,152 +3,138 @@
|
|||
* Test cases for sscanf facility.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/prandom.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "../tools/testing/selftests/kselftest_module.h"
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
KSTM_MODULE_GLOBALS();
|
||||
static char *test_buffer __initdata;
|
||||
static char *fmt_buffer __initdata;
|
||||
static struct rnd_state rnd_state __initdata;
|
||||
static char *test_buffer;
|
||||
static char *fmt_buffer;
|
||||
static struct rnd_state rnd_state;
|
||||
|
||||
typedef int (*check_fn)(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap);
|
||||
typedef void (*check_fn)(struct kunit *test, const char *file, const int line,
|
||||
const void *check_data, const char *string, const char *fmt, int n_args,
|
||||
va_list ap);
|
||||
|
||||
static void __scanf(4, 6) __init
|
||||
_test(check_fn fn, const void *check_data, const char *string, const char *fmt,
|
||||
int n_args, ...)
|
||||
static void __scanf(7, 9)
|
||||
_test(struct kunit *test, const char *file, const int line, check_fn fn, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, ...)
|
||||
{
|
||||
va_list ap, ap_copy;
|
||||
int ret;
|
||||
|
||||
total_tests++;
|
||||
|
||||
va_start(ap, n_args);
|
||||
va_copy(ap_copy, ap);
|
||||
ret = vsscanf(string, fmt, ap_copy);
|
||||
va_end(ap_copy);
|
||||
|
||||
if (ret != n_args) {
|
||||
pr_warn("vsscanf(\"%s\", \"%s\", ...) returned %d expected %d\n",
|
||||
string, fmt, ret, n_args);
|
||||
goto fail;
|
||||
KUNIT_FAIL(test, "%s:%d: vsscanf(\"%s\", \"%s\", ...) returned %d expected %d",
|
||||
file, line, string, fmt, ret, n_args);
|
||||
} else {
|
||||
(*fn)(test, file, line, check_data, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
ret = (*fn)(check_data, string, fmt, n_args, ap);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
failed_tests++;
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define _check_numbers_template(arg_fmt, expect, str, fmt, n_args, ap) \
|
||||
do { \
|
||||
pr_debug("\"%s\", \"%s\" ->\n", str, fmt); \
|
||||
for (; n_args > 0; n_args--, expect++) { \
|
||||
typeof(*expect) got = *va_arg(ap, typeof(expect)); \
|
||||
pr_debug("\t" arg_fmt "\n", got); \
|
||||
if (got != *expect) { \
|
||||
pr_warn("vsscanf(\"%s\", \"%s\", ...) expected " arg_fmt " got " arg_fmt "\n", \
|
||||
str, fmt, *expect, got); \
|
||||
return 1; \
|
||||
KUNIT_FAIL(test, \
|
||||
"%s:%d: vsscanf(\"%s\", \"%s\", ...) expected " arg_fmt " got " arg_fmt, \
|
||||
file, line, str, fmt, *expect, got); \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
static int __init check_ull(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_ull(struct kunit *test, const char *file, const int line, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, va_list ap)
|
||||
{
|
||||
const unsigned long long *pval = check_data;
|
||||
|
||||
_check_numbers_template("%llu", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_ll(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_ll(struct kunit *test, const char *file, const int line, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, va_list ap)
|
||||
{
|
||||
const long long *pval = check_data;
|
||||
|
||||
_check_numbers_template("%lld", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_ulong(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_ulong(struct kunit *test, const char *file, const int line,
|
||||
const void *check_data, const char *string, const char *fmt, int n_args,
|
||||
va_list ap)
|
||||
{
|
||||
const unsigned long *pval = check_data;
|
||||
|
||||
_check_numbers_template("%lu", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_long(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_long(struct kunit *test, const char *file, const int line, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, va_list ap)
|
||||
{
|
||||
const long *pval = check_data;
|
||||
|
||||
_check_numbers_template("%ld", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_uint(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_uint(struct kunit *test, const char *file, const int line, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, va_list ap)
|
||||
{
|
||||
const unsigned int *pval = check_data;
|
||||
|
||||
_check_numbers_template("%u", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_int(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_int(struct kunit *test, const char *file, const int line, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, va_list ap)
|
||||
{
|
||||
const int *pval = check_data;
|
||||
|
||||
_check_numbers_template("%d", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_ushort(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_ushort(struct kunit *test, const char *file, const int line,
|
||||
const void *check_data, const char *string, const char *fmt, int n_args,
|
||||
va_list ap)
|
||||
{
|
||||
const unsigned short *pval = check_data;
|
||||
|
||||
_check_numbers_template("%hu", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_short(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_short(struct kunit *test, const char *file, const int line,
|
||||
const void *check_data, const char *string, const char *fmt, int n_args,
|
||||
va_list ap)
|
||||
{
|
||||
const short *pval = check_data;
|
||||
|
||||
_check_numbers_template("%hd", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_uchar(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_uchar(struct kunit *test, const char *file, const int line,
|
||||
const void *check_data, const char *string, const char *fmt, int n_args,
|
||||
va_list ap)
|
||||
{
|
||||
const unsigned char *pval = check_data;
|
||||
|
||||
_check_numbers_template("%hhu", pval, string, fmt, n_args, ap);
|
||||
}
|
||||
|
||||
static int __init check_char(const void *check_data, const char *string,
|
||||
const char *fmt, int n_args, va_list ap)
|
||||
static void check_char(struct kunit *test, const char *file, const int line, const void *check_data,
|
||||
const char *string, const char *fmt, int n_args, va_list ap)
|
||||
{
|
||||
const signed char *pval = check_data;
|
||||
|
||||
|
@ -156,7 +142,7 @@ static int __init check_char(const void *check_data, const char *string,
|
|||
}
|
||||
|
||||
/* Selection of interesting numbers to test, copied from test-kstrtox.c */
|
||||
static const unsigned long long numbers[] __initconst = {
|
||||
static const unsigned long long numbers[] = {
|
||||
0x0ULL,
|
||||
0x1ULL,
|
||||
0x7fULL,
|
||||
|
@ -196,7 +182,7 @@ do { \
|
|||
T result = ~expect_val; /* should be overwritten */ \
|
||||
\
|
||||
snprintf(test_buffer, BUF_SIZE, gen_fmt, expect_val); \
|
||||
_test(fn, &expect_val, test_buffer, "%" scan_fmt, 1, &result); \
|
||||
_test(test, __FILE__, __LINE__, fn, &expect_val, test_buffer, "%" scan_fmt, 1, &result);\
|
||||
} while (0)
|
||||
|
||||
#define simple_numbers_loop(T, gen_fmt, scan_fmt, fn) \
|
||||
|
@ -214,7 +200,7 @@ do { \
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
static void __init numbers_simple(void)
|
||||
static void numbers_simple(struct kunit *test)
|
||||
{
|
||||
simple_numbers_loop(unsigned long long, "%llu", "llu", check_ull);
|
||||
simple_numbers_loop(long long, "%lld", "lld", check_ll);
|
||||
|
@ -267,14 +253,14 @@ static void __init numbers_simple(void)
|
|||
* the raw prandom*() functions (Not mathematically rigorous!!).
|
||||
* Variabilty of length and value is more important than perfect randomness.
|
||||
*/
|
||||
static u32 __init next_test_random(u32 max_bits)
|
||||
static u32 next_test_random(u32 max_bits)
|
||||
{
|
||||
u32 n_bits = hweight32(prandom_u32_state(&rnd_state)) % (max_bits + 1);
|
||||
|
||||
return prandom_u32_state(&rnd_state) & GENMASK(n_bits, 0);
|
||||
}
|
||||
|
||||
static unsigned long long __init next_test_random_ull(void)
|
||||
static unsigned long long next_test_random_ull(void)
|
||||
{
|
||||
u32 rand1 = prandom_u32_state(&rnd_state);
|
||||
u32 n_bits = (hweight32(rand1) * 3) % 64;
|
||||
|
@ -311,7 +297,7 @@ do { \
|
|||
* updating buf_pos and returning the number of characters appended.
|
||||
* On error buf_pos is not changed and return value is 0.
|
||||
*/
|
||||
static int __init __printf(4, 5)
|
||||
static int __printf(4, 5)
|
||||
append_fmt(char *buf, int *buf_pos, int buf_len, const char *val_fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -333,7 +319,7 @@ append_fmt(char *buf, int *buf_pos, int buf_len, const char *val_fmt, ...)
|
|||
* Convenience function to append the field delimiter string
|
||||
* to both the value string and format string buffers.
|
||||
*/
|
||||
static void __init append_delim(char *str_buf, int *str_buf_pos, int str_buf_len,
|
||||
static void append_delim(char *str_buf, int *str_buf_pos, int str_buf_len,
|
||||
char *fmt_buf, int *fmt_buf_pos, int fmt_buf_len,
|
||||
const char *delim_str)
|
||||
{
|
||||
|
@ -344,7 +330,7 @@ static void __init append_delim(char *str_buf, int *str_buf_pos, int str_buf_len
|
|||
#define test_array_8(fn, check_data, string, fmt, arr) \
|
||||
do { \
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arr) != 8); \
|
||||
_test(fn, check_data, string, fmt, 8, \
|
||||
_test(test, __FILE__, __LINE__, fn, check_data, string, fmt, 8, \
|
||||
&(arr)[0], &(arr)[1], &(arr)[2], &(arr)[3], \
|
||||
&(arr)[4], &(arr)[5], &(arr)[6], &(arr)[7]); \
|
||||
} while (0)
|
||||
|
@ -398,7 +384,7 @@ do { \
|
|||
test_array_8(fn, expect, test_buffer, fmt_buffer, result); \
|
||||
} while (0)
|
||||
|
||||
static void __init numbers_list_ll(const char *delim)
|
||||
static void numbers_list_ll(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_8(unsigned long long, "%llu", delim, "llu", check_ull);
|
||||
numbers_list_8(long long, "%lld", delim, "lld", check_ll);
|
||||
|
@ -408,7 +394,7 @@ static void __init numbers_list_ll(const char *delim)
|
|||
numbers_list_8(long long, "0x%llx", delim, "lli", check_ll);
|
||||
}
|
||||
|
||||
static void __init numbers_list_l(const char *delim)
|
||||
static void numbers_list_l(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_8(unsigned long, "%lu", delim, "lu", check_ulong);
|
||||
numbers_list_8(long, "%ld", delim, "ld", check_long);
|
||||
|
@ -418,7 +404,7 @@ static void __init numbers_list_l(const char *delim)
|
|||
numbers_list_8(long, "0x%lx", delim, "li", check_long);
|
||||
}
|
||||
|
||||
static void __init numbers_list_d(const char *delim)
|
||||
static void numbers_list_d(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_8(unsigned int, "%u", delim, "u", check_uint);
|
||||
numbers_list_8(int, "%d", delim, "d", check_int);
|
||||
|
@ -428,7 +414,7 @@ static void __init numbers_list_d(const char *delim)
|
|||
numbers_list_8(int, "0x%x", delim, "i", check_int);
|
||||
}
|
||||
|
||||
static void __init numbers_list_h(const char *delim)
|
||||
static void numbers_list_h(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_8(unsigned short, "%hu", delim, "hu", check_ushort);
|
||||
numbers_list_8(short, "%hd", delim, "hd", check_short);
|
||||
|
@ -438,7 +424,7 @@ static void __init numbers_list_h(const char *delim)
|
|||
numbers_list_8(short, "0x%hx", delim, "hi", check_short);
|
||||
}
|
||||
|
||||
static void __init numbers_list_hh(const char *delim)
|
||||
static void numbers_list_hh(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_8(unsigned char, "%hhu", delim, "hhu", check_uchar);
|
||||
numbers_list_8(signed char, "%hhd", delim, "hhd", check_char);
|
||||
|
@ -448,16 +434,19 @@ static void __init numbers_list_hh(const char *delim)
|
|||
numbers_list_8(signed char, "0x%hhx", delim, "hhi", check_char);
|
||||
}
|
||||
|
||||
static void __init numbers_list(const char *delim)
|
||||
static void numbers_list(struct kunit *test)
|
||||
{
|
||||
numbers_list_ll(delim);
|
||||
numbers_list_l(delim);
|
||||
numbers_list_d(delim);
|
||||
numbers_list_h(delim);
|
||||
numbers_list_hh(delim);
|
||||
const char * const *param = test->param_value;
|
||||
const char *delim = *param;
|
||||
|
||||
numbers_list_ll(test, delim);
|
||||
numbers_list_l(test, delim);
|
||||
numbers_list_d(test, delim);
|
||||
numbers_list_h(test, delim);
|
||||
numbers_list_hh(test, delim);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_ll(const char *delim)
|
||||
static void numbers_list_field_width_ll(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_fix_width(unsigned long long, "%llu", delim, 20, "llu", check_ull);
|
||||
numbers_list_fix_width(long long, "%lld", delim, 20, "lld", check_ll);
|
||||
|
@ -467,7 +456,7 @@ static void __init numbers_list_field_width_ll(const char *delim)
|
|||
numbers_list_fix_width(long long, "0x%llx", delim, 18, "lli", check_ll);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_l(const char *delim)
|
||||
static void numbers_list_field_width_l(struct kunit *test, const char *delim)
|
||||
{
|
||||
#if BITS_PER_LONG == 64
|
||||
numbers_list_fix_width(unsigned long, "%lu", delim, 20, "lu", check_ulong);
|
||||
|
@ -486,7 +475,7 @@ static void __init numbers_list_field_width_l(const char *delim)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_d(const char *delim)
|
||||
static void numbers_list_field_width_d(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_fix_width(unsigned int, "%u", delim, 10, "u", check_uint);
|
||||
numbers_list_fix_width(int, "%d", delim, 11, "d", check_int);
|
||||
|
@ -496,7 +485,7 @@ static void __init numbers_list_field_width_d(const char *delim)
|
|||
numbers_list_fix_width(int, "0x%x", delim, 10, "i", check_int);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_h(const char *delim)
|
||||
static void numbers_list_field_width_h(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_fix_width(unsigned short, "%hu", delim, 5, "hu", check_ushort);
|
||||
numbers_list_fix_width(short, "%hd", delim, 6, "hd", check_short);
|
||||
|
@ -506,7 +495,7 @@ static void __init numbers_list_field_width_h(const char *delim)
|
|||
numbers_list_fix_width(short, "0x%hx", delim, 6, "hi", check_short);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_hh(const char *delim)
|
||||
static void numbers_list_field_width_hh(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_fix_width(unsigned char, "%hhu", delim, 3, "hhu", check_uchar);
|
||||
numbers_list_fix_width(signed char, "%hhd", delim, 4, "hhd", check_char);
|
||||
|
@ -520,16 +509,19 @@ static void __init numbers_list_field_width_hh(const char *delim)
|
|||
* List of numbers separated by delim. Each field width specifier is the
|
||||
* maximum possible digits for the given type and base.
|
||||
*/
|
||||
static void __init numbers_list_field_width_typemax(const char *delim)
|
||||
static void numbers_list_field_width_typemax(struct kunit *test)
|
||||
{
|
||||
numbers_list_field_width_ll(delim);
|
||||
numbers_list_field_width_l(delim);
|
||||
numbers_list_field_width_d(delim);
|
||||
numbers_list_field_width_h(delim);
|
||||
numbers_list_field_width_hh(delim);
|
||||
const char * const *param = test->param_value;
|
||||
const char *delim = *param;
|
||||
|
||||
numbers_list_field_width_ll(test, delim);
|
||||
numbers_list_field_width_l(test, delim);
|
||||
numbers_list_field_width_d(test, delim);
|
||||
numbers_list_field_width_h(test, delim);
|
||||
numbers_list_field_width_hh(test, delim);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_val_ll(const char *delim)
|
||||
static void numbers_list_field_width_val_ll(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_val_width(unsigned long long, "%llu", delim, "llu", check_ull);
|
||||
numbers_list_val_width(long long, "%lld", delim, "lld", check_ll);
|
||||
|
@ -539,7 +531,7 @@ static void __init numbers_list_field_width_val_ll(const char *delim)
|
|||
numbers_list_val_width(long long, "0x%llx", delim, "lli", check_ll);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_val_l(const char *delim)
|
||||
static void numbers_list_field_width_val_l(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_val_width(unsigned long, "%lu", delim, "lu", check_ulong);
|
||||
numbers_list_val_width(long, "%ld", delim, "ld", check_long);
|
||||
|
@ -549,7 +541,7 @@ static void __init numbers_list_field_width_val_l(const char *delim)
|
|||
numbers_list_val_width(long, "0x%lx", delim, "li", check_long);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_val_d(const char *delim)
|
||||
static void numbers_list_field_width_val_d(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_val_width(unsigned int, "%u", delim, "u", check_uint);
|
||||
numbers_list_val_width(int, "%d", delim, "d", check_int);
|
||||
|
@ -559,7 +551,7 @@ static void __init numbers_list_field_width_val_d(const char *delim)
|
|||
numbers_list_val_width(int, "0x%x", delim, "i", check_int);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_val_h(const char *delim)
|
||||
static void numbers_list_field_width_val_h(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_val_width(unsigned short, "%hu", delim, "hu", check_ushort);
|
||||
numbers_list_val_width(short, "%hd", delim, "hd", check_short);
|
||||
|
@ -569,7 +561,7 @@ static void __init numbers_list_field_width_val_h(const char *delim)
|
|||
numbers_list_val_width(short, "0x%hx", delim, "hi", check_short);
|
||||
}
|
||||
|
||||
static void __init numbers_list_field_width_val_hh(const char *delim)
|
||||
static void numbers_list_field_width_val_hh(struct kunit *test, const char *delim)
|
||||
{
|
||||
numbers_list_val_width(unsigned char, "%hhu", delim, "hhu", check_uchar);
|
||||
numbers_list_val_width(signed char, "%hhd", delim, "hhd", check_char);
|
||||
|
@ -583,13 +575,16 @@ static void __init numbers_list_field_width_val_hh(const char *delim)
|
|||
* List of numbers separated by delim. Each field width specifier is the
|
||||
* exact length of the corresponding value digits in the string being scanned.
|
||||
*/
|
||||
static void __init numbers_list_field_width_val_width(const char *delim)
|
||||
static void numbers_list_field_width_val_width(struct kunit *test)
|
||||
{
|
||||
numbers_list_field_width_val_ll(delim);
|
||||
numbers_list_field_width_val_l(delim);
|
||||
numbers_list_field_width_val_d(delim);
|
||||
numbers_list_field_width_val_h(delim);
|
||||
numbers_list_field_width_val_hh(delim);
|
||||
const char * const *param = test->param_value;
|
||||
const char *delim = *param;
|
||||
|
||||
numbers_list_field_width_val_ll(test, delim);
|
||||
numbers_list_field_width_val_l(test, delim);
|
||||
numbers_list_field_width_val_d(test, delim);
|
||||
numbers_list_field_width_val_h(test, delim);
|
||||
numbers_list_field_width_val_hh(test, delim);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -598,9 +593,14 @@ static void __init numbers_list_field_width_val_width(const char *delim)
|
|||
* of digits. For example the hex values c0,3,bf01,303 would have a
|
||||
* string representation of "c03bf01303" and extracted with "%2x%1x%4x%3x".
|
||||
*/
|
||||
static void __init numbers_slice(void)
|
||||
static void numbers_slice(struct kunit *test)
|
||||
{
|
||||
numbers_list_field_width_val_width("");
|
||||
const char *delim = "";
|
||||
|
||||
KUNIT_ASSERT_PTR_EQ(test, test->param_value, NULL);
|
||||
test->param_value = &delim;
|
||||
|
||||
numbers_list_field_width_val_width(test);
|
||||
}
|
||||
|
||||
#define test_number_prefix(T, str, scan_fmt, expect0, expect1, n_args, fn) \
|
||||
|
@ -608,14 +608,14 @@ do { \
|
|||
const T expect[2] = { expect0, expect1 }; \
|
||||
T result[2] = { (T)~expect[0], (T)~expect[1] }; \
|
||||
\
|
||||
_test(fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]); \
|
||||
_test(test, __FILE__, __LINE__, fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]);\
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Number prefix is >= field width.
|
||||
* Expected behaviour is derived from testing userland sscanf.
|
||||
*/
|
||||
static void __init numbers_prefix_overflow(void)
|
||||
static void numbers_prefix_overflow(struct kunit *test)
|
||||
{
|
||||
/*
|
||||
* Negative decimal with a field of width 1, should quit scanning
|
||||
|
@ -684,25 +684,17 @@ do { \
|
|||
T got; \
|
||||
char *endp; \
|
||||
int len; \
|
||||
bool fail = false; \
|
||||
\
|
||||
total_tests++; \
|
||||
len = snprintf(test_buffer, BUF_SIZE, gen_fmt, expect); \
|
||||
got = (fn)(test_buffer, &endp, base); \
|
||||
pr_debug(#fn "(\"%s\", %d) -> " gen_fmt "\n", test_buffer, base, got); \
|
||||
if (got != (expect)) { \
|
||||
fail = true; \
|
||||
pr_warn(#fn "(\"%s\", %d): got " gen_fmt " expected " gen_fmt "\n", \
|
||||
test_buffer, base, got, expect); \
|
||||
KUNIT_FAIL(test, #fn "(\"%s\", %d): got " gen_fmt " expected " gen_fmt, \
|
||||
test_buffer, base, got, expect); \
|
||||
} else if (endp != test_buffer + len) { \
|
||||
fail = true; \
|
||||
pr_warn(#fn "(\"%s\", %d) startp=0x%px got endp=0x%px expected 0x%px\n", \
|
||||
test_buffer, base, test_buffer, \
|
||||
test_buffer + len, endp); \
|
||||
KUNIT_FAIL(test, #fn "(\"%s\", %d) startp=0x%px got endp=0x%px expected 0x%px", \
|
||||
test_buffer, base, test_buffer, \
|
||||
test_buffer + len, endp); \
|
||||
} \
|
||||
\
|
||||
if (fail) \
|
||||
failed_tests++; \
|
||||
} while (0)
|
||||
|
||||
#define test_simple_strtoxx(T, fn, gen_fmt, base) \
|
||||
|
@ -718,7 +710,7 @@ do { \
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
static void __init test_simple_strtoull(void)
|
||||
static void test_simple_strtoull(struct kunit *test)
|
||||
{
|
||||
test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu", 10);
|
||||
test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu", 0);
|
||||
|
@ -727,7 +719,7 @@ static void __init test_simple_strtoull(void)
|
|||
test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 0);
|
||||
}
|
||||
|
||||
static void __init test_simple_strtoll(void)
|
||||
static void test_simple_strtoll(struct kunit *test)
|
||||
{
|
||||
test_simple_strtoxx(long long, simple_strtoll, "%lld", 10);
|
||||
test_simple_strtoxx(long long, simple_strtoll, "%lld", 0);
|
||||
|
@ -736,7 +728,7 @@ static void __init test_simple_strtoll(void)
|
|||
test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 0);
|
||||
}
|
||||
|
||||
static void __init test_simple_strtoul(void)
|
||||
static void test_simple_strtoul(struct kunit *test)
|
||||
{
|
||||
test_simple_strtoxx(unsigned long, simple_strtoul, "%lu", 10);
|
||||
test_simple_strtoxx(unsigned long, simple_strtoul, "%lu", 0);
|
||||
|
@ -745,7 +737,7 @@ static void __init test_simple_strtoul(void)
|
|||
test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 0);
|
||||
}
|
||||
|
||||
static void __init test_simple_strtol(void)
|
||||
static void test_simple_strtol(struct kunit *test)
|
||||
{
|
||||
test_simple_strtoxx(long, simple_strtol, "%ld", 10);
|
||||
test_simple_strtoxx(long, simple_strtol, "%ld", 0);
|
||||
|
@ -755,60 +747,69 @@ static void __init test_simple_strtol(void)
|
|||
}
|
||||
|
||||
/* Selection of common delimiters/separators between numbers in a string. */
|
||||
static const char * const number_delimiters[] __initconst = {
|
||||
static const char * const number_delimiters[] = {
|
||||
" ", ":", ",", "-", "/",
|
||||
};
|
||||
|
||||
static void __init test_numbers(void)
|
||||
static void number_delimiter_param_desc(const char * const *param,
|
||||
char *desc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* String containing only one number. */
|
||||
numbers_simple();
|
||||
|
||||
/* String with multiple numbers separated by delimiter. */
|
||||
for (i = 0; i < ARRAY_SIZE(number_delimiters); i++) {
|
||||
numbers_list(number_delimiters[i]);
|
||||
|
||||
/* Field width may be longer than actual field digits. */
|
||||
numbers_list_field_width_typemax(number_delimiters[i]);
|
||||
|
||||
/* Each field width exactly length of actual field digits. */
|
||||
numbers_list_field_width_val_width(number_delimiters[i]);
|
||||
}
|
||||
|
||||
/* Slice continuous sequence of digits using field widths. */
|
||||
numbers_slice();
|
||||
|
||||
numbers_prefix_overflow();
|
||||
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "\"%s\"", *param);
|
||||
}
|
||||
|
||||
static void __init selftest(void)
|
||||
KUNIT_ARRAY_PARAM(number_delimiters, number_delimiters, number_delimiter_param_desc);
|
||||
|
||||
static struct kunit_case scanf_test_cases[] = {
|
||||
KUNIT_CASE(numbers_simple),
|
||||
/* String with multiple numbers separated by delimiter. */
|
||||
KUNIT_CASE_PARAM(numbers_list, number_delimiters_gen_params),
|
||||
/* Field width may be longer than actual field digits. */
|
||||
KUNIT_CASE_PARAM(numbers_list_field_width_typemax, number_delimiters_gen_params),
|
||||
/* Each field width exactly length of actual field digits. */
|
||||
KUNIT_CASE_PARAM(numbers_list_field_width_val_width, number_delimiters_gen_params),
|
||||
/* Slice continuous sequence of digits using field widths. */
|
||||
KUNIT_CASE(numbers_slice),
|
||||
KUNIT_CASE(numbers_prefix_overflow),
|
||||
|
||||
KUNIT_CASE(test_simple_strtoull),
|
||||
KUNIT_CASE(test_simple_strtoll),
|
||||
KUNIT_CASE(test_simple_strtoul),
|
||||
KUNIT_CASE(test_simple_strtol),
|
||||
{}
|
||||
};
|
||||
|
||||
static int scanf_suite_init(struct kunit_suite *suite)
|
||||
{
|
||||
test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
|
||||
if (!test_buffer)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
|
||||
fmt_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
|
||||
if (!fmt_buffer) {
|
||||
kfree(test_buffer);
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
prandom_seed_state(&rnd_state, 3141592653589793238ULL);
|
||||
|
||||
test_numbers();
|
||||
|
||||
test_simple_strtoull();
|
||||
test_simple_strtoll();
|
||||
test_simple_strtoul();
|
||||
test_simple_strtol();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scanf_suite_exit(struct kunit_suite *suite)
|
||||
{
|
||||
kfree(fmt_buffer);
|
||||
kfree(test_buffer);
|
||||
}
|
||||
|
||||
KSTM_MODULE_LOADERS(test_scanf);
|
||||
static struct kunit_suite scanf_test_suite = {
|
||||
.name = "scanf",
|
||||
.suite_init = scanf_suite_init,
|
||||
.suite_exit = scanf_suite_exit,
|
||||
.test_cases = scanf_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(scanf_test_suite);
|
||||
|
||||
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
||||
MODULE_DESCRIPTION("Test cases for sscanf facility");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -184,6 +184,15 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
|
|||
#define INIT_UNION_assigned_copy(var_type) \
|
||||
INIT_STRUCT_assigned_copy(var_type)
|
||||
|
||||
/*
|
||||
* The "did we actually fill the stack?" check value needs
|
||||
* to be neither 0 nor any of the "pattern" bytes. The
|
||||
* pattern bytes are compiler, architecture, and type based,
|
||||
* so we have to pick a value that never appears for those
|
||||
* combinations. Use 0x99 which is not 0xFF, 0xFE, nor 0xAA.
|
||||
*/
|
||||
#define FILL_BYTE 0x99
|
||||
|
||||
/*
|
||||
* @name: unique string name for the test
|
||||
* @var_type: type to be tested for zeroing initialization
|
||||
|
@ -206,12 +215,12 @@ static noinline void test_ ## name (struct kunit *test) \
|
|||
ZERO_CLONE_ ## which(zero); \
|
||||
/* Clear entire check buffer for 0xFF overlap test. */ \
|
||||
memset(check_buf, 0x00, sizeof(check_buf)); \
|
||||
/* Fill stack with 0xFF. */ \
|
||||
/* Fill stack with FILL_BYTE. */ \
|
||||
ignored = leaf_ ##name((unsigned long)&ignored, 1, \
|
||||
FETCH_ARG_ ## which(zero)); \
|
||||
/* Verify all bytes overwritten with 0xFF. */ \
|
||||
/* Verify all bytes overwritten with FILL_BYTE. */ \
|
||||
for (sum = 0, i = 0; i < target_size; i++) \
|
||||
sum += (check_buf[i] != 0xFF); \
|
||||
sum += (check_buf[i] != FILL_BYTE); \
|
||||
/* Clear entire check buffer for later bit tests. */ \
|
||||
memset(check_buf, 0x00, sizeof(check_buf)); \
|
||||
/* Extract stack-defined variable contents. */ \
|
||||
|
@ -222,7 +231,8 @@ static noinline void test_ ## name (struct kunit *test) \
|
|||
* possible between the two leaf function calls. \
|
||||
*/ \
|
||||
KUNIT_ASSERT_EQ_MSG(test, sum, 0, \
|
||||
"leaf fill was not 0xFF!?\n"); \
|
||||
"leaf fill was not 0x%02X!?\n", \
|
||||
FILL_BYTE); \
|
||||
\
|
||||
/* Validate that compiler lined up fill and target. */ \
|
||||
KUNIT_ASSERT_TRUE_MSG(test, \
|
||||
|
@ -234,9 +244,9 @@ static noinline void test_ ## name (struct kunit *test) \
|
|||
(int)((ssize_t)(uintptr_t)fill_start - \
|
||||
(ssize_t)(uintptr_t)target_start)); \
|
||||
\
|
||||
/* Look for any bytes still 0xFF in check region. */ \
|
||||
/* Validate check region has no FILL_BYTE bytes. */ \
|
||||
for (sum = 0, i = 0; i < target_size; i++) \
|
||||
sum += (check_buf[i] == 0xFF); \
|
||||
sum += (check_buf[i] == FILL_BYTE); \
|
||||
\
|
||||
if (sum != 0 && xfail) \
|
||||
kunit_skip(test, \
|
||||
|
@ -271,12 +281,12 @@ static noinline int leaf_ ## name(unsigned long sp, bool fill, \
|
|||
* stack frame of SOME kind... \
|
||||
*/ \
|
||||
memset(buf, (char)(sp & 0xff), sizeof(buf)); \
|
||||
/* Fill variable with 0xFF. */ \
|
||||
/* Fill variable with FILL_BYTE. */ \
|
||||
if (fill) { \
|
||||
fill_start = &var; \
|
||||
fill_size = sizeof(var); \
|
||||
memset(fill_start, \
|
||||
(char)((sp & 0xff) | forced_mask), \
|
||||
FILL_BYTE & forced_mask, \
|
||||
fill_size); \
|
||||
} \
|
||||
\
|
||||
|
@ -469,7 +479,7 @@ static int noinline __leaf_switch_none(int path, bool fill)
|
|||
fill_start = &var;
|
||||
fill_size = sizeof(var);
|
||||
|
||||
memset(fill_start, forced_mask | 0x55, fill_size);
|
||||
memset(fill_start, (forced_mask | 0x55) & FILL_BYTE, fill_size);
|
||||
}
|
||||
memcpy(check_buf, target_start, target_size);
|
||||
break;
|
||||
|
@ -480,7 +490,7 @@ static int noinline __leaf_switch_none(int path, bool fill)
|
|||
fill_start = &var;
|
||||
fill_size = sizeof(var);
|
||||
|
||||
memset(fill_start, forced_mask | 0xaa, fill_size);
|
||||
memset(fill_start, (forced_mask | 0xaa) & FILL_BYTE, fill_size);
|
||||
}
|
||||
memcpy(check_buf, target_start, target_size);
|
||||
break;
|
|
@ -11,7 +11,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# $(dirname $0)/../kselftest/module.sh "description" module_name
|
||||
#
|
||||
# Example: tools/testing/selftests/lib/printf.sh
|
||||
# Example: tools/testing/selftests/lib/bitmap.sh
|
||||
|
||||
desc="" # Output prefix.
|
||||
module="" # Filename (without the .ko).
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
|
||||
all:
|
||||
|
||||
TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh scanf.sh
|
||||
TEST_PROGS := bitmap.sh
|
||||
include ../lib.mk
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
CONFIG_TEST_PRINTF=m
|
||||
CONFIG_TEST_SCANF=m
|
||||
CONFIG_TEST_BITMAP=m
|
||||
CONFIG_PRIME_NUMBERS=m
|
||||
CONFIG_TEST_BITOPS=m
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Checks fast/slow prime_number generation for inconsistencies
|
||||
$(dirname $0)/../kselftest/module.sh "prime numbers" prime_numbers selftest=65536
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Tests the printf infrastructure using test_printf kernel module.
|
||||
$(dirname $0)/../kselftest/module.sh "printf" test_printf
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Tests the scanf infrastructure using test_scanf kernel module.
|
||||
$(dirname $0)/../kselftest/module.sh "scanf" test_scanf
|
Loading…
Reference in New Issue
Block a user