All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <kees@kernel.org>
To: David Gow <davidgow@google.com>
Cc: Kees Cook <kees@kernel.org>, Rae Moar <rmoar@google.com>,
	Tamir Duberstein <tamird@gmail.com>,
	Eric Biggers <ebiggers@kernel.org>,
	"Steven Rostedt (Google)" <rostedt@goodmis.org>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Petr Mladek <pmladek@suse.com>,
	"Matthew Wilcox (Oracle)" <willy@infradead.org>,
	Luis Chamberlain <mcgrof@kernel.org>,
	"Paul E. McKenney" <paulmck@kernel.org>,
	linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: [PATCH] seq_buf: Introduce KUnit tests
Date: Thu, 17 Jul 2025 01:52:12 -0700	[thread overview]
Message-ID: <20250717085156.work.363-kees@kernel.org> (raw)

Add KUnit tests for the seq_buf API to ensure its correctness and
prevent future regressions.

The tests cover the following functions:
- seq_buf_init()
- DECLARE_SEQ_BUF()
- seq_buf_clear()
- seq_buf_puts()
- seq_buf_putc()
- seq_buf_printf()
- seq_buf_get_buf()
- seq_buf_commit()

$ tools/testing/kunit/kunit.py run seq_buf
=================== seq_buf (9 subtests) ===================
[PASSED] seq_buf_init_test
[PASSED] seq_buf_declare_test
[PASSED] seq_buf_clear_test
[PASSED] seq_buf_puts_test
[PASSED] seq_buf_puts_overflow_test
[PASSED] seq_buf_putc_test
[PASSED] seq_buf_printf_test
[PASSED] seq_buf_printf_overflow_test
[PASSED] seq_buf_get_buf_commit_test
===================== [PASSED] seq_buf =====================

Signed-off-by: Kees Cook <kees@kernel.org>
---
I used an LLM to produce this; it did pretty well, but I had to help it
get the Kconfig and make targets in the right places, and I tweaked some
of the edge cases and added a bit more (perhaps redundant) state checking.

Cc: David Gow <davidgow@google.com>
Cc: Rae Moar <rmoar@google.com>
Cc: Tamir Duberstein <tamird@gmail.com>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Petr Mladek <pmladek@suse.com>
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
---
 lib/Kconfig.debug         |   9 ++
 lib/tests/Makefile        |   1 +
 lib/tests/seq_buf_kunit.c | 205 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 215 insertions(+)
 create mode 100644 lib/tests/seq_buf_kunit.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index cf05bf1df983..048efc3183d5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2470,6 +2470,15 @@ config SCANF_KUNIT_TEST
 
 	  If unsure, say N.
 
+config SEQ_BUF_KUNIT_TEST
+	tristate "KUnit test for seq_buf" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	default KUNIT_ALL_TESTS
+	help
+	  This builds unit tests for the seq_buf library.
+
+	  If unsure, say N.
+
 config STRING_KUNIT_TEST
 	tristate "KUnit test string functions at runtime" if !KUNIT_ALL_TESTS
 	depends on KUNIT
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index 84b15c986b8c..fa6d728a8b5b 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -36,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/seq_buf_kunit.c b/lib/tests/seq_buf_kunit.c
new file mode 100644
index 000000000000..74648dbda13f
--- /dev/null
+++ b/lib/tests/seq_buf_kunit.c
@@ -0,0 +1,205 @@
+// 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);
-- 
2.34.1


             reply	other threads:[~2025-07-17  8:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-17  8:52 Kees Cook [this message]
2025-07-17 12:30 ` [PATCH] seq_buf: Introduce KUnit tests Steven Rostedt
2025-07-26  9:08 ` David Gow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250717085156.work.363-kees@kernel.org \
    --to=kees@kernel.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=davidgow@google.com \
    --cc=ebiggers@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=paulmck@kernel.org \
    --cc=pmladek@suse.com \
    --cc=rmoar@google.com \
    --cc=rostedt@goodmis.org \
    --cc=tamird@gmail.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.