summaryrefslogtreecommitdiff
path: root/lib/tests
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tests')
-rw-r--r--lib/tests/Makefile2
-rw-r--r--lib/tests/crc_kunit.c489
-rw-r--r--lib/tests/fortify_kunit.c4
-rw-r--r--lib/tests/seq_buf_kunit.c208
4 files changed, 211 insertions, 492 deletions
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index 56d645014482..83434b722193 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_BLACKHOLE_DEV_KUNIT_TEST) += blackhole_dev_kunit.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)
@@ -37,6 +36,7 @@ obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o
obj-$(CONFIG_RANDSTRUCT_KUNIT_TEST) += randstruct_kunit.o
obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o
+obj-$(CONFIG_SEQ_BUF_KUNIT_TEST) += seq_buf_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
diff --git a/lib/tests/crc_kunit.c b/lib/tests/crc_kunit.c
deleted file mode 100644
index 064c2d581557..000000000000
--- a/lib/tests/crc_kunit.c
+++ /dev/null
@@ -1,489 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Unit tests and benchmarks for the CRC library functions
- *
- * Copyright 2024 Google LLC
- *
- * Author: Eric Biggers <ebiggers@google.com>
- */
-#include <kunit/test.h>
-#include <linux/crc7.h>
-#include <linux/crc16.h>
-#include <linux/crc-t10dif.h>
-#include <linux/crc32.h>
-#include <linux/crc32c.h>
-#include <linux/crc64.h>
-#include <linux/prandom.h>
-#include <linux/vmalloc.h>
-
-#define CRC_KUNIT_SEED 42
-#define CRC_KUNIT_MAX_LEN 16384
-#define CRC_KUNIT_NUM_TEST_ITERS 1000
-
-static struct rnd_state rng;
-static u8 *test_buffer;
-static size_t test_buflen;
-
-/**
- * struct crc_variant - describes a CRC variant
- * @bits: Number of bits in the CRC, 1 <= @bits <= 64.
- * @le: true if it's a "little endian" CRC (reversed mapping between bits and
- * polynomial coefficients in each byte), false if it's a "big endian" CRC
- * (natural mapping between bits and polynomial coefficients in each byte)
- * @poly: The generator polynomial with the highest-order term omitted.
- * Bit-reversed if @le is true.
- * @func: The function to compute a CRC. The type signature uses u64 so that it
- * can fit any CRC up to CRC-64. The CRC is passed in, and is expected
- * to be returned in, the least significant bits of the u64. The
- * function is expected to *not* invert the CRC at the beginning and end.
- * @combine_func: Optional function to combine two CRCs.
- */
-struct crc_variant {
- int bits;
- bool le;
- u64 poly;
- u64 (*func)(u64 crc, const u8 *p, size_t len);
- u64 (*combine_func)(u64 crc1, u64 crc2, size_t len2);
-};
-
-static u32 rand32(void)
-{
- return prandom_u32_state(&rng);
-}
-
-static u64 rand64(void)
-{
- u32 n = rand32();
-
- return ((u64)n << 32) | rand32();
-}
-
-static u64 crc_mask(const struct crc_variant *v)
-{
- return (u64)-1 >> (64 - v->bits);
-}
-
-/* Reference implementation of any CRC variant */
-static u64 crc_ref(const struct crc_variant *v,
- u64 crc, const u8 *p, size_t len)
-{
- size_t i, j;
-
- for (i = 0; i < len; i++) {
- for (j = 0; j < 8; j++) {
- if (v->le) {
- crc ^= (p[i] >> j) & 1;
- crc = (crc >> 1) ^ ((crc & 1) ? v->poly : 0);
- } else {
- crc ^= (u64)((p[i] >> (7 - j)) & 1) <<
- (v->bits - 1);
- if (crc & (1ULL << (v->bits - 1)))
- crc = ((crc << 1) ^ v->poly) &
- crc_mask(v);
- else
- crc <<= 1;
- }
- }
- }
- return crc;
-}
-
-static int crc_suite_init(struct kunit_suite *suite)
-{
- /*
- * Allocate the test buffer using vmalloc() with a page-aligned length
- * so that it is immediately followed by a guard page. This allows
- * buffer overreads to be detected, even in assembly code.
- */
- test_buflen = round_up(CRC_KUNIT_MAX_LEN, PAGE_SIZE);
- test_buffer = vmalloc(test_buflen);
- if (!test_buffer)
- return -ENOMEM;
-
- prandom_seed_state(&rng, CRC_KUNIT_SEED);
- prandom_bytes_state(&rng, test_buffer, test_buflen);
- return 0;
-}
-
-static void crc_suite_exit(struct kunit_suite *suite)
-{
- vfree(test_buffer);
- test_buffer = NULL;
-}
-
-/* Generate a random initial CRC. */
-static u64 generate_random_initial_crc(const struct crc_variant *v)
-{
- switch (rand32() % 4) {
- case 0:
- return 0;
- case 1:
- return crc_mask(v); /* All 1 bits */
- default:
- return rand64() & crc_mask(v);
- }
-}
-
-/* Generate a random length, preferring small lengths. */
-static size_t generate_random_length(size_t max_length)
-{
- size_t len;
-
- switch (rand32() % 3) {
- case 0:
- len = rand32() % 128;
- break;
- case 1:
- len = rand32() % 3072;
- break;
- default:
- len = rand32();
- break;
- }
- return len % (max_length + 1);
-}
-
-/* Test that v->func gives the same CRCs as a reference implementation. */
-static void crc_main_test(struct kunit *test, const struct crc_variant *v)
-{
- size_t i;
-
- for (i = 0; i < CRC_KUNIT_NUM_TEST_ITERS; i++) {
- u64 init_crc, expected_crc, actual_crc;
- size_t len, offset;
- bool nosimd;
-
- init_crc = generate_random_initial_crc(v);
- len = generate_random_length(CRC_KUNIT_MAX_LEN);
-
- /* Generate a random offset. */
- if (rand32() % 2 == 0) {
- /* Use a random alignment mod 64 */
- offset = rand32() % 64;
- offset = min(offset, CRC_KUNIT_MAX_LEN - len);
- } else {
- /* Go up to the guard page, to catch buffer overreads */
- offset = test_buflen - len;
- }
-
- if (rand32() % 8 == 0)
- /* Refresh the data occasionally. */
- prandom_bytes_state(&rng, &test_buffer[offset], len);
-
- nosimd = rand32() % 8 == 0;
-
- /*
- * Compute the CRC, and verify that it equals the CRC computed
- * by a simple bit-at-a-time reference implementation.
- */
- expected_crc = crc_ref(v, init_crc, &test_buffer[offset], len);
- if (nosimd)
- local_irq_disable();
- actual_crc = v->func(init_crc, &test_buffer[offset], len);
- if (nosimd)
- local_irq_enable();
- KUNIT_EXPECT_EQ_MSG(test, expected_crc, actual_crc,
- "Wrong result with len=%zu offset=%zu nosimd=%d",
- len, offset, nosimd);
- }
-}
-
-/* Test that CRC(concat(A, B)) == combine_CRCs(CRC(A), CRC(B), len(B)). */
-static void crc_combine_test(struct kunit *test, const struct crc_variant *v)
-{
- int i;
-
- for (i = 0; i < 100; i++) {
- u64 init_crc = generate_random_initial_crc(v);
- size_t len1 = generate_random_length(CRC_KUNIT_MAX_LEN);
- size_t len2 = generate_random_length(CRC_KUNIT_MAX_LEN - len1);
- u64 crc1, crc2, expected_crc, actual_crc;
-
- prandom_bytes_state(&rng, test_buffer, len1 + len2);
- crc1 = v->func(init_crc, test_buffer, len1);
- crc2 = v->func(0, &test_buffer[len1], len2);
- expected_crc = v->func(init_crc, test_buffer, len1 + len2);
- actual_crc = v->combine_func(crc1, crc2, len2);
- KUNIT_EXPECT_EQ_MSG(test, expected_crc, actual_crc,
- "CRC combination gave wrong result with len1=%zu len2=%zu\n",
- len1, len2);
- }
-}
-
-static void crc_test(struct kunit *test, const struct crc_variant *v)
-{
- crc_main_test(test, v);
- if (v->combine_func)
- crc_combine_test(test, v);
-}
-
-static __always_inline void
-crc_benchmark(struct kunit *test,
- u64 (*crc_func)(u64 crc, const u8 *p, size_t len))
-{
- static const size_t lens_to_test[] = {
- 1, 16, 64, 127, 128, 200, 256, 511, 512, 1024, 3173, 4096, 16384,
- };
- size_t len, i, j, num_iters;
- /*
- * The CRC value that this function computes in a series of calls to
- * crc_func is never actually used, so use volatile to ensure that the
- * computations are done as intended and don't all get optimized out.
- */
- volatile u64 crc = 0;
- u64 t;
-
- if (!IS_ENABLED(CONFIG_CRC_BENCHMARK))
- kunit_skip(test, "not enabled");
-
- /* warm-up */
- for (i = 0; i < 10000000; i += CRC_KUNIT_MAX_LEN)
- crc = crc_func(crc, test_buffer, CRC_KUNIT_MAX_LEN);
-
- for (i = 0; i < ARRAY_SIZE(lens_to_test); i++) {
- len = lens_to_test[i];
- KUNIT_ASSERT_LE(test, len, CRC_KUNIT_MAX_LEN);
- num_iters = 10000000 / (len + 128);
- preempt_disable();
- t = ktime_get_ns();
- for (j = 0; j < num_iters; j++)
- crc = crc_func(crc, test_buffer, len);
- t = ktime_get_ns() - t;
- preempt_enable();
- kunit_info(test, "len=%zu: %llu MB/s\n",
- len, div64_u64((u64)len * num_iters * 1000, t));
- }
-}
-
-/* crc7_be */
-
-static u64 crc7_be_wrapper(u64 crc, const u8 *p, size_t len)
-{
- /*
- * crc7_be() left-aligns the 7-bit CRC in a u8, whereas the test wants a
- * right-aligned CRC (in a u64). Convert between the conventions.
- */
- return crc7_be(crc << 1, p, len) >> 1;
-}
-
-static const struct crc_variant crc_variant_crc7_be = {
- .bits = 7,
- .poly = 0x9,
- .func = crc7_be_wrapper,
-};
-
-static void crc7_be_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc7_be);
-}
-
-static void crc7_be_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc7_be_wrapper);
-}
-
-/* crc16 */
-
-static u64 crc16_wrapper(u64 crc, const u8 *p, size_t len)
-{
- return crc16(crc, p, len);
-}
-
-static const struct crc_variant crc_variant_crc16 = {
- .bits = 16,
- .le = true,
- .poly = 0xa001,
- .func = crc16_wrapper,
-};
-
-static void crc16_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc16);
-}
-
-static void crc16_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc16_wrapper);
-}
-
-/* crc_t10dif */
-
-static u64 crc_t10dif_wrapper(u64 crc, const u8 *p, size_t len)
-{
- return crc_t10dif_update(crc, p, len);
-}
-
-static const struct crc_variant crc_variant_crc_t10dif = {
- .bits = 16,
- .le = false,
- .poly = 0x8bb7,
- .func = crc_t10dif_wrapper,
-};
-
-static void crc_t10dif_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc_t10dif);
-}
-
-static void crc_t10dif_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc_t10dif_wrapper);
-}
-
-/* crc32_le */
-
-static u64 crc32_le_wrapper(u64 crc, const u8 *p, size_t len)
-{
- return crc32_le(crc, p, len);
-}
-
-static u64 crc32_le_combine_wrapper(u64 crc1, u64 crc2, size_t len2)
-{
- return crc32_le_combine(crc1, crc2, len2);
-}
-
-static const struct crc_variant crc_variant_crc32_le = {
- .bits = 32,
- .le = true,
- .poly = 0xedb88320,
- .func = crc32_le_wrapper,
- .combine_func = crc32_le_combine_wrapper,
-};
-
-static void crc32_le_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc32_le);
-}
-
-static void crc32_le_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc32_le_wrapper);
-}
-
-/* crc32_be */
-
-static u64 crc32_be_wrapper(u64 crc, const u8 *p, size_t len)
-{
- return crc32_be(crc, p, len);
-}
-
-static const struct crc_variant crc_variant_crc32_be = {
- .bits = 32,
- .le = false,
- .poly = 0x04c11db7,
- .func = crc32_be_wrapper,
-};
-
-static void crc32_be_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc32_be);
-}
-
-static void crc32_be_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc32_be_wrapper);
-}
-
-/* crc32c */
-
-static u64 crc32c_wrapper(u64 crc, const u8 *p, size_t len)
-{
- return crc32c(crc, p, len);
-}
-
-static const struct crc_variant crc_variant_crc32c = {
- .bits = 32,
- .le = true,
- .poly = 0x82f63b78,
- .func = crc32c_wrapper,
-};
-
-static void crc32c_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc32c);
-}
-
-static void crc32c_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc32c_wrapper);
-}
-
-/* crc64_be */
-
-static u64 crc64_be_wrapper(u64 crc, const u8 *p, size_t len)
-{
- return crc64_be(crc, p, len);
-}
-
-static const struct crc_variant crc_variant_crc64_be = {
- .bits = 64,
- .le = false,
- .poly = 0x42f0e1eba9ea3693,
- .func = crc64_be_wrapper,
-};
-
-static void crc64_be_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc64_be);
-}
-
-static void crc64_be_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc64_be_wrapper);
-}
-
-/* crc64_nvme */
-
-static u64 crc64_nvme_wrapper(u64 crc, const u8 *p, size_t len)
-{
- /* The inversions that crc64_nvme() does have to be undone here. */
- return ~crc64_nvme(~crc, p, len);
-}
-
-static const struct crc_variant crc_variant_crc64_nvme = {
- .bits = 64,
- .le = true,
- .poly = 0x9a6c9329ac4bc9b5,
- .func = crc64_nvme_wrapper,
-};
-
-static void crc64_nvme_test(struct kunit *test)
-{
- crc_test(test, &crc_variant_crc64_nvme);
-}
-
-static void crc64_nvme_benchmark(struct kunit *test)
-{
- crc_benchmark(test, crc64_nvme_wrapper);
-}
-
-static struct kunit_case crc_test_cases[] = {
- KUNIT_CASE(crc7_be_test),
- KUNIT_CASE(crc7_be_benchmark),
- KUNIT_CASE(crc16_test),
- KUNIT_CASE(crc16_benchmark),
- KUNIT_CASE(crc_t10dif_test),
- KUNIT_CASE(crc_t10dif_benchmark),
- KUNIT_CASE(crc32_le_test),
- KUNIT_CASE(crc32_le_benchmark),
- KUNIT_CASE(crc32_be_test),
- KUNIT_CASE(crc32_be_benchmark),
- KUNIT_CASE(crc32c_test),
- KUNIT_CASE(crc32c_benchmark),
- KUNIT_CASE(crc64_be_test),
- KUNIT_CASE(crc64_be_benchmark),
- KUNIT_CASE(crc64_nvme_test),
- KUNIT_CASE(crc64_nvme_benchmark),
- {},
-};
-
-static struct kunit_suite crc_test_suite = {
- .name = "crc",
- .test_cases = crc_test_cases,
- .suite_init = crc_suite_init,
- .suite_exit = crc_suite_exit,
-};
-kunit_test_suite(crc_test_suite);
-
-MODULE_DESCRIPTION("Unit tests and benchmarks for the CRC library functions");
-MODULE_LICENSE("GPL");
diff --git a/lib/tests/fortify_kunit.c b/lib/tests/fortify_kunit.c
index 29ffc62a71e3..fc9c76f026d6 100644
--- a/lib/tests/fortify_kunit.c
+++ b/lib/tests/fortify_kunit.c
@@ -1003,8 +1003,8 @@ 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) - 1;
- size_t two_len = sizeof(two) - 1;
+ volatile size_t one_len = sizeof(one) - 1;
+ volatile size_t two_len = sizeof(two) - 1;
OPTIMIZER_HIDE_VAR(one_len);
OPTIMIZER_HIDE_VAR(two_len);
diff --git a/lib/tests/seq_buf_kunit.c b/lib/tests/seq_buf_kunit.c
new file mode 100644
index 000000000000..8a01579a978e
--- /dev/null
+++ b/lib/tests/seq_buf_kunit.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit tests for the seq_buf API
+ *
+ * Copyright (C) 2025, Google LLC.
+ */
+
+#include <kunit/test.h>
+#include <linux/seq_buf.h>
+
+static void seq_buf_init_test(struct kunit *test)
+{
+ char buf[32];
+ struct seq_buf s;
+
+ seq_buf_init(&s, buf, sizeof(buf));
+
+ KUNIT_EXPECT_EQ(test, s.size, 32);
+ KUNIT_EXPECT_EQ(test, s.len, 0);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_EQ(test, seq_buf_buffer_left(&s), 32);
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 0);
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "");
+}
+
+static void seq_buf_declare_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 24);
+
+ KUNIT_EXPECT_EQ(test, s.size, 24);
+ KUNIT_EXPECT_EQ(test, s.len, 0);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_EQ(test, seq_buf_buffer_left(&s), 24);
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 0);
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "");
+}
+
+static void seq_buf_clear_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 128);
+
+ seq_buf_puts(&s, "hello");
+ KUNIT_EXPECT_EQ(test, s.len, 5);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello");
+
+ seq_buf_clear(&s);
+
+ KUNIT_EXPECT_EQ(test, s.len, 0);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "");
+}
+
+static void seq_buf_puts_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 16);
+
+ seq_buf_puts(&s, "hello");
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 5);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello");
+
+ seq_buf_puts(&s, " world");
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 11);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello world");
+}
+
+static void seq_buf_puts_overflow_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 10);
+
+ seq_buf_puts(&s, "123456789");
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 9);
+
+ seq_buf_puts(&s, "0");
+ KUNIT_EXPECT_TRUE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 10);
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "123456789");
+
+ seq_buf_clear(&s);
+ KUNIT_EXPECT_EQ(test, s.len, 0);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "");
+}
+
+static void seq_buf_putc_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 4);
+
+ seq_buf_putc(&s, 'a');
+ seq_buf_putc(&s, 'b');
+ seq_buf_putc(&s, 'c');
+
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 3);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "abc");
+
+ seq_buf_putc(&s, 'd');
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 4);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "abc");
+
+ seq_buf_putc(&s, 'e');
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 4);
+ KUNIT_EXPECT_TRUE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "abc");
+
+ seq_buf_clear(&s);
+ KUNIT_EXPECT_EQ(test, s.len, 0);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "");
+}
+
+static void seq_buf_printf_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 32);
+
+ seq_buf_printf(&s, "hello %s", "world");
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 11);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello world");
+
+ seq_buf_printf(&s, " %d", 123);
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 15);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello world 123");
+}
+
+static void seq_buf_printf_overflow_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 16);
+
+ seq_buf_printf(&s, "%lu", 1234567890UL);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 10);
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "1234567890");
+
+ seq_buf_printf(&s, "%s", "abcdefghij");
+ KUNIT_EXPECT_TRUE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 16);
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "1234567890abcde");
+
+ seq_buf_clear(&s);
+ KUNIT_EXPECT_EQ(test, s.len, 0);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "");
+}
+
+static void seq_buf_get_buf_commit_test(struct kunit *test)
+{
+ DECLARE_SEQ_BUF(s, 16);
+ char *buf;
+ size_t len;
+
+ len = seq_buf_get_buf(&s, &buf);
+ KUNIT_EXPECT_EQ(test, len, 16);
+ KUNIT_EXPECT_PTR_NE(test, buf, NULL);
+
+ memcpy(buf, "hello", 5);
+ seq_buf_commit(&s, 5);
+
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 5);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello");
+
+ len = seq_buf_get_buf(&s, &buf);
+ KUNIT_EXPECT_EQ(test, len, 11);
+ KUNIT_EXPECT_PTR_NE(test, buf, NULL);
+
+ memcpy(buf, " worlds!", 8);
+ seq_buf_commit(&s, 6);
+
+ KUNIT_EXPECT_EQ(test, seq_buf_used(&s), 11);
+ KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(&s));
+ KUNIT_EXPECT_STREQ(test, seq_buf_str(&s), "hello world");
+
+ len = seq_buf_get_buf(&s, &buf);
+ KUNIT_EXPECT_EQ(test, len, 5);
+ KUNIT_EXPECT_PTR_NE(test, buf, NULL);
+
+ seq_buf_commit(&s, -1);
+ KUNIT_EXPECT_TRUE(test, seq_buf_has_overflowed(&s));
+}
+
+static struct kunit_case seq_buf_test_cases[] = {
+ KUNIT_CASE(seq_buf_init_test),
+ KUNIT_CASE(seq_buf_declare_test),
+ KUNIT_CASE(seq_buf_clear_test),
+ KUNIT_CASE(seq_buf_puts_test),
+ KUNIT_CASE(seq_buf_puts_overflow_test),
+ KUNIT_CASE(seq_buf_putc_test),
+ KUNIT_CASE(seq_buf_printf_test),
+ KUNIT_CASE(seq_buf_printf_overflow_test),
+ KUNIT_CASE(seq_buf_get_buf_commit_test),
+ {}
+};
+
+static struct kunit_suite seq_buf_test_suite = {
+ .name = "seq_buf",
+ .test_cases = seq_buf_test_cases,
+};
+
+kunit_test_suite(seq_buf_test_suite);
+
+MODULE_DESCRIPTION("Runtime test cases for seq_buf string API");
+MODULE_LICENSE("GPL");