From patchwork Fri Aug 22 14:21:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 107 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872544; bh=dKYxFR0jNfMvYZoCiMNpTL+0GyqtDH4/WlpSgdFj6l4=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iM9IutAjvnmKoELH1wZirR7JGE3QFsQx4cwEZQNa/f5VarwprXLM055ZG77ItUSKQ 6GHEXRbLmV8A7OxfASHNBvHutAx5NX3Z7lwDqeFCn7yuLFlIbDBdTh/1GfgsUOt7Tn iyjNEeWY0XJ7BRHQOjyfiKP8B5Jy4L4MN7x8el9Uq0Vf+Fa2DwAGyXciphzHDAV27P Ql2+DGew4z9hvpPRICTYlh3nvgvXi4VqzOR6NF2eBwgBJ+f1hrbSSL3LNdMgsYf6Wn hxXkpt10JTap2a9IHrrTKPMTRTsOR2GHXJLgRI3fxIlV/WggaH302kqPsHC0WfZATp AXHCse8o6LTFA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 12AEE67702 for ; Fri, 22 Aug 2025 08:22:24 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id bpXGmRSnkdtS for ; Fri, 22 Aug 2025 08:22:24 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872544; bh=dKYxFR0jNfMvYZoCiMNpTL+0GyqtDH4/WlpSgdFj6l4=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iM9IutAjvnmKoELH1wZirR7JGE3QFsQx4cwEZQNa/f5VarwprXLM055ZG77ItUSKQ 6GHEXRbLmV8A7OxfASHNBvHutAx5NX3Z7lwDqeFCn7yuLFlIbDBdTh/1GfgsUOt7Tn iyjNEeWY0XJ7BRHQOjyfiKP8B5Jy4L4MN7x8el9Uq0Vf+Fa2DwAGyXciphzHDAV27P Ql2+DGew4z9hvpPRICTYlh3nvgvXi4VqzOR6NF2eBwgBJ+f1hrbSSL3LNdMgsYf6Wn hxXkpt10JTap2a9IHrrTKPMTRTsOR2GHXJLgRI3fxIlV/WggaH302kqPsHC0WfZATp AXHCse8o6LTFA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 02E26676F0 for ; Fri, 22 Aug 2025 08:22:24 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872542; bh=wSrhWyBgyD479z/oregXBZ1+LEknY6Uw3mKbfbvvxyg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RL2KSLQQooHTgBKgmyhVQ1MLU0PYSwILPZ6Hxf2+2Q0k/6yvMrb2uRz+l7WiMIw3n mxlnSdqLfZOmS06UC+s48FApqxPykDXB8Tpmg24uR8jip7zydV/m6cTOcYU1P3i762 nLepSQobnXhU25WEg8YUufRftf52NGJMWIEWU1KahhZc4BcC45W+ZPVqp2VRDgqKOa eU9aU4vnQYQrDnzClgcoeiM28nffJub0Skch8gvEEpTqZPsxRKPtEL2vE94Jy5q5n3 mP7Tf3ytohK8cePPLcUj3PgVmdamiFf+fo8EgojjPeyULsTa2HMapBpqQCtCONQ6gg E6WnF8EucDcfw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 54071676DB; Fri, 22 Aug 2025 08:22:22 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id FRCl3NKRSB9x; Fri, 22 Aug 2025 08:22:22 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1755872541; bh=QVawyu9m+Unj/HmSTUcOYAuVR6MAIluZC2NMOhoF8n4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nsi4dKPxOYt9qdp4l/xM9I2bOrSMmiSqluvBWC9vSebA6RfPUBgNKrvS5NTUnDGeW m7e42sJ0OGMS7yHDe4130DG5+7M3SQBREKp23JLQFapAUnSQ1GPhLqCKBd1tXWjtn2 BZyScMpaoudFN4Q2lbDntvEe+/sdEtfaqfDfMGb/eW66JyWN0T8Zf2NXhZxaqvh6u+ vKLXfGxWizdPQEZtgUcQs7wCAyaZ0d6IXNk6rXPIC4soEgsREhKviW6RgGjOXOaEQh 4BflEkm0Wju/8/gYJYsQE2ayr7Xp3eRgKsdElyirbsSj5Mv0h0GrVJgyUmwfHQOvKM gZ/JInjHoxACw== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 9C8A7676C4; Fri, 22 Aug 2025 08:22:21 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Fri, 22 Aug 2025 08:21:33 -0600 Message-ID: <20250822142153.3404275-3-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250822142153.3404275-1-sjg@u-boot.org> References: <20250822142153.3404275-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: I6XCG2IJQPO3L3ECBPWYSM22SWPBPYB6 X-Message-ID-Hash: I6XCG2IJQPO3L3ECBPWYSM22SWPBPYB6 X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 02/16] console: Add tests for the basic functionality List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Cover the various cases in the base code. Put the tests in the 'common' suite to match where the pager implementation is. Co-developed-by: Claude Signed-off-by: Simon Glass --- test/common/Makefile | 1 + test/common/pager.c | 324 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 test/common/pager.c diff --git a/test/common/Makefile b/test/common/Makefile index baefc7b3622..ea1317c41dc 100644 --- a/test/common/Makefile +++ b/test/common/Makefile @@ -10,4 +10,5 @@ endif obj-$(CONFIG_CYCLIC) += cyclic.o obj-$(CONFIG_EVENT_DYNAMIC) += event.o obj-y += cread.o +obj-$(CONFIG_CONSOLE_PAGER) += pager.o obj-$(CONFIG_$(PHASE_)CMDLINE) += print.o diff --git a/test/common/pager.c b/test/common/pager.c new file mode 100644 index 00000000000..37796494f79 --- /dev/null +++ b/test/common/pager.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2025 Simon Glass + * + * Test for pager functionality + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Test basic pager init and cleanup */ +static int pager_test_basic_init(struct unit_test_state *uts) +{ + struct pager *pag; + + /* Test successful init */ + ut_assertok(pager_init(&pag, 20, 1024)); + ut_assertnonnull(pag); + ut_asserteq(20, pag->page_len); + ut_asserteq(0, pag->line_count); + ut_assertnull(pag->overflow); + ut_assertnull(pag->nulch); + + /* Clean up */ + pager_uninit(pag); + + /* Test init with different parameters */ + ut_assertok(pager_init(&pag, 10, 2048)); + ut_assertnonnull(pag); + ut_asserteq(10, pag->page_len); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_basic_init, 0); + +/* Test pager with simple text */ +static int pager_test_simple_text(struct unit_test_state *uts) +{ + struct pager *pag; + const char *text = "Hello, World!"; + const char *result; + + ut_assertok(pager_init(&pag, 20, 1024)); + + /* Post some text and get it back */ + result = pager_post(pag, text); + ut_assertnonnull(result); + ut_asserteq_str(text, result); + + /* Should be no more text */ + result = pager_next(pag, 0); + ut_assertnull(result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_simple_text, 0); + +/* Test pager with multiple lines */ +static int pager_test_multiline(struct unit_test_state *uts) +{ + struct pager *pag; + const char *text1 = "Line 1\n"; + const char *text2 = "Line 2\n"; + const char *text3 = "Line 3\n"; + const char *result; + + ut_assertok(pager_init(&pag, 20, 1024)); + + /* Post multiple pieces of text */ + result = pager_post(pag, text1); + ut_assertnonnull(result); + ut_asserteq_str(text1, result); + + /* Should be no more text after first post */ + result = pager_next(pag, 0); + ut_assertnull(result); + + result = pager_post(pag, text2); + ut_assertnonnull(result); + ut_asserteq_str(text2, result); + + /* Should be no more text after second post */ + result = pager_next(pag, 0); + ut_assertnull(result); + + result = pager_post(pag, text3); + ut_assertnonnull(result); + ut_asserteq_str(text3, result); + + /* Should be no more text after third post */ + result = pager_next(pag, 0); + ut_assertnull(result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_multiline, 0); + +/* Test pager with large text that fills the buffer */ +static int pager_test_large_text(struct unit_test_state *uts) +{ + struct pager *pag; + const char *result; + + ut_assertok(pager_init(&pag, 20, 16)); /* Small buffer */ + + /* Post large text - should fit in buffer */ + result = pager_post(pag, "this is 16 chars"); + ut_assertnonnull(result); + ut_asserteq_str("this is 16 chars", result); + ut_assertnull(pager_next(pag, 0)); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_large_text, 0); + +/* Test pager overflow handling */ +static int pager_test_overflow(struct unit_test_state *uts) +{ + struct pager *pag; + const char *result; + + ut_assertok(pager_init(&pag, 20, 4)); /* Small buffer */ + + /* send some text which is too long for the buffer */ + result = pager_post(pag, "test1"); + ut_assertnonnull(result); + + /* overflow handling should return the text */ + ut_asserteq_str("test1", result); + ut_assertnull(pager_next(pag, 0)); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_overflow, 0); + +/* Test pager with NULL input */ +static int pager_test_null_input(struct unit_test_state *uts) +{ + const char *result; + + /* Test pager_post with NULL pager */ + result = pager_post(NULL, "test"); + ut_asserteq_str("test", result); + + return 0; +} +COMMON_TEST(pager_test_null_input, 0); + +/* Test pager with empty strings */ +static int pager_test_empty_strings(struct unit_test_state *uts) +{ + struct pager *pag; + const char *result; + + ut_assertok(pager_init(&pag, 20, 1024)); + + /* Post empty string */ + result = pager_post(pag, ""); + ut_assertnull(result); + + /* Should be no more text */ + result = pager_next(pag, 0); + ut_assertnull(result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_empty_strings, 0); + +/* Test pager buffer management */ +static int pager_test_buffer_management(struct unit_test_state *uts) +{ + struct pager *pag; + const char *text = "Test buffer management"; + const char *result; + + ut_assertok(pager_init(&pag, 20, 1024)); + + /* Verify buffer is properly inited */ + ut_assertnonnull(pag->buf.data); + ut_asserteq(1024, pag->buf.size); + + /* Post text and verify buffer state */ + result = pager_post(pag, text); + ut_assertnonnull(result); + + /* Verify the buffer contains our text */ + ut_asserteq_str(text, result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_buffer_management, 0); + +/* Test pager with very long single line */ +static int pager_test_long_single_line(struct unit_test_state *uts) +{ + struct pager *pag; + char long_line[1000]; + const char *result; + int i; + + ut_assertok(pager_init(&pag, 20, 1024)); + + /* Create a very long line without newlines */ + for (i = 0; i < sizeof(long_line) - 1; i++) + long_line[i] = 'X'; + long_line[sizeof(long_line) - 1] = '\0'; + + /* Post the long line */ + result = pager_post(pag, long_line); + ut_assertnonnull(result); + + /* Should get our text back */ + ut_asserteq_str(long_line, result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_long_single_line, 0); + +/* Test pager line counting and page breaks */ +static int pager_test_line_counting(struct unit_test_state *uts) +{ + struct pager *pag; + const char *multiline_text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n"; + const char *result; + + /* Init with page length of 4 lines */ + ut_assertok(pager_init(&pag, 4, 1024)); + + /* Post multiline text */ + result = pager_post(pag, multiline_text); + ut_assertnonnull(result); + + /* Should get first 3 lines (excluding the 3rd newline) */ + ut_asserteq_str("Line 1\nLine 2\nLine 3", result); + /* line_count is reset to 0 when page limit is reached */ + ut_asserteq(0, pag->line_count); + + /* Next call should return pager prompt */ + result = pager_next(pag, 0); + ut_assertnonnull(result); + ut_asserteq_str("\n: Press SPACE to continue", result); + + /* Press space to continue */ + result = pager_next(pag, ' '); + ut_assertnonnull(result); + ut_asserteq_str("\r \r", result); + + /* Get remaining lines */ + result = pager_next(pag, 0); + ut_assertnonnull(result); + ut_asserteq_str("Line 4\nLine 5\n", result); + + /* Should be no more text */ + result = pager_next(pag, 0); + ut_assertnull(result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_line_counting, 0); + +/* Test that PAGER_WAITING is returned when pager waits for user input */ +static int pager_test_pager_waiting(struct unit_test_state *uts) +{ + struct pager *pag; + const char *result; + + /* Create pager with small page size to trigger waiting quickly */ + ut_assertok(pager_init(&pag, 3, 1024)); + + /* Post text that fills exactly the page limit */ + result = pager_post(pag, "Line 1\nLine 2\n"); + ut_assertnonnull(result); + ut_asserteq_str("Line 1\nLine 2", result); + + /* Next call should return the prompt */ + result = pager_next(pag, 0); + ut_assertnonnull(result); + ut_asserteq_str("\n: Press SPACE to continue", result); + + /* Next call without space key should return PAGER_WAITING */ + result = pager_next(pag, 0); + ut_asserteq_ptr(PAGER_WAITING, result); + + /* Another call without space should still return PAGER_WAITING */ + result = pager_next(pag, 'x'); /* Wrong key */ + ut_asserteq_ptr(PAGER_WAITING, result); + + /* Pressing space should clear the prompt */ + result = pager_next(pag, ' '); + ut_assertnonnull(result); + ut_asserteq_str("\r \r", result); + + /* Now should return NULL (no more content) */ + result = pager_next(pag, 0); + ut_assertnull(result); + + pager_uninit(pag); + + return 0; +} +COMMON_TEST(pager_test_pager_waiting, 0);