summaryrefslogtreecommitdiff
path: root/lib/tests
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-12 12:13:01 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-12 12:13:01 -0800
commit136114e0abf03005e182d75761ab694648e6d388 (patch)
tree05c61b103fc9cb72a7cae99680a4b524347e9616 /lib/tests
parent4cff5c05e076d2ee4e34122aa956b84a2eaac587 (diff)
parent0dddf20b4fd4afd59767acc144ad4da60259f21f (diff)
Merge tag 'mm-nonmm-stable-2026-02-12-10-48' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull non-MM updates from Andrew Morton: - "ocfs2: give ocfs2 the ability to reclaim suballocator free bg" saves disk space by teaching ocfs2 to reclaim suballocator block group space (Heming Zhao) - "Add ARRAY_END(), and use it to fix off-by-one bugs" adds the ARRAY_END() macro and uses it in various places (Alejandro Colomar) - "vmcoreinfo: support VMCOREINFO_BYTES larger than PAGE_SIZE" makes the vmcore code future-safe, if VMCOREINFO_BYTES ever exceeds the page size (Pnina Feder) - "kallsyms: Prevent invalid access when showing module buildid" cleans up kallsyms code related to module buildid and fixes an invalid access crash when printing backtraces (Petr Mladek) - "Address page fault in ima_restore_measurement_list()" fixes a kexec-related crash that can occur when booting the second-stage kernel on x86 (Harshit Mogalapalli) - "kho: ABI headers and Documentation updates" updates the kexec handover ABI documentation (Mike Rapoport) - "Align atomic storage" adds the __aligned attribute to atomic_t and atomic64_t definitions to get natural alignment of both types on csky, m68k, microblaze, nios2, openrisc and sh (Finn Thain) - "kho: clean up page initialization logic" simplifies the page initialization logic in kho_restore_page() (Pratyush Yadav) - "Unload linux/kernel.h" moves several things out of kernel.h and into more appropriate places (Yury Norov) - "don't abuse task_struct.group_leader" removes the usage of ->group_leader when it is "obviously unnecessary" (Oleg Nesterov) - "list private v2 & luo flb" adds some infrastructure improvements to the live update orchestrator (Pasha Tatashin) * tag 'mm-nonmm-stable-2026-02-12-10-48' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (107 commits) watchdog/hardlockup: simplify perf event probe and remove per-cpu dependency procfs: fix missing RCU protection when reading real_parent in do_task_stat() watchdog/softlockup: fix sample ring index wrap in need_counting_irqs() kcsan, compiler_types: avoid duplicate type issues in BPF Type Format kho: fix doc for kho_restore_pages() tests/liveupdate: add in-kernel liveupdate test liveupdate: luo_flb: introduce File-Lifecycle-Bound global state liveupdate: luo_file: Use private list list: add kunit test for private list primitives list: add primitives for private list manipulations delayacct: fix uapi timespec64 definition panic: add panic_force_cpu= parameter to redirect panic to a specific CPU netclassid: use thread_group_leader(p) in update_classid_task() RDMA/umem: don't abuse current->group_leader drm/pan*: don't abuse current->group_leader drm/amd: kill the outdated "Only the pthreads threading model is supported" checks drm/amdgpu: don't abuse current->group_leader android/binder: use same_thread_group(proc->tsk, current) in binder_mmap() android/binder: don't abuse current->group_leader kho: skip memoryless NUMA nodes when reserving scratch areas ...
Diffstat (limited to 'lib/tests')
-rw-r--r--lib/tests/Makefile5
-rw-r--r--lib/tests/glob_kunit.c125
-rw-r--r--lib/tests/list-private-test.c76
-rw-r--r--lib/tests/liveupdate.c158
-rw-r--r--lib/tests/min_heap_kunit.c209
-rw-r--r--lib/tests/uuid_kunit.c106
6 files changed, 679 insertions, 0 deletions
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index 0f24048f3684..05f74edbc62b 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -20,20 +20,24 @@ 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_GLOB_KUNIT_TEST) += glob_kunit.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_LIST_PRIVATE_KUNIT_TEST) += list-private-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_LIVEUPDATE_TEST) += liveupdate.o
CFLAGS_longest_symbol_kunit.o += $(call cc-disable-warning, missing-prototypes)
obj-$(CONFIG_LONGEST_SYM_KUNIT_TEST) += longest_symbol_kunit.o
obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
+obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_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
@@ -50,5 +54,6 @@ 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_RATELIMIT_KUNIT_TEST) += test_ratelimit.o
+obj-$(CONFIG_UUID_KUNIT_TEST) += uuid_kunit.o
obj-$(CONFIG_TEST_RUNTIME_MODULE) += module/
diff --git a/lib/tests/glob_kunit.c b/lib/tests/glob_kunit.c
new file mode 100644
index 000000000000..362b1eda8e5b
--- /dev/null
+++ b/lib/tests/glob_kunit.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: MIT OR GPL-2.0
+/*
+ * Test cases for glob functions.
+ */
+
+#include <kunit/test.h>
+#include <linux/glob.h>
+#include <linux/module.h>
+
+/**
+ * struct glob_test_case - Test case for glob matching.
+ * @pat: Pattern to match.
+ * @str: String to match against.
+ * @expected: Expected glob_match result, true if matched.
+ */
+struct glob_test_case {
+ const char *pat;
+ const char *str;
+ bool expected;
+};
+
+static const struct glob_test_case glob_test_cases[] = {
+ /* Some basic tests */
+ { .pat = "a", .str = "a", .expected = true },
+ { .pat = "a", .str = "b", .expected = false },
+ { .pat = "a", .str = "aa", .expected = false },
+ { .pat = "a", .str = "", .expected = false },
+ { .pat = "", .str = "", .expected = true },
+ { .pat = "", .str = "a", .expected = false },
+ /* Simple character class tests */
+ { .pat = "[a]", .str = "a", .expected = true },
+ { .pat = "[a]", .str = "b", .expected = false },
+ { .pat = "[!a]", .str = "a", .expected = false },
+ { .pat = "[!a]", .str = "b", .expected = true },
+ { .pat = "[ab]", .str = "a", .expected = true },
+ { .pat = "[ab]", .str = "b", .expected = true },
+ { .pat = "[ab]", .str = "c", .expected = false },
+ { .pat = "[!ab]", .str = "c", .expected = true },
+ { .pat = "[a-c]", .str = "b", .expected = true },
+ { .pat = "[a-c]", .str = "d", .expected = false },
+ /* Corner cases in character class parsing */
+ { .pat = "[a-c-e-g]", .str = "-", .expected = true },
+ { .pat = "[a-c-e-g]", .str = "d", .expected = false },
+ { .pat = "[a-c-e-g]", .str = "f", .expected = true },
+ { .pat = "[]a-ceg-ik[]", .str = "a", .expected = true },
+ { .pat = "[]a-ceg-ik[]", .str = "]", .expected = true },
+ { .pat = "[]a-ceg-ik[]", .str = "[", .expected = true },
+ { .pat = "[]a-ceg-ik[]", .str = "h", .expected = true },
+ { .pat = "[]a-ceg-ik[]", .str = "f", .expected = false },
+ { .pat = "[!]a-ceg-ik[]", .str = "h", .expected = false },
+ { .pat = "[!]a-ceg-ik[]", .str = "]", .expected = false },
+ { .pat = "[!]a-ceg-ik[]", .str = "f", .expected = true },
+ /* Simple wild cards */
+ { .pat = "?", .str = "a", .expected = true },
+ { .pat = "?", .str = "aa", .expected = false },
+ { .pat = "??", .str = "a", .expected = false },
+ { .pat = "?x?", .str = "axb", .expected = true },
+ { .pat = "?x?", .str = "abx", .expected = false },
+ { .pat = "?x?", .str = "xab", .expected = false },
+ /* Asterisk wild cards (backtracking) */
+ { .pat = "*??", .str = "a", .expected = false },
+ { .pat = "*??", .str = "ab", .expected = true },
+ { .pat = "*??", .str = "abc", .expected = true },
+ { .pat = "*??", .str = "abcd", .expected = true },
+ { .pat = "??*", .str = "a", .expected = false },
+ { .pat = "??*", .str = "ab", .expected = true },
+ { .pat = "??*", .str = "abc", .expected = true },
+ { .pat = "??*", .str = "abcd", .expected = true },
+ { .pat = "?*?", .str = "a", .expected = false },
+ { .pat = "?*?", .str = "ab", .expected = true },
+ { .pat = "?*?", .str = "abc", .expected = true },
+ { .pat = "?*?", .str = "abcd", .expected = true },
+ { .pat = "*b", .str = "b", .expected = true },
+ { .pat = "*b", .str = "ab", .expected = true },
+ { .pat = "*b", .str = "ba", .expected = false },
+ { .pat = "*b", .str = "bb", .expected = true },
+ { .pat = "*b", .str = "abb", .expected = true },
+ { .pat = "*b", .str = "bab", .expected = true },
+ { .pat = "*bc", .str = "abbc", .expected = true },
+ { .pat = "*bc", .str = "bc", .expected = true },
+ { .pat = "*bc", .str = "bbc", .expected = true },
+ { .pat = "*bc", .str = "bcbc", .expected = true },
+ /* Multiple asterisks (complex backtracking) */
+ { .pat = "*ac*", .str = "abacadaeafag", .expected = true },
+ { .pat = "*ac*ae*ag*", .str = "abacadaeafag", .expected = true },
+ { .pat = "*a*b*[bc]*[ef]*g*", .str = "abacadaeafag", .expected = true },
+ { .pat = "*a*b*[ef]*[cd]*g*", .str = "abacadaeafag", .expected = false },
+ { .pat = "*abcd*", .str = "abcabcabcabcdefg", .expected = true },
+ { .pat = "*ab*cd*", .str = "abcabcabcabcdefg", .expected = true },
+ { .pat = "*abcd*abcdef*", .str = "abcabcdabcdeabcdefg", .expected = true },
+ { .pat = "*abcd*", .str = "abcabcabcabcefg", .expected = false },
+ { .pat = "*ab*cd*", .str = "abcabcabcabcefg", .expected = false },
+};
+
+static void glob_case_to_desc(const struct glob_test_case *t, char *desc)
+{
+ snprintf(desc, KUNIT_PARAM_DESC_SIZE, "pat:\"%s\" str:\"%s\"", t->pat, t->str);
+}
+
+KUNIT_ARRAY_PARAM(glob, glob_test_cases, glob_case_to_desc);
+
+static void glob_test_match(struct kunit *test)
+{
+ const struct glob_test_case *params = test->param_value;
+
+ KUNIT_EXPECT_EQ_MSG(test,
+ glob_match(params->pat, params->str),
+ params->expected,
+ "Pattern: \"%s\", String: \"%s\", Expected: %d",
+ params->pat, params->str, params->expected);
+}
+
+static struct kunit_case glob_kunit_test_cases[] = {
+ KUNIT_CASE_PARAM(glob_test_match, glob_gen_params),
+ {}
+};
+
+static struct kunit_suite glob_test_suite = {
+ .name = "glob",
+ .test_cases = glob_kunit_test_cases,
+};
+
+kunit_test_suite(glob_test_suite);
+MODULE_DESCRIPTION("Test cases for glob functions");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/lib/tests/list-private-test.c b/lib/tests/list-private-test.c
new file mode 100644
index 000000000000..3bd62939ae67
--- /dev/null
+++ b/lib/tests/list-private-test.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit compilation/smoke test for Private list primitives.
+ *
+ * Copyright (c) 2025, Google LLC.
+ * Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+#include <linux/list_private.h>
+#include <kunit/test.h>
+
+/*
+ * This forces compiler to warn if you access it directly, because list
+ * primitives expect (struct list_head *), not (volatile struct list_head *).
+ */
+#undef __private
+#define __private volatile
+
+/* Redefine ACCESS_PRIVATE for this test. */
+#undef ACCESS_PRIVATE
+#define ACCESS_PRIVATE(p, member) \
+ (*((struct list_head *)((unsigned long)&((p)->member))))
+
+struct list_test_struct {
+ int data;
+ struct list_head __private list;
+};
+
+static void list_private_compile_test(struct kunit *test)
+{
+ struct list_test_struct entry;
+ struct list_test_struct *pos, *n;
+ LIST_HEAD(head);
+
+ INIT_LIST_HEAD(&ACCESS_PRIVATE(&entry, list));
+ list_add(&ACCESS_PRIVATE(&entry, list), &head);
+ pos = &entry;
+
+ pos = list_private_entry(&ACCESS_PRIVATE(&entry, list), struct list_test_struct, list);
+ pos = list_private_first_entry(&head, struct list_test_struct, list);
+ pos = list_private_last_entry(&head, struct list_test_struct, list);
+ pos = list_private_next_entry(pos, list);
+ pos = list_private_prev_entry(pos, list);
+ pos = list_private_next_entry_circular(pos, &head, list);
+ pos = list_private_prev_entry_circular(pos, &head, list);
+
+ if (list_private_entry_is_head(pos, &head, list))
+ return;
+
+ list_private_for_each_entry(pos, &head, list) { }
+ list_private_for_each_entry_reverse(pos, &head, list) { }
+ list_private_for_each_entry_continue(pos, &head, list) { }
+ list_private_for_each_entry_continue_reverse(pos, &head, list) { }
+ list_private_for_each_entry_from(pos, &head, list) { }
+ list_private_for_each_entry_from_reverse(pos, &head, list) { }
+
+ list_private_for_each_entry_safe(pos, n, &head, list)
+ list_private_safe_reset_next(pos, n, list);
+ list_private_for_each_entry_safe_continue(pos, n, &head, list) { }
+ list_private_for_each_entry_safe_from(pos, n, &head, list) { }
+ list_private_for_each_entry_safe_reverse(pos, n, &head, list) { }
+}
+
+static struct kunit_case list_private_test_cases[] = {
+ KUNIT_CASE(list_private_compile_test),
+ {},
+};
+
+static struct kunit_suite list_private_test_module = {
+ .name = "list-private-kunit-test",
+ .test_cases = list_private_test_cases,
+};
+
+kunit_test_suite(list_private_test_module);
+
+MODULE_DESCRIPTION("KUnit compilation test for private list primitives");
+MODULE_LICENSE("GPL");
diff --git a/lib/tests/liveupdate.c b/lib/tests/liveupdate.c
new file mode 100644
index 000000000000..496d6ef91a30
--- /dev/null
+++ b/lib/tests/liveupdate.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (c) 2025, Google LLC.
+ * Pasha Tatashin <pasha.tatashin@soleen.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME " test: " fmt
+
+#include <linux/cleanup.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/liveupdate.h>
+#include <linux/module.h>
+#include "../../kernel/liveupdate/luo_internal.h"
+
+static const struct liveupdate_flb_ops test_flb_ops;
+#define DEFINE_TEST_FLB(i) { \
+ .ops = &test_flb_ops, \
+ .compatible = LIVEUPDATE_TEST_FLB_COMPATIBLE(i), \
+}
+
+/* Number of Test FLBs to register with every file handler */
+#define TEST_NFLBS 3
+static struct liveupdate_flb test_flbs[TEST_NFLBS] = {
+ DEFINE_TEST_FLB(0),
+ DEFINE_TEST_FLB(1),
+ DEFINE_TEST_FLB(2),
+};
+
+#define TEST_FLB_MAGIC_BASE 0xFEEDF00DCAFEBEE0ULL
+
+static int test_flb_preserve(struct liveupdate_flb_op_args *argp)
+{
+ ptrdiff_t index = argp->flb - test_flbs;
+
+ pr_info("%s: preserve was triggered\n", argp->flb->compatible);
+ argp->data = TEST_FLB_MAGIC_BASE + index;
+
+ return 0;
+}
+
+static void test_flb_unpreserve(struct liveupdate_flb_op_args *argp)
+{
+ pr_info("%s: unpreserve was triggered\n", argp->flb->compatible);
+}
+
+static int test_flb_retrieve(struct liveupdate_flb_op_args *argp)
+{
+ ptrdiff_t index = argp->flb - test_flbs;
+ u64 expected_data = TEST_FLB_MAGIC_BASE + index;
+
+ if (argp->data == expected_data) {
+ pr_info("%s: found flb data from the previous boot\n",
+ argp->flb->compatible);
+ argp->obj = (void *)argp->data;
+ } else {
+ pr_err("%s: ERROR - incorrect data handle: %llx, expected %llx\n",
+ argp->flb->compatible, argp->data, expected_data);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void test_flb_finish(struct liveupdate_flb_op_args *argp)
+{
+ ptrdiff_t index = argp->flb - test_flbs;
+ void *expected_obj = (void *)(TEST_FLB_MAGIC_BASE + index);
+
+ if (argp->obj == expected_obj) {
+ pr_info("%s: finish was triggered\n", argp->flb->compatible);
+ } else {
+ pr_err("%s: ERROR - finish called with invalid object\n",
+ argp->flb->compatible);
+ }
+}
+
+static const struct liveupdate_flb_ops test_flb_ops = {
+ .preserve = test_flb_preserve,
+ .unpreserve = test_flb_unpreserve,
+ .retrieve = test_flb_retrieve,
+ .finish = test_flb_finish,
+ .owner = THIS_MODULE,
+};
+
+static void liveupdate_test_init(void)
+{
+ static DEFINE_MUTEX(init_lock);
+ static bool initialized;
+ int i;
+
+ guard(mutex)(&init_lock);
+
+ if (initialized)
+ return;
+
+ for (i = 0; i < TEST_NFLBS; i++) {
+ struct liveupdate_flb *flb = &test_flbs[i];
+ void *obj;
+ int err;
+
+ err = liveupdate_flb_get_incoming(flb, &obj);
+ if (err && err != -ENODATA && err != -ENOENT) {
+ pr_err("liveupdate_flb_get_incoming for %s failed: %pe\n",
+ flb->compatible, ERR_PTR(err));
+ }
+ }
+ initialized = true;
+}
+
+void liveupdate_test_register(struct liveupdate_file_handler *fh)
+{
+ int err, i;
+
+ liveupdate_test_init();
+
+ for (i = 0; i < TEST_NFLBS; i++) {
+ struct liveupdate_flb *flb = &test_flbs[i];
+
+ err = liveupdate_register_flb(fh, flb);
+ if (err) {
+ pr_err("Failed to register %s %pe\n",
+ flb->compatible, ERR_PTR(err));
+ }
+ }
+
+ err = liveupdate_register_flb(fh, &test_flbs[0]);
+ if (!err || err != -EEXIST) {
+ pr_err("Failed: %s should be already registered, but got err: %pe\n",
+ test_flbs[0].compatible, ERR_PTR(err));
+ }
+
+ pr_info("Registered %d FLBs with file handler: [%s]\n",
+ TEST_NFLBS, fh->compatible);
+}
+
+void liveupdate_test_unregister(struct liveupdate_file_handler *fh)
+{
+ int err, i;
+
+ for (i = 0; i < TEST_NFLBS; i++) {
+ struct liveupdate_flb *flb = &test_flbs[i];
+
+ err = liveupdate_unregister_flb(fh, flb);
+ if (err) {
+ pr_err("Failed to unregister %s %pe\n",
+ flb->compatible, ERR_PTR(err));
+ }
+ }
+
+ pr_info("Unregistered %d FLBs from file handler: [%s]\n",
+ TEST_NFLBS, fh->compatible);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pasha Tatashin <pasha.tatashin@soleen.com>");
+MODULE_DESCRIPTION("In-kernel test for LUO mechanism");
diff --git a/lib/tests/min_heap_kunit.c b/lib/tests/min_heap_kunit.c
new file mode 100644
index 000000000000..9c1122661698
--- /dev/null
+++ b/lib/tests/min_heap_kunit.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for the min max heap.
+ */
+
+#include <kunit/test.h>
+#include <linux/min_heap.h>
+#include <linux/module.h>
+#include <linux/random.h>
+
+struct min_heap_test_case {
+ const char *str;
+ bool min_heap;
+};
+
+static struct min_heap_test_case min_heap_cases[] = {
+ {
+ .str = "min",
+ .min_heap = true,
+ },
+ {
+ .str = "max",
+ .min_heap = false,
+ },
+};
+
+KUNIT_ARRAY_PARAM_DESC(min_heap, min_heap_cases, str);
+
+DEFINE_MIN_HEAP(int, min_heap_test);
+
+static bool less_than(const void *lhs, const void *rhs, void __always_unused *args)
+{
+ return *(int *)lhs < *(int *)rhs;
+}
+
+static bool greater_than(const void *lhs, const void *rhs, void __always_unused *args)
+{
+ return *(int *)lhs > *(int *)rhs;
+}
+
+static void pop_verify_heap(struct kunit *test,
+ bool min_heap,
+ struct min_heap_test *heap,
+ const struct min_heap_callbacks *funcs)
+{
+ int *values = heap->data;
+ int last;
+
+ last = values[0];
+ min_heap_pop_inline(heap, funcs, NULL);
+ while (heap->nr > 0) {
+ if (min_heap)
+ KUNIT_EXPECT_LE(test, last, values[0]);
+ else
+ KUNIT_EXPECT_GE(test, last, values[0]);
+ last = values[0];
+ min_heap_pop_inline(heap, funcs, NULL);
+ }
+}
+
+static void test_heapify_all(struct kunit *test)
+{
+ const struct min_heap_test_case *params = test->param_value;
+ int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0,
+ -3, -1, -2, -4, 0x8000000, 0x7FFFFFF };
+ struct min_heap_test heap = {
+ .data = values,
+ .nr = ARRAY_SIZE(values),
+ .size = ARRAY_SIZE(values),
+ };
+ struct min_heap_callbacks funcs = {
+ .less = params->min_heap ? less_than : greater_than,
+ .swp = NULL,
+ };
+ int i;
+
+ /* Test with known set of values. */
+ min_heapify_all_inline(&heap, &funcs, NULL);
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+
+ /* Test with randomly generated values. */
+ heap.nr = ARRAY_SIZE(values);
+ for (i = 0; i < heap.nr; i++)
+ values[i] = get_random_u32();
+
+ min_heapify_all_inline(&heap, &funcs, NULL);
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+}
+
+static void test_heap_push(struct kunit *test)
+{
+ const struct min_heap_test_case *params = test->param_value;
+ const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0,
+ -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF };
+ int values[ARRAY_SIZE(data)];
+ struct min_heap_test heap = {
+ .data = values,
+ .nr = 0,
+ .size = ARRAY_SIZE(values),
+ };
+ struct min_heap_callbacks funcs = {
+ .less = params->min_heap ? less_than : greater_than,
+ .swp = NULL,
+ };
+ int i, temp;
+
+ /* Test with known set of values copied from data. */
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ min_heap_push_inline(&heap, &data[i], &funcs, NULL);
+
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+
+ /* Test with randomly generated values. */
+ while (heap.nr < heap.size) {
+ temp = get_random_u32();
+ min_heap_push_inline(&heap, &temp, &funcs, NULL);
+ }
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+}
+
+static void test_heap_pop_push(struct kunit *test)
+{
+ const struct min_heap_test_case *params = test->param_value;
+ const int data[] = { 3, 1, 2, 4, 0x80000000, 0x7FFFFFFF, 0,
+ -3, -1, -2, -4, 0x80000000, 0x7FFFFFFF };
+ int values[ARRAY_SIZE(data)];
+ struct min_heap_test heap = {
+ .data = values,
+ .nr = 0,
+ .size = ARRAY_SIZE(values),
+ };
+ struct min_heap_callbacks funcs = {
+ .less = params->min_heap ? less_than : greater_than,
+ .swp = NULL,
+ };
+ int i, temp;
+
+ /* Fill values with data to pop and replace. */
+ temp = params->min_heap ? 0x80000000 : 0x7FFFFFFF;
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ min_heap_push_inline(&heap, &temp, &funcs, NULL);
+
+ /* Test with known set of values copied from data. */
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ min_heap_pop_push_inline(&heap, &data[i], &funcs, NULL);
+
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+
+ heap.nr = 0;
+ for (i = 0; i < ARRAY_SIZE(data); i++)
+ min_heap_push_inline(&heap, &temp, &funcs, NULL);
+
+ /* Test with randomly generated values. */
+ for (i = 0; i < ARRAY_SIZE(data); i++) {
+ temp = get_random_u32();
+ min_heap_pop_push_inline(&heap, &temp, &funcs, NULL);
+ }
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+}
+
+static void test_heap_del(struct kunit *test)
+{
+ const struct min_heap_test_case *params = test->param_value;
+ int values[] = { 3, 1, 2, 4, 0x8000000, 0x7FFFFFF, 0,
+ -3, -1, -2, -4, 0x8000000, 0x7FFFFFF };
+ struct min_heap_test heap;
+
+ min_heap_init_inline(&heap, values, ARRAY_SIZE(values));
+ heap.nr = ARRAY_SIZE(values);
+ struct min_heap_callbacks funcs = {
+ .less = params->min_heap ? less_than : greater_than,
+ .swp = NULL,
+ };
+ int i;
+
+ /* Test with known set of values. */
+ min_heapify_all_inline(&heap, &funcs, NULL);
+ for (i = 0; i < ARRAY_SIZE(values) / 2; i++)
+ min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL);
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+
+ /* Test with randomly generated values. */
+ heap.nr = ARRAY_SIZE(values);
+ for (i = 0; i < heap.nr; i++)
+ values[i] = get_random_u32();
+ min_heapify_all_inline(&heap, &funcs, NULL);
+
+ for (i = 0; i < ARRAY_SIZE(values) / 2; i++)
+ min_heap_del_inline(&heap, get_random_u32() % heap.nr, &funcs, NULL);
+ pop_verify_heap(test, params->min_heap, &heap, &funcs);
+}
+
+static struct kunit_case min_heap_test_cases[] = {
+ KUNIT_CASE_PARAM(test_heapify_all, min_heap_gen_params),
+ KUNIT_CASE_PARAM(test_heap_push, min_heap_gen_params),
+ KUNIT_CASE_PARAM(test_heap_pop_push, min_heap_gen_params),
+ KUNIT_CASE_PARAM(test_heap_del, min_heap_gen_params),
+ {},
+};
+
+static struct kunit_suite min_heap_test_suite = {
+ .name = "min_heap",
+ .test_cases = min_heap_test_cases,
+};
+
+kunit_test_suite(min_heap_test_suite);
+
+MODULE_DESCRIPTION("Test cases for the min max heap");
+MODULE_LICENSE("GPL");
diff --git a/lib/tests/uuid_kunit.c b/lib/tests/uuid_kunit.c
new file mode 100644
index 000000000000..de71b2649dac
--- /dev/null
+++ b/lib/tests/uuid_kunit.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Test cases for lib/uuid.c module.
+ */
+
+#include <kunit/test.h>
+#include <linux/uuid.h>
+
+struct test_uuid_data {
+ const char *uuid;
+ guid_t le;
+ uuid_t be;
+};
+
+static const struct test_uuid_data test_uuid_test_data[] = {
+ {
+ .uuid = "c33f4995-3701-450e-9fbf-206a2e98e576",
+ .le = GUID_INIT(0xc33f4995, 0x3701, 0x450e, 0x9f, 0xbf, 0x20, 0x6a, 0x2e, 0x98, 0xe5, 0x76),
+ .be = UUID_INIT(0xc33f4995, 0x3701, 0x450e, 0x9f, 0xbf, 0x20, 0x6a, 0x2e, 0x98, 0xe5, 0x76),
+ },
+ {
+ .uuid = "64b4371c-77c1-48f9-8221-29f054fc023b",
+ .le = GUID_INIT(0x64b4371c, 0x77c1, 0x48f9, 0x82, 0x21, 0x29, 0xf0, 0x54, 0xfc, 0x02, 0x3b),
+ .be = UUID_INIT(0x64b4371c, 0x77c1, 0x48f9, 0x82, 0x21, 0x29, 0xf0, 0x54, 0xfc, 0x02, 0x3b),
+ },
+ {
+ .uuid = "0cb4ddff-a545-4401-9d06-688af53e7f84",
+ .le = GUID_INIT(0x0cb4ddff, 0xa545, 0x4401, 0x9d, 0x06, 0x68, 0x8a, 0xf5, 0x3e, 0x7f, 0x84),
+ .be = UUID_INIT(0x0cb4ddff, 0xa545, 0x4401, 0x9d, 0x06, 0x68, 0x8a, 0xf5, 0x3e, 0x7f, 0x84),
+ },
+};
+
+static const char * const test_uuid_wrong_data[] = {
+ "c33f4995-3701-450e-9fbf206a2e98e576 ", /* no hyphen(s) */
+ "64b4371c-77c1-48f9-8221-29f054XX023b", /* invalid character(s) */
+ "0cb4ddff-a545-4401-9d06-688af53e", /* not enough data */
+};
+
+static void uuid_test_guid_valid(struct kunit *test)
+{
+ unsigned int i;
+ const struct test_uuid_data *data;
+ guid_t le;
+
+ for (i = 0; i < ARRAY_SIZE(test_uuid_test_data); i++) {
+ data = &test_uuid_test_data[i];
+ KUNIT_EXPECT_EQ(test, guid_parse(data->uuid, &le), 0);
+ KUNIT_EXPECT_TRUE(test, guid_equal(&data->le, &le));
+ }
+}
+
+static void uuid_test_uuid_valid(struct kunit *test)
+{
+ unsigned int i;
+ const struct test_uuid_data *data;
+ uuid_t be;
+
+ for (i = 0; i < ARRAY_SIZE(test_uuid_test_data); i++) {
+ data = &test_uuid_test_data[i];
+ KUNIT_EXPECT_EQ(test, uuid_parse(data->uuid, &be), 0);
+ KUNIT_EXPECT_TRUE(test, uuid_equal(&data->be, &be));
+ }
+}
+
+static void uuid_test_guid_invalid(struct kunit *test)
+{
+ unsigned int i;
+ const char *uuid;
+ guid_t le;
+
+ for (i = 0; i < ARRAY_SIZE(test_uuid_wrong_data); i++) {
+ uuid = test_uuid_wrong_data[i];
+ KUNIT_EXPECT_EQ(test, guid_parse(uuid, &le), -EINVAL);
+ }
+}
+
+static void uuid_test_uuid_invalid(struct kunit *test)
+{
+ unsigned int i;
+ const char *uuid;
+ uuid_t be;
+
+ for (i = 0; i < ARRAY_SIZE(test_uuid_wrong_data); i++) {
+ uuid = test_uuid_wrong_data[i];
+ KUNIT_EXPECT_EQ(test, uuid_parse(uuid, &be), -EINVAL);
+ }
+}
+
+static struct kunit_case uuid_test_cases[] = {
+ KUNIT_CASE(uuid_test_guid_valid),
+ KUNIT_CASE(uuid_test_uuid_valid),
+ KUNIT_CASE(uuid_test_guid_invalid),
+ KUNIT_CASE(uuid_test_uuid_invalid),
+ {},
+};
+
+static struct kunit_suite uuid_test_suite = {
+ .name = "uuid",
+ .test_cases = uuid_test_cases,
+};
+
+kunit_test_suite(uuid_test_suite);
+
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
+MODULE_DESCRIPTION("Test cases for lib/uuid.c module");
+MODULE_LICENSE("Dual BSD/GPL");