From patchwork Sun Dec 14 17:54:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 894 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=1765734909; bh=JHER0NnrbNvfUMzu650j37g59II95vUTulfVF5oMSxs=; 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=tpCiVxh90J7nbG1WmbfhTS4if62TfsslM0VQGWQeO0w1CWOvQvV0UzeKyfOITL/1T eyTUX4XZsIRMy/wmX1YhuAJek+ZxaNk8zl6i3Ew9zmBaUNOqmwWCbiA7OpIG1ZoMnk DTAylwC8kR0VMuNyrjlCPN6p2dJdz+riPUuLXadefFWrV4G7acHaPAS93EiPiTxRY1 3aPwrIi5LhXOs1KKGwpR2SWqj2L/KvMjCdbq2FbN8zWHY3lWRu+zqAlooDkSJCVEnb NmxzlL0FgCW61Ie3NCE0Ri/nlBwt8XSB+2omIrbvzTD/c7hCl+/BQURGKA3lcOkfZh UZbsLGl2X3rLA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A7A8B68AEA for ; Sun, 14 Dec 2025 10:55:09 -0700 (MST) 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 U1tvTGyl4BXl for ; Sun, 14 Dec 2025 10:55:09 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734909; bh=JHER0NnrbNvfUMzu650j37g59II95vUTulfVF5oMSxs=; 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=tpCiVxh90J7nbG1WmbfhTS4if62TfsslM0VQGWQeO0w1CWOvQvV0UzeKyfOITL/1T eyTUX4XZsIRMy/wmX1YhuAJek+ZxaNk8zl6i3Ew9zmBaUNOqmwWCbiA7OpIG1ZoMnk DTAylwC8kR0VMuNyrjlCPN6p2dJdz+riPUuLXadefFWrV4G7acHaPAS93EiPiTxRY1 3aPwrIi5LhXOs1KKGwpR2SWqj2L/KvMjCdbq2FbN8zWHY3lWRu+zqAlooDkSJCVEnb NmxzlL0FgCW61Ie3NCE0Ri/nlBwt8XSB+2omIrbvzTD/c7hCl+/BQURGKA3lcOkfZh UZbsLGl2X3rLA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 9747568AC0 for ; Sun, 14 Dec 2025 10:55:09 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734906; bh=xnUL3XmrYBHhjTrZrKAp4kifK/5xbc5MdejNQEQNJpI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NfUnanYsYRa+eWRvoMOo48keLYOF3VZNZEisR/RyETceL5Oq5Oc6l5FyrvzXjMNQ8 nUyu0IjwXzLplOCTbkwtNfHFPcYZKqFTEnifLJtPCoNGdo9ChyV+radb9bdAHmd/+J wtqDsA4UHH9m1QT1yTg3aCx1Fare5tUMBPPvDTgyP+n5PrgU+LanG2zcoQ5YEN8ku9 RvDGpi7DV7ciS1nuWUycrPOaxl7EtXgWuMmK204b/zDEyhES4kslhmpNlXL/RRaQmd 7GXltM1UHrrxF0NR2CtHcL/LovglaCNynHKtCUJdnjjcFpFsI6QbYntdzuwygFlnaZ TUfZAAZloiHIw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A225F68A84; Sun, 14 Dec 2025 10:55:06 -0700 (MST) 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 VeV_i-HP6ozY; Sun, 14 Dec 2025 10:55:06 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734902; bh=HUOnye6VtdONX+gH+1zeMgyunYaOxmTYvz2/jl/H9Hc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LUaF7Td+xu/AuEZVKWMKKkmoC+f5hXKcDQhGAzoiwhGzUHKZS7L/WWzUCzbGIb4DJ 5nux9THyK27Kff6eG62wNbhA1zSI6mNL0uSjh24aLFxA6P9ZN4b/6IBH4n9aQpCC6R eJCxE5EOq77PpqOMGpsItbTGipRFFBP777j21Td5wmDTx3IA+dFQL2wd3jfN3Ra0en igDmaWzMDk56u0QAVznqCwGZvhAjTI0Rw7Mbsw0sVKumHtOJd+aW/kkRz/isS074dg h5MNtZq5uYVAfDb93pGZSaYzcV4jENbbyiXopMRia503L/n9cFXKb6dhfUPRd3fAAZ kuSNXyG+IjFPQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 24A9468A91; Sun, 14 Dec 2025 10:55:02 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:23 -0700 Message-ID: <20251214175449.3799539-2-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 2Y5YHAYGLANYFOREK2RHZDMAXGCIQ2PD X-Message-ID-Hash: 2Y5YHAYGLANYFOREK2RHZDMAXGCIQ2PD 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: Heinrich Schuchardt , Heinrich Schuchardt , Simon Glass , Leo Yu-Chi Liang , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 01/21] configs: raise SPL_SYS_MALLOC_SIZE to 8 MiB on RISC-V 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: Heinrich Schuchardt On several RISC-V boards we have seen that 1 MiB is a insufficient value for CONFIG_SPL_SYS_MALLOC_SIZE. For instance qemu-riscv32_spl_defconfig fails booting because u-boot.itb exceeds 1 MiB. 8 MiB is a reasonable value that allows adding FPGA blobs or splash images to main U-boot. Reported-by: Simon Glass Signed-off-by: Heinrich Schuchardt Reviewed-by: Leo Yu-Chi Liang (cherry picked from commit 8b410cab51266a0f6ee9c20e7f2bac9cfec079e8) Dropped modifications to all files except common/spl/Kconfig: Signed-off-by: Simon Glass --- common/spl/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index da0a358b2a3..c40dc5a1fe9 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -481,6 +481,7 @@ config SPL_CUSTOM_SYS_MALLOC_ADDR config SPL_SYS_MALLOC_SIZE hex "Size of the SPL malloc pool" depends on SPL_SYS_MALLOC + default 0x800000 if RISCV default 0x100000 config SPL_READ_ONLY From patchwork Sun Dec 14 17:54:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 895 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=1765734913; bh=OmfPav9vrXOD3HDZLwjZF2oa6sF2tIOwyLyOVh+4uvY=; 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=LnKv0Hi+/cQAdUE9esWCi+mZyB+qzBHld3j5fJZdyZTWqGbqYPA5EreSxrGdi4Qlx N0YSQpUVUaJ2zSfk7+aKnWM0wvQlGlqLBjD1p0atA2lZ28EXmKTXeCEr3Yo/xq3v+V skQyaDmrVUos8M5X2WMxUWSMzSBn9stNc4HoQSzoIsrpU/MWSZ7dj/EIubdNd7qcXx NsgSdca70HvRvKG4eMj3rRivy4t1qbxkdil8fLg+QkFE0QzE7sbBlIdHE05SY5DxdW KZEfzPu6MZjsaSYjbBHfJoyE2hNRlrJZX/U1hLi2zGEnAKtQehwJwrorNDNZBNrlgi migmm5glIB92Q== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 294CF68B08 for ; Sun, 14 Dec 2025 10:55:13 -0700 (MST) 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 FZ_s4IzSpDtj for ; Sun, 14 Dec 2025 10:55:13 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734913; bh=OmfPav9vrXOD3HDZLwjZF2oa6sF2tIOwyLyOVh+4uvY=; 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=LnKv0Hi+/cQAdUE9esWCi+mZyB+qzBHld3j5fJZdyZTWqGbqYPA5EreSxrGdi4Qlx N0YSQpUVUaJ2zSfk7+aKnWM0wvQlGlqLBjD1p0atA2lZ28EXmKTXeCEr3Yo/xq3v+V skQyaDmrVUos8M5X2WMxUWSMzSBn9stNc4HoQSzoIsrpU/MWSZ7dj/EIubdNd7qcXx NsgSdca70HvRvKG4eMj3rRivy4t1qbxkdil8fLg+QkFE0QzE7sbBlIdHE05SY5DxdW KZEfzPu6MZjsaSYjbBHfJoyE2hNRlrJZX/U1hLi2zGEnAKtQehwJwrorNDNZBNrlgi migmm5glIB92Q== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1910F68AEA for ; Sun, 14 Dec 2025 10:55:13 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734912; bh=/PIWNU5WRgDgGaM64Ppwjniu92DFEuRJzc/+n25wekY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A9ggy7d69/OVopCGPXSTkj0152ppmrntwoZxx2CqzKwBLHDuTOAcgruE0hFzv2Lyh E/wFg2iZRarvHTLGgRTA/kA6D0tL48CfFmIqTUM8D1hrMJPKFK9GHHpqj3joNezk9Z bT91jEwgOLjschiZsavEbnwX4PSiZxFqwXYlBQPnhtboax9xUjhHXu037S8PBZvRIN gn0obVIMj5DeaYWT5VIW073cCAleyzk9MI5H+45eMFXm7tb7n9oUtfop/STvsckIDO xJSaLY3QRTKWsKZilk8Ko8P+OFGDW/4pnoVztf+IuNFLd3dEmfie5QTX4pmZiu+ZdO pI8qcQ3mrEDFg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0C01E68AC0; Sun, 14 Dec 2025 10:55:12 -0700 (MST) 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 wHzbZ3j0evQR; Sun, 14 Dec 2025 10:55:11 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734907; bh=syP0b505fupAW33r1DzlYu/7xh2X2JcKp+cC1wbfbVk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DF/3xjZHq+9PatWZx0BqAHwR3ow32REMtqfyPcsSIiWzY0Co0pZotzesTGcG/tmIu s8nfR7kh8a/uY0AmjaxMVFOCzmeboSRx9SZI6vmnkltyMda5M0ystjBtO3Hl+Erd0w 6imTHBdFjjSrD0HRUaM8nePiMHsOt47sh+6jCpmiNmNv/i9UrjJ/8lPxclSQg1/mIK mlnuiaTrgOp9DIQHs3EYLoKRY0xdMRui6aatuW0YQUPOu4zQcRJJ9cswmqSEN42gZr K1Gv92tXmq+TROhx6xx93PVaJx2H70508K6AQYjiOwdWOo/abbBNLYBg9j1NAOzli0 MnT1VeTIJDOEA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id E3EBE68A91; Sun, 14 Dec 2025 10:55:06 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:24 -0700 Message-ID: <20251214175449.3799539-3-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: MGMP57TXKVCCJCBH4ZS2YMSSHSMRLYUT X-Message-ID-Hash: MGMP57TXKVCCJCBH4ZS2YMSSHSMRLYUT 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: Heinrich Schuchardt , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 02/21] serial: Retry output if it fails 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 If something goes wrong when writing to the serial device, take notice of the error code and try again, if needed. Signed-off-by: Simon Glass --- drivers/serial/serial-uclass.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 8644d210770..8d330d687a3 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -271,6 +271,8 @@ static int __serial_puts(struct udevice *dev, const char *str, size_t len) do { ssize_t written = ops->puts(dev, str, len); + if (written == -EAGAIN) + continue; if (written < 0) return written; str += written; From patchwork Sun Dec 14 17:54:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 896 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=1765734915; bh=aBdtptYUIzjwj2aPO448rcBfBLsnIdPmsgYfA8ZwXAE=; 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=eTxWFvyECMdqiuRGFhi5WeDR1WA/yweQokzhmbzluZQrPCHoiS5rQNC6kjWx46F5j oX5vIxIAhzma2z21eMRx9lisBVjwwjVWDSi9VnDwdxTjd8KnmIpG40B0wEGIIcd3Js CRefZyAfjP4rRr2ZmTjDrM/6ERDk2e5vQZyMIueIoI2vuu3D/6LrhMmNwBepDBhy5q o74uVVfMYgVh24xXgbk5YR7a1ajcV4+qShLCbOFJgxv78TZvJ88gUFtpGLwbfy9Wvu zkMpSut7ydlHZy4ADqeXZTpsdR+H8tk8yewoqxFtZo/rR0teVz8NIPCrCu9vXull+y 6QVy/WDkY0m7Q== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8334C68A84 for ; Sun, 14 Dec 2025 10:55:15 -0700 (MST) 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 fqXs88TOmXCQ for ; Sun, 14 Dec 2025 10:55:15 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734913; bh=aBdtptYUIzjwj2aPO448rcBfBLsnIdPmsgYfA8ZwXAE=; 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=Ux0TQosG99t4P+jA1gwRubcgbtJESydaXXaIT2M11mqDVvlhfQUgByjEd+X1XeAzC oBPUOaCpD6c8USPcWIUSmRXucPVx+gN1UlzBefx5NiQwwZkRmP8S52jyUhg2C2ijqE xJXSQ5+AKKSPHtIuU7CI3LXbjdWi0rl/aNvENe2axhvRaJ9KKyCrIkrN438ixE00tW hNwhi3CQrJPaL73t/yMZ04OkcRqiIiveR7zXns01Cl2LpXhEYRBwF/R5fLFzK0q8Ib TI74V5xoG7lsu2hhYwmFwTBbuVnPrv1BVV/s7tCx4/BkdOfjC/1w3t1L/YtJ9diHqe qLz1UH8es1r1A== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E24E068A89 for ; Sun, 14 Dec 2025 10:55:13 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734912; bh=XmCvCxCy+VXBfsmKDCA0oYsr7riercLUpSX4cGc2hrU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qhiBock7BJeeWD/aNBoC+7orVKAhc12ulBfs7m2cTu+iX2BfY5rUDDiRsSdWOyVWM XOZsgAUyUflcolUD48YeH1GdMwq6fo1UjsIO5aAV6cFlWMAzD4YzFoMMDbT+jHw3ht CkkVQZ3nL2qaOvC95VsmyRQGrCBMc3qpmKdYDX2NIk3S3eaH7N13RqJ3sxRCGhTWis EE8+oCnhMe3yypQoEexZE66RdCzKq2hQejgZ6sfWjwIXorXaHLLNhK2kA5VONEUi8L d5lWYjsT4hgi3UcViq9F2uGYz7PvjA7J3AqsGKcaaW5oLOGMAsnZri1NYvHWDmKUx6 cfrPYTKZTZ0DA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 446FE68A89; Sun, 14 Dec 2025 10:55:12 -0700 (MST) 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 RNpMJpOy-9iA; Sun, 14 Dec 2025 10:55:12 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734911; bh=m5wUhDCwFL1bvv8gvnUDB4T3L44+bR97ASLsZP/0+9A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YMadbsC6l77Ddanei60sB4F6BR/CuRTxjXkkNvVo98LrLNRC3BR8clM+5O2baSaqp 9I6pUnXfER2p19QW/txg1f/3cM7wHhA1gV3ml6ktF4TFTOrq8piLulQ0qNTuWoO1Fp 2gLac+BXQLEiTjACIrVO/oMxMTcIwq/6rx62VmFMvZ0I99UjKSwfBsm9aaEswvewHt oWStZfXwTBCQ/X4HSnlvLBPH+dKU4Ncuu/zkydcOQ27XLPVa0OhuOpWV8vtb+q8H2T cOkezevQ61uraG2FtwB005uzK1ytXtiB7lOaU3ZJ0nbWsA5FKdT+YbfJrPPMJjsLGP 4oUvukunlKnsg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 81F0868A96; Sun, 14 Dec 2025 10:55:11 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:25 -0700 Message-ID: <20251214175449.3799539-4-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 27KZRZWDWCDCS2BWYQUL7U62XAHMCZK6 X-Message-ID-Hash: 27KZRZWDWCDCS2BWYQUL7U62XAHMCZK6 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: Heinrich Schuchardt , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 03/21] sandbox: serial: Report output failurs 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 When characters cannot be sent to the serial port, return an error code so that the uclass can try again. This fixes a problem with gnome-terminal which seems to get behind and then drop output when a large amount of output is produced quickly (e.g. 100K in under a second). Since sandbox often writes to the device one character at a time it does place a substantial load on the other end of the PTY. Quite possibly it does not empty the pipe quickly enough and so writing to the PTY fails. Signed-off-by: Simon Glass --- drivers/serial/sandbox.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index cc0491bc3c8..227524ae911 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -94,13 +94,16 @@ static void sandbox_print_color(struct udevice *dev) static int sandbox_serial_putc(struct udevice *dev, const char ch) { struct sandbox_serial_priv *priv = dev_get_priv(dev); + ssize_t ret; if (ch == '\n') priv->start_of_line = true; if (sandbox_serial_enabled) { sandbox_print_color(dev); - os_write(1, &ch, 1); + ret = os_write(1, &ch, 1); + if (ret != 1) + return -EAGAIN; } _sandbox_serial_written += 1; return 0; @@ -120,6 +123,8 @@ static ssize_t sandbox_serial_puts(struct udevice *dev, const char *s, ret = os_write(1, s, len); if (ret < 0) return ret; + if (ret != len) + return -EAGAIN; } else { ret = len; } From patchwork Sun Dec 14 17:54:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 898 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=1765734921; bh=FPnBp/IpqoWKYzORi1WQN/+Gea82aYivjxpMPe/0G6g=; 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=RpGc/8IRrus6CSB194eo0Z5d9Lk9zZhsuVul1fE6juBtKuna6gxBWK37ST0gqhlxY 0KD2B6NoQcCzueUuWkQCnPlbbpEMltCqIrUh2uJSegLXdyZSe1zVbg3zCYxwaCjnQR W5NSCZzOkcd0x7NDKsj1T11viddQ1udU2/RTd3aJNpC/sPOpc7le8Fd/qS3aqBHwIw tWfnXaJ/W25XLfUPUHh+gXat4q8uh+kv4OwsIAh8YV9f8IYu+6VfOFoBJBdNAtsrYH He+LCPNQmmT3vYNiRFJB6gwzUSt5+GT1uS0rd25f7Mmk0F89Q3Foz+I54byNvNxehu C4yAvu6vgOtcw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C2D8568B0D for ; Sun, 14 Dec 2025 10:55:21 -0700 (MST) 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 qMaZLoqyAOx8 for ; Sun, 14 Dec 2025 10:55:21 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734919; bh=FPnBp/IpqoWKYzORi1WQN/+Gea82aYivjxpMPe/0G6g=; 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=Lnv1VfjY+ZixB7Uj/+LieZp7O/maecoUpVZPas7rLvcGhzhDEBrSpn1pITihps7m1 dCP845bu7uFgjL1J2apGNO09LiL8MtY42ePlSCUqg0L3PudceEKFUEOsX3T+x+mPZE h5YMwfHnK75RTWLFfDqfYK/YodCn6deHM7KkAKjJ5NMPJPkdfB5FZ/eq3OYtiHruPx m6br9vaLO3fduwcpyMmcaFZI+Q6l6MQD7vmCivCF0dRteWnUqdgC3K2TnS+GqaUcz0 +qKNTbavvhMmto7R9HJryFUpyhJWyb6akx0gWF/HPXNdVbWlvk5Xzr33uBmqm+2jV8 tabrZ5QJZmEcA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id BD3A668A89 for ; Sun, 14 Dec 2025 10:55:19 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734917; bh=zPT3aAXMWdnAy141YyXIDYVVv+e+Dxc7KKLc+aXnwHs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qjbei5KxMH9wyXcQSOuLNpFiNVnoPT0B5f2M5If3+5AL/pzHvQSA6lgIRDN4NgYzu 3NReqksgRY+I/rgw0Yvv7oPTuKer4NXAAMCClG5yVFfQg4Yb/mivXgMwLs43iuvVg2 bmPcgnwdscrtcCA2CiTMkYJKV2cOK1ujfXL2LBfpvxiuHentLszLBmnDw/oVWKUvce B7EQFSOwJi5+wGbcYLjH65HWSPI0T/ky+0JTEc66xdS5eKbRS36bRov2/YewKV1cQh UxhPcY6bJKxRZiaGZtSZXjnvJwqEzAEC42wisKsrhxgG5I/GORvlg7vAVsymoK+9lF y2R6X7zI2kiTg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CC50868AC0; Sun, 14 Dec 2025 10:55:17 -0700 (MST) 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 7mVuemQNAdob; Sun, 14 Dec 2025 10:55:17 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734912; bh=ba32JAVc0a3QNxPqYWzjXrAqD6PMJiSZmpGiBuKgGL8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JKjRO+lOCSi1rAKRVpa5zSNBhwYh+KAuw1P6ksfhN+POfBb1N4DvXk0DS6VjUk0Di T3dlX61VdHnKBHjrv+PGMA81LJPYfSGCRT8xUamQYWT0HdR5KZjXdPwb8Yf+oe2+rZ i7wnFCuPoESGDNiyA1RtvycyZip/l9+k16YUi3HE7QjPiskVXdLlVOWfq8Dos/tXhi CKJ32kVPuakFGDPByM3BZQV95nahbXKxUSajrA7zecYb/pZNyeLnbkxQENw1SwIXji 38cLu1VQJFx1fSE5GLYnc68AL2R4QPin+36UYgwzVqL7D+snFBuTzttyaLQO9Y6+EO SNpFjyBKQW0iA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 8566568A96; Sun, 14 Dec 2025 10:55:12 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:26 -0700 Message-ID: <20251214175449.3799539-5-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: NBMZRCV2FYWIW5LWKKRQIJUSDANIU5XZ X-Message-ID-Hash: NBMZRCV2FYWIW5LWKKRQIJUSDANIU5XZ 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 04/21] doc: Expand printf documentation 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 Expand the printf format documentation to include information on all printf-style functions. Mention CONFIG depencies as well. Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/printf.rst | 80 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst index 99d05061b14..4a0f054aae1 100644 --- a/doc/develop/printf.rst +++ b/doc/develop/printf.rst @@ -1,7 +1,62 @@ .. SPDX-License-Identifier: GPL-2.0+ -Printf() format codes -===================== +Printf-style Functions +====================== + +U-Boot provides a family of printf-style functions for formatted output. + +Functions +--------- + +printf() + Prints formatted output to the console. + + .. code-block:: c + + int printf(const char *fmt, ...); + +vprintf() + Like printf() but takes a va_list argument. + + .. code-block:: c + + int vprintf(const char *fmt, va_list args); + +sprintf() + Prints formatted output to a string buffer. The buffer must be large + enough to hold the output. + + .. code-block:: c + + int sprintf(char *buf, const char *fmt, ...); + +vsprintf() + Like sprintf() but takes a va_list argument. + + .. code-block:: c + + int vsprintf(char *buf, const char *fmt, va_list args); + +snprintf() + Prints formatted output to a string buffer with a size limit. At most + size-1 characters are written, and the buffer is always null-terminated. + Returns the number of characters that would have been written if the + buffer were large enough. + + .. code-block:: c + + int snprintf(char *buf, size_t size, const char *fmt, ...); + +vsnprintf() + Like snprintf() but takes a va_list argument. + + .. code-block:: c + + int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); + + +Format Specification +-------------------- Each conversion specification consists of: @@ -166,10 +221,15 @@ Pointers * resource_size_t %pD - prints a UEFI device path + prints a UEFI device path (requires CONFIG_EFI_DEVICE_PATH_TO_TEXT) %pi4, %pI4 - prints IPv4 address, e.g. '192.168.0.1' + prints IPv4 address, e.g. '192.168.0.1'. Lower case (%pi4) omits the + dot separators. + +%pi6, %pI6 + prints IPv6 address (requires CONFIG_IPV6). Lower case (%pi6) omits the + colon separators. %pm prints MAC address without separators, e.g. '001122334455' @@ -178,22 +238,22 @@ Pointers print MAC address colon separated, e.g. '00:01:02:03:04:05' %pUb - prints GUID big endian, lower case + prints GUID big endian, lower case (requires CONFIG_LIB_UUID) e.g. '00112233-4455-6677-8899-aabbccddeeff' %pUB - prints GUID big endian, upper case + prints GUID big endian, upper case (requires CONFIG_LIB_UUID) e.g. '00112233-4455-6677-8899-AABBCCDDEEFF' %pUl - prints GUID little endian, lower case + prints GUID little endian, lower case (requires CONFIG_LIB_UUID) e.g. '33221100-5544-7766-8899-aabbccddeeff' %pUL - prints GUID little endian, upper case + prints GUID little endian, upper case (requires CONFIG_LIB_UUID) e.g. '33221100-5544-7766-8899-AABBCCDDEEFF' %pUs prints text description of a GUID or if such is not known little endian, - lower case, e.g. 'system' for a GUID identifying an EFI system - partition. + lower case (requires CONFIG_LIB_UUID), e.g. 'system' for a GUID + identifying an EFI system partition. From patchwork Sun Dec 14 17:54:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 897 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=1765734919; bh=h8shfPXVX8F8o44+5UDfh14P60snpzf1T0IycwTkkYM=; 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=cOP6WLX9pRH7cHoxyKBSY6FjtJsM1KX2G8eVyzSfmtWnqsAg3CFUr9fU4mmOhJPlE a2p8eboATyoRJYla+6g+d6118icdyi09hAXHrOBIjITGBsJ5x44d4nLTxpW6bylNMf 79L6ptav2iVn8y099610LTwdFYlOfvEiO037BNsfapYKCj8bPXID6cCFO/orr4cXpA IYXAtIWNsmrskMMZvFou9UbVCQEO29A0QFizR5cFRHze2yAF9yOF1EpD5xjjXtevG1 7M9wEjzizu0VaQ2L/2uinPjwSH2bD9sTP+2KW7llTZ4WBNRKrfwXwG2KRNNgLM9m0b dDRIvPLodVXEw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 6188B68AFE for ; Sun, 14 Dec 2025 10:55:19 -0700 (MST) 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 pxGjw1_ayJ5B for ; Sun, 14 Dec 2025 10:55:19 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734919; bh=h8shfPXVX8F8o44+5UDfh14P60snpzf1T0IycwTkkYM=; 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=cOP6WLX9pRH7cHoxyKBSY6FjtJsM1KX2G8eVyzSfmtWnqsAg3CFUr9fU4mmOhJPlE a2p8eboATyoRJYla+6g+d6118icdyi09hAXHrOBIjITGBsJ5x44d4nLTxpW6bylNMf 79L6ptav2iVn8y099610LTwdFYlOfvEiO037BNsfapYKCj8bPXID6cCFO/orr4cXpA IYXAtIWNsmrskMMZvFou9UbVCQEO29A0QFizR5cFRHze2yAF9yOF1EpD5xjjXtevG1 7M9wEjzizu0VaQ2L/2uinPjwSH2bD9sTP+2KW7llTZ4WBNRKrfwXwG2KRNNgLM9m0b dDRIvPLodVXEw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 51F3168ADC for ; Sun, 14 Dec 2025 10:55:19 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734917; bh=joffOa2OGMb70ktQo4WFLUv99hrzK8ig4+ZrIKMTV+g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E8AgLF+ZaDD5vilRyVkETjeXEjlV+JJfZUJ4WEtuiIBkvpzFBEeqdgk1+aARCrp+R V/6H7EDO0guWkrW7CC9TXk/JncCiwYmiVbUReeNut5OO5TpB+VOPsl7Ra/ktFBEVRH e1ZiW1hHmWEqs4zug7zRizjodBUl0Z7cMwNJVjcKarocdUE3N8gS9CqoLJDay/EfE9 As8QomhX4cbFCpyq7O14cwsZZC8ZGSeeZJNBlSmyAUDvQAxAgm2bxiik1bq10zm/hH HLV8ydVwvvKWUCnszvOjDZL8V2ffUqw2uVmVkR9oG7Aq6qeUZicNuhXBQBKF1FMyAE 2q1iysdbsLCsw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CC48568A89; Sun, 14 Dec 2025 10:55:17 -0700 (MST) 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 A-CzS0oASiWW; Sun, 14 Dec 2025 10:55:17 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734917; bh=76DRXad1qdHoJAZdxIPtta/+eLA2frV4L9SyQUktAaY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jOE+kwqDWOnusIw4hHNGG/TXMpoSuP6nQ//h+cgJ4Mz2M9R9HPb8e0cVE/DAo1GLx 8RphGTo04CUbdAEARmoFyTBSoDSRz7sxiqJwebw9CAMNU7+N12zkuWj5g0jN5QhNiM QQf0qS/+9EcCP6ruPqw343L6jZkn1jCW89Qz9/u29Wyxpww40q24Obv0arufe3FeVq LHl2CqEiqRNmRtbcFPoKummaxgOBXrIkURAAGkvTT6HzU9yshmzV6uxTwVw33jQFpp muXWBHiSJ7ms7lb1s+NZYhoOFpD/L7C3oZzw0eWD98mzh5/xO3flcDCmvuq03V2LCx DAyxHzJpcKBjA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 314C368A84; Sun, 14 Dec 2025 10:55:17 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:27 -0700 Message-ID: <20251214175449.3799539-6-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: SG74WHXSFTCQIRRS43IGWKPJNO5LIKDY X-Message-ID-Hash: SG74WHXSFTCQIRRS43IGWKPJNO5LIKDY 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 05/21] doc: Document tiny printf for SPL 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 Add documentation for the tiny printf implementation used in SPL, TPL, and VPL when CONFIG_SPL_USE_TINY_PRINTF (or equivalent) is enabled. Document the supported format specifiers, limitations, and the warning about snprintf() not performing bounds checking in this implementation. Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/printf.rst | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst index 4a0f054aae1..edda8b24a8e 100644 --- a/doc/develop/printf.rst +++ b/doc/develop/printf.rst @@ -257,3 +257,78 @@ Pointers prints text description of a GUID or if such is not known little endian, lower case (requires CONFIG_LIB_UUID), e.g. 'system' for a GUID identifying an EFI system partition. + + +Tiny printf +----------- + +For space-constrained environments like SPL, U-Boot provides a minimal printf +implementation enabled by CONFIG_SPL_USE_TINY_PRINTF (and corresponding +CONFIG_TPL_USE_TINY_PRINTF, CONFIG_VPL_USE_TINY_PRINTF for TPL and VPL). This +reduces code size by approximately 2.5KiB on armv7. + +The tiny printf supports only a limited set of format specifiers: + +Basic specifiers +'''''''''''''''' + +%c + prints a single character + +%s + prints a string + +%d, %i + signed decimal integer + +%u + unsigned decimal integer + +%x + unsigned hexadecimal (lowercase) + +%% + a literal '%' character + +Length modifiers +'''''''''''''''' + +%l + long (e.g., %ld, %lu, %lx) + +Width and padding +''''''''''''''''' + +Field width and zero-padding are supported (e.g., %08x, %4d). + +Pointer specifiers (CONFIG_SPL_NET only) +'''''''''''''''''''''''''''''''''''''''' + +When CONFIG_SPL_NET is enabled, the following pointer formats are available: + +%pM + MAC address colon-separated, e.g. '00:11:22:33:44:55' + +%pm + MAC address without separators, e.g. '001122334455' + +%pI4 + IPv4 address, e.g. '192.168.1.1' + +Limitations +''''''''''' + +The tiny printf does NOT support: + +* Floating point (%f, %e, %g, etc.) +* Long long (%ll) +* Size/ptrdiff modifiers (%z, %t) +* Precision (%.Nf, %.Ns) +* Most pointer formats (%pU, %pD, %pV, etc.) +* The snprintf() size parameter is ignored - no bounds checking is performed + +.. warning:: + + Because snprintf() ignores the size parameter in tiny printf, buffer + overflows are possible. Ensure buffers are large enough for the expected + output. From patchwork Sun Dec 14 17:54:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 899 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=1765734925; bh=WoNrmz8R6ISa9VDmkQ3cu7mc+uSQg21z1qYQFpLzZlg=; 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=iMeMAH8kd2KAUeqOf6L71NismrjB96X5eBbcE0uinHY4HsT2/RhS2yaLOR/azUbVy WiKTTSVGez74APmYx/kIhRseUh/QADv29YKzNxg6yczuhpKUaDH3zlV18mzajnWoV4 rAst1XcuC155XNWGkD/lprkNUFXXkYLXAQO9B13ZLxKiDL9gXu4KQ5yDbuyDgpuOCG FRsIFWTnRnG944Mqf3m3wj3mrCnxxS1ipEn+9KcdPQIZbDahV0Vx3GU4J4F6ZUaynf abs1uJR1/Ge2BK5YFBdMnhtPAunUk3NZ3wus7zWPfKH+kOssSZ+fDK05CIaCeO0Ezi D6oJvexvkI15w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CD74968A91 for ; Sun, 14 Dec 2025 10:55:25 -0700 (MST) 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 rxEk1YOEKDiG for ; Sun, 14 Dec 2025 10:55:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734925; bh=WoNrmz8R6ISa9VDmkQ3cu7mc+uSQg21z1qYQFpLzZlg=; 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=iMeMAH8kd2KAUeqOf6L71NismrjB96X5eBbcE0uinHY4HsT2/RhS2yaLOR/azUbVy WiKTTSVGez74APmYx/kIhRseUh/QADv29YKzNxg6yczuhpKUaDH3zlV18mzajnWoV4 rAst1XcuC155XNWGkD/lprkNUFXXkYLXAQO9B13ZLxKiDL9gXu4KQ5yDbuyDgpuOCG FRsIFWTnRnG944Mqf3m3wj3mrCnxxS1ipEn+9KcdPQIZbDahV0Vx3GU4J4F6ZUaynf abs1uJR1/Ge2BK5YFBdMnhtPAunUk3NZ3wus7zWPfKH+kOssSZ+fDK05CIaCeO0Ezi D6oJvexvkI15w== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id BCB7F68A96 for ; Sun, 14 Dec 2025 10:55:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734924; bh=SeHmOoO5JEyZuFDiQsS/AKuKQKd7qLKuAw/uHiDMLN0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E76JYsZTUG5rap61cFJ9JgmTMj04f3AqUFzC5w/6sBDU09zM5IQZXxPBQ832EYsYP r2yphqMhBuc+7LaZ4FFZD30QfGROx9ipXFJAg9gduNHqdoO3zqkWf8L2Ht/Mzyoanj mmgIuljEZaBpQ2YNDWtpuPJSyOtYpd+Sz65P3EZ48gaXP9u2Lzx0OER34L5dDZuKKM ReI4/YE528OfTHyAwKmx3ZeWLZncWMq1dDpcOQBqZbw36eAtXO5/HAq+VJB1Za3RJt OONpN96k4kDEFMqpnrRhqpayyvRzAOvvbnILbwFWpTXHvdaJvjEsY3MA5j1L2itwDX K/RMTc8GEfbKQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 14B5068A91; Sun, 14 Dec 2025 10:55:24 -0700 (MST) 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 1PzAqR-zXxHs; Sun, 14 Dec 2025 10:55:23 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734918; bh=DtH66KCcrWQglUFsBxSLExce6wNgyspFf1/PgdpW8N4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hCmLnv6N5j4tkeEuZZOv8o1ZCjCJ5yqmc8YATzAx51v6ev/1qVnD4l9hNyJKK4ay1 oHKSqCoa3iaqKB/g2pRZMbxUb55NCygC9Mjq25chI82YABhzyaVXM/oSAIqI2kkJ7i cGUWDmniL+fKQQdT1UXtJ/eZqqHYVjhCJMVIDhXwSEyZSJuH5dnC8GvTZ3Yi+TzFo1 PwMGR8DCPHniMDXP6DiXG+hLKfGduYEzvyz1l+1YVaR2kJ5I8GZjsWTurjB2bbRDV6 da/J89Ya8smktb2XyNcNFmbLvfRcOn6wp5eOy/iamqDSe0ibhqWNHogWM9TfVPYlmj OsgOYCi47oqOg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 16BD068A84; Sun, 14 Dec 2025 10:55:18 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:28 -0700 Message-ID: <20251214175449.3799539-7-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 22LEJQ2EFUS466EJWKSF7VBIJBT5UXCX X-Message-ID-Hash: 22LEJQ2EFUS466EJWKSF7VBIJBT5UXCX 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 06/21] vsprintf: Add support for the %pV format-specifier 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 Add support for the %pV format-specifier which allows printing a struct va_format. This is used by the Linux kernel for recursive printf() formatting and is needed by the ext4l filesystem driver. Add the struct to include/linux/printk.h to match the kernel location. Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/printf.rst | 19 +++++++++++++++++ include/linux/printk.h | 5 +++++ lib/vsprintf.c | 12 +++++++++++ test/common/print.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst index edda8b24a8e..42de22c8555 100644 --- a/doc/develop/printf.rst +++ b/doc/develop/printf.rst @@ -258,6 +258,25 @@ Pointers lower case (requires CONFIG_LIB_UUID), e.g. 'system' for a GUID identifying an EFI system partition. +%pV + prints a struct va_format, which contains a format string and a va_list + pointer. This allows recursive printf formatting and is used for + implementing custom print functions that wrap printf. + + .. code-block:: c + + void my_print(const char *fmt, ...) + { + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + printf("prefix: %pV\n", &vaf); + va_end(args); + } + Tiny printf ----------- diff --git a/include/linux/printk.h b/include/linux/printk.h index 5e85513853c..e28cef0ac31 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -84,4 +84,9 @@ #define printk_once(fmt, ...) \ printk(fmt, ##__VA_ARGS__) +struct va_format { + const char *fmt; + va_list *va; +}; + #endif diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c072b44140b..0f2c303b138 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,6 +25,7 @@ #include #include #include +#include /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') @@ -508,6 +509,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, return uuid_string(buf, end, ptr, field_width, precision, flags, fmt); #endif + case 'V': + { + const struct va_format *vaf = ptr; + va_list va; + + va_copy(va, *vaf->va); + buf += vsnprintf(buf, end > buf ? end - buf : 0, + vaf->fmt, va); + va_end(va); + return buf; + } default: break; } diff --git a/test/common/print.c b/test/common/print.c index 3fe24dc3e9d..9bd409d4b66 100644 --- a/test/common/print.c +++ b/test/common/print.c @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -376,3 +378,49 @@ static int snprint(struct unit_test_state *uts) return 0; } COMMON_TEST(snprint, 0); + +/* Helper function to test %pV format specifier */ +static int print_with_va_format(char *buf, size_t size, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int ret; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + ret = snprintf(buf, size, "prefix: %pV :suffix", &vaf); + va_end(args); + + return ret; +} + +/* Test printing with %pV (struct va_format) */ +static int print_va_format(struct unit_test_state *uts) +{ + char str[64]; + int ret; + + /* Basic string */ + ret = print_with_va_format(str, sizeof(str), "hello"); + ut_asserteq_str("prefix: hello :suffix", str); + ut_asserteq(21, ret); + + /* String with arguments */ + ret = print_with_va_format(str, sizeof(str), "value=%d", 42); + ut_asserteq_str("prefix: value=42 :suffix", str); + ut_asserteq(24, ret); + + /* Multiple arguments */ + ret = print_with_va_format(str, sizeof(str), "%s: %d/%d", "test", 1, 2); + ut_asserteq_str("prefix: test: 1/2 :suffix", str); + ut_asserteq(25, ret); + + /* Truncation */ + ret = print_with_va_format(str, 15, "hello world"); + ut_asserteq_str("prefix: hello ", str); + ut_asserteq(27, ret); + + return 0; +} +COMMON_TEST(print_va_format, 0); From patchwork Sun Dec 14 17:54:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 900 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=1765734930; bh=lpMsZgaPxFmoWlQRayIbEu0fjoFFswgRfK/x1GUjz58=; 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=lg8tU0MGWMs/zIa5EFC7ciWvLSeBK+dFfB1vHuqhUWv66t5L2/NrlksygQglr6Aj5 mvrz6KF9vsSnuFD3OhuQ7dsGeBFLzdpd+5QetWn61hq9eYlf70yTg0f+u5UiVboH34 p2NzfYGGHIGX7SCdcPlfaNpArPKSVlvF92hhIHFOTtqBZKV0RwUEF5GsxGEzPhyhlN xzMYcwa5y9r+NXvxjgLbCidvtUVReB1cxMm5FCcDMiqqkg2P0Fg4x1jMWsQwqJ+fNw mo9Lg9vOntKE3KOD9B0uvDYH7Cv5BTOSEMU2ptYDpDqYgL1723BVhGWByANJ5584vR 2xF/Bc/MmF4VQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 4FE6C68A89 for ; Sun, 14 Dec 2025 10:55:30 -0700 (MST) 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 XjTo8k2Xq7pV for ; Sun, 14 Dec 2025 10:55:30 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734930; bh=lpMsZgaPxFmoWlQRayIbEu0fjoFFswgRfK/x1GUjz58=; 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=lg8tU0MGWMs/zIa5EFC7ciWvLSeBK+dFfB1vHuqhUWv66t5L2/NrlksygQglr6Aj5 mvrz6KF9vsSnuFD3OhuQ7dsGeBFLzdpd+5QetWn61hq9eYlf70yTg0f+u5UiVboH34 p2NzfYGGHIGX7SCdcPlfaNpArPKSVlvF92hhIHFOTtqBZKV0RwUEF5GsxGEzPhyhlN xzMYcwa5y9r+NXvxjgLbCidvtUVReB1cxMm5FCcDMiqqkg2P0Fg4x1jMWsQwqJ+fNw mo9Lg9vOntKE3KOD9B0uvDYH7Cv5BTOSEMU2ptYDpDqYgL1723BVhGWByANJ5584vR 2xF/Bc/MmF4VQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3FC2868AC0 for ; Sun, 14 Dec 2025 10:55:30 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734928; bh=YscAAkGBA61wKF1Eq/IEysb8YxvOZ6tLMqqETsosFEg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SoQqx+XhYSQlmQY9e34ysNRN4WHz0SWwdbQ3uuU4hd0JEEZzBLY7clIswssHr7tvk IlIEvxhAaN2pawAwF2vWNs+w/s3pmI2hxCTns7sir0Ao9YTmYtLcKgKaI8zC1PEayb rdN+XN8TJShNmQSun3UqNyE3EEt4y0e+Y4fechotLVQmnnCunpQ58i7ddt/Z4AiD5Q u7QRMexFn6uNM4GotFYZ8SrZRxR7fuPGtC1JOVf/ifDo1PfT0oPChl4UD8ECp3FZyL W+xoPAOynBYrvrR8k355V1JRYHXf6xLqKsVXxdJOv8boTm6zXZlQ5sYPmxenr4/YU7 zWDx06erWtFAA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 42C9D68AC0; Sun, 14 Dec 2025 10:55:28 -0700 (MST) 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 OmIRKslkpHrP; Sun, 14 Dec 2025 10:55:28 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734922; bh=Oftx1f3gpxxGXW4Uua1qblrSic44cDNh80/qQvi8w5U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jo1svf0Z7ZIfsP0Vgmk3e3+mZsP5AgwkT1F29XRQ6mssNPSbjkN1H5bg/O5S+Wu/d 92ttL7hJsQdsvmOonuSNg30L1MQtXyaviueGS7G3Xuq/IAU6LVzzABuGCGhlXc73SC 9QNJE/wIlVeFUfxc/Wleyrxw8gw83VvGIPD9KSjeGEk17bZXoEXCKI56zHic4lPj9j TfnYXwd8F0sn+PWx334Q8ud3l0KZUmcZjzjyoY/SOIZz3+vCiojHbZIgccMFfKMWFm yWccGrqCP6s1RXVBiunIyHkBZwoYs7wn1/RQrY3YYe5yYJd7DbXhgmQnNAymzuv2qi 2iRlNbkoNQO0w== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 9432B68A89; Sun, 14 Dec 2025 10:55:22 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:29 -0700 Message-ID: <20251214175449.3799539-8-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: EJEZJZUFKX66XPPE5VUZHLS6YXJ6LUA5 X-Message-ID-Hash: EJEZJZUFKX66XPPE5VUZHLS6YXJ6LUA5 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 07/21] check_linker_lists: Enhance detection of alignment problems 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 When linker-inserted padding breaks list integrity, pointer arithmetic like (end - start) / sizeof(struct) produces garbage. GCC optimizes division by constants using multiplicative inverses, which only works when the dividend is an exact multiple. With padding, outputs like "Running -858993444 bloblist tests" appear instead of the correct count. Enhance the linker list checking script to detect these problems by adding symbol size tracking using nm -S. This enables: 1. Padding detection: Compare symbol sizes to gaps. If gap > size, padding was inserted, breaking contiguous array assumptions. 2. Pointer arithmetic bugs: Check if (end - start) marker span is a multiple of struct size. Co-developed-by: Claude Signed-off-by: Simon Glass --- scripts/check_linker_lists.py | 206 +++++++++++++++++++++++----------- 1 file changed, 143 insertions(+), 63 deletions(-) diff --git a/scripts/check_linker_lists.py b/scripts/check_linker_lists.py index c91b1d9875d..4f122480481 100755 --- a/scripts/check_linker_lists.py +++ b/scripts/check_linker_lists.py @@ -1,127 +1,194 @@ #!/usr/bin/env python3 -# -# check_list_alignment.py: Auto-discover and verify the uniform -# spacing of all U-Boot linker list symbols -# -# Analyze the symbol table of a U-Boot ELF file to ensure that -# all entries in all linker-generated lists are separated by a consistent -# number of bytes. Detect problems caused by linker-inserted -# alignment padding. -# -# By default, produce no output if no problems are found -# Use the -v flag to force output even on success -# -# Exit Codes: -# 0: Success. No alignment problems were found -# 1: Usage Error. The script was not called with the correct arguments -# 2: Execution Error. Failed to run `nm` or the ELF file was not found -# 3: Problem Found. An inconsistent gap was detected in at least one list -# +# SPDX-License-Identifier: GPL-2.0+ +"""Check alignment of U-Boot linker lists. + +Auto-discover and verify the uniform spacing of all U-Boot linker list symbols. + +Analyze the symbol table of a U-Boot ELF file to ensure that all entries in all +linker-generated lists are separated by a consistent number of bytes. Detect +problems caused by linker-inserted alignment padding. + +By default, produce no output if no problems are found. +Use the -v flag to force output even on success. + +Exit Codes: + 0: Success - no alignment problems were found + 1: Usage Error - the script was not called with the correct arguments + 2: Execution Error - failed to run `nm` or the ELF file was not found + 3: Problem Found - an inconsistent gap was detected in at least one list +""" import sys import subprocess import re import argparse -from statistics import mode, StatisticsError +from statistics import mode from collections import defaultdict, namedtuple +# Information about a symbol: address, size (from nm -S), and name +Symbol = namedtuple('Symbol', ['address', 'size', 'name']) + # Information about the gap between two consecutive symbols -Gap = namedtuple('Gap', ['gap', 'prev_sym', 'next_sym']) +Gap = namedtuple('Gap', ['gap', 'prev_sym', 'next_sym', 'prev_size']) + +# Start and end marker addresses for a list +Markers = namedtuple('Markers', ['start', 'end']) + # Holds all the analysis results from checking the lists Results = namedtuple('Results', [ 'total_problems', 'total_symbols', 'all_lines', 'max_name_len', 'list_count']) def eprint(*args, **kwargs): - '''Print to stderr''' + """Print to stderr""" print(*args, file=sys.stderr, **kwargs) -def check_single_list(name, symbols, max_name_len): - '''Check alignment for a single list and return its findings +def check_single_list(name, symbols, max_name_len, marker_info=None): + """Check alignment for a single list and return its findings Args: name (str): The cleaned-up name of the list for display - symbols (list): A list of (address, name) tuples, sorted by address + symbols (list): A list of Symbol tuples, sorted by address max_name_len (int): The max length of list names for column formatting + marker_info (Markers): Optional namedtuple with start and end addresses Returns: tuple: (problem_count, list_of_output_lines) - ''' + """ lines = [] if len(symbols) < 2: return 0, [] gaps = [] for i in range(len(symbols) - 1): - addr1, name1 = symbols[i] - addr2, name2 = symbols[i+1] - gaps.append(Gap(gap=addr2 - addr1, prev_sym=name1, next_sym=name2)) + sym1, sym2 = symbols[i], symbols[i+1] + gaps.append(Gap(gap=sym2.address - sym1.address, prev_sym=sym1.name, + next_sym=sym2.name, prev_size=sym1.size)) expected_gap = mode(g.gap for g in gaps) - lines.append( - f"{name:<{max_name_len + 2}} {len(symbols):>12} " - f"{f'0x{expected_gap:x}':>17}") problem_count = 0 + hex_gap = f'0x{expected_gap:x}' + line = f'{name:<{max_name_len + 2}} {len(symbols):>12} {hex_gap:>17}' + lines.append(line) + for g in gaps: if g.gap != expected_gap: problem_count += 1 lines.append( - f" - Bad gap (0x{g.gap:x}) before symbol: {g.next_sym}") + f' - Bad gap (0x{g.gap:x}) before symbol: {g.next_sym}') + elif g.prev_size and g.gap > g.prev_size: + # Gap is larger than symbol size - padding was inserted + problem_count += 1 + lines.append( + f' - Padding: gap 0x{g.gap:x} > size 0x{g.prev_size:x}' + f' before: {g.next_sym}') + + # Check if start/end marker span is a multiple of the struct size + # If not, pointer subtraction (end - start) will produce wrong results + # due to compiler optimization using magic number multiplication + if marker_info: + total_span = marker_info.end - marker_info.start + if total_span % expected_gap != 0: + problem_count += 1 + remainder = total_span % expected_gap + lines.append( + f' - Pointer arithmetic bug: span 0x{total_span:x} is not a ' + f'multiple of struct size 0x{expected_gap:x} ' + f'(remainder: {remainder})') return problem_count, lines def run_nm_and_get_lists(elf_path): - '''Run `nm` and parse the output to discover all linker lists + """Run `nm -S` and parse the output to discover all linker lists Args: elf_path (str): The path to the ELF file to process Returns: - dict or None: A dictionary of discovered lists, or None on error - ''' - cmd = ['nm', '-n', elf_path] + tuple or None: (lists_dict, markers_dict) or None on error + lists_dict: entries keyed by base_name + markers_dict: start/end marker addresses keyed by base_name + """ + cmd = ['nm', '-S', '-n', elf_path] try: proc = subprocess.run(cmd, capture_output=True, text=True, check=True) except FileNotFoundError: eprint( - 'Error: The "nm" command was not found. ' + "Error: The 'nm' command was not found. " 'Please ensure binutils is installed') return None except subprocess.CalledProcessError as e: eprint( f"Error: Failed to execute 'nm' on '{elf_path}'.\n" - f" Return Code: {e.returncode}\n Stderr:\n{e.stderr}") + f' Return Code: {e.returncode}\n Stderr:\n{e.stderr}') return None - list_name_pattern = re.compile( + # Pattern to match _2_ entries (the actual list elements) + entry_pattern = re.compile( r'^(?P_u_boot_list_\d+_\w+)(?:_info)?_2_') + # Pattern to match _1 (start) and _3 (end) markers + marker_pattern = re.compile( + r'^(?P_u_boot_list_\d+_\w+)_(?P[13])$') + lists = defaultdict(list) + markers = defaultdict(dict) # {base_name: {'start': addr, 'end': addr}} + for line in proc.stdout.splitlines(): - if ' D _u_boot_list_' not in line: + if '_u_boot_list_' not in line: continue try: parts = line.strip().split() - address, name = int(parts[0], 16), parts[-1] - - match = list_name_pattern.match(name) + name = parts[-1] + address = int(parts[0], 16) + # Size is present if we have 4 parts and parts[2] is a single char + if len(parts) == 4 and len(parts[2]) == 1: + size = int(parts[1], 16) + else: + size = 0 # Size not available + + # Check for entry (_2_) symbols - must be uppercase D + if ' D _u_boot_list_' in line: + match = entry_pattern.match(name) + if match: + base_name = match.group('base_name') + lists[base_name].append(Symbol(address, size, name)) + continue + + # Check for marker (_1 or _3) symbols - can be any type + match = marker_pattern.match(name) if match: base_name = match.group('base_name') - lists[base_name].append((address, name)) + marker_type = match.group('marker') + if marker_type == '1': + markers[base_name]['start'] = address + else: # marker_type == '3' + markers[base_name]['end'] = address + except (ValueError, IndexError): eprint(f'Warning: Could not parse line: {line}') - return lists + # Convert marker dicts to Markers namedtuples (only if both start/end exist) + marker_tuples = {} + for base_name, m in markers.items(): + if 'start' in m and 'end' in m: + marker_tuples[base_name] = Markers(m['start'], m['end']) -def collect_data(lists): - '''Collect alignment check data for all lists + return lists, marker_tuples + +def collect_data(lists, markers): + """Collect alignment check data for all lists Args: lists (dict): A dictionary of lists and their symbols + markers (dict): A dictionary of start/end marker addresses per list Returns: Results: A namedtuple containing the analysis results - ''' + """ + if markers is None: + markers = {} + names = {} prefix_to_strip = '_u_boot_list_2_' for list_name in lists.keys(): @@ -138,7 +205,9 @@ def collect_data(lists): symbols = lists[list_name] total_symbols += len(symbols) name = names[list_name] - problem_count, lines = check_single_list(name, symbols, max_name_len) + marker_info = markers.get(list_name) + problem_count, lines = check_single_list(name, symbols, max_name_len, + marker_info) total_problems += problem_count all_lines.extend(lines) @@ -150,19 +219,20 @@ def collect_data(lists): list_count=len(lists)) def show_output(results, verbose): - '''Print the collected results to stderr based on verbosity + """Print the collected results to stderr based on verbosity Args: results (Results): The analysis results from collect_data() verbose (bool): True to print output even on success - ''' + """ if results.total_problems == 0 and not verbose: return header = (f"{'List Name':<{results.max_name_len + 2}} {'# Symbols':>12} " f"{'Struct Size (hex)':>17}") + sep = f"{'-' * (results.max_name_len + 2)} {'-' * 12} {'-' * 17}" eprint(header) - eprint(f"{'-' * (results.max_name_len + 2)} {'-' * 12} {'-' * 17}") + eprint(sep) for line in results.all_lines: eprint(line) @@ -177,19 +247,28 @@ def show_output(results, verbose): eprint('\nSUCCESS: All discovered lists have consistent alignment') def main(): - '''Main entry point of the script, returns an exit code''' + """Main entry point of the script, returns an exit code""" epilog_text = ''' Auto-discover all linker-generated lists in a U-Boot ELF file -(e.g., for drivers, commands, etc.) and verify their integrity. Check -that all elements in a given list are separated by a consistent number of -bytes. +(e.g., for drivers, commands, etc.) and verify their integrity. + +Problems detected (cause build failure): + +1. Inconsistent gaps: Elements in a list should all be separated by the same + number of bytes (the struct size). If the linker inserts padding between + some elements but not others, this is detected and reported. + +2. Padding detection: Using symbol sizes from nm -S, the script compares each + symbol's size to the gap after it. If gap > size, the linker inserted + padding, which breaks U-Boot's assumption that the list is a contiguous + array of same-sized structs. -Problems typically indicate that the linker has inserted alignment padding -between two elements in a list, which can break U-Boot's assumption that the -list is a simple, contiguous array of same-sized structs. +3. Pointer arithmetic bugs: Each list has start (_1) and end (_3) markers. + If the span (end - start) is not a multiple of struct size, pointer + subtraction produces garbage due to GCC's magic-number division. ''' parser = argparse.ArgumentParser( - description='Check alignment of all U-Boot linker lists in an ELF file.', + description='Check alignment of U-Boot linker lists in an ELF file.', epilog=epilog_text, formatter_class=argparse.RawDescriptionHelpFormatter ) @@ -200,16 +279,17 @@ list is a simple, contiguous array of same-sized structs. args = parser.parse_args() - lists = run_nm_and_get_lists(args.elf_path) - if lists is None: + result = run_nm_and_get_lists(args.elf_path) + if result is None: return 2 # Error running nm + lists, markers = result if not lists: if args.verbose: eprint('Success: No U-Boot linker lists found to check') return 0 - results = collect_data(lists) + results = collect_data(lists, markers) show_output(results, args.verbose) return 3 if results.total_problems > 0 else 0 From patchwork Sun Dec 14 17:54:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 901 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=1765734933; bh=2bCaL+JLMdntS+CFiXctTbJLkrbCEA8Jxk3KaNcA2U8=; 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=Dl6v4LQlvyF9RuOGgEbCGgoUuwoQXO1oCVZyxjR5U1Vymm1ns+MTgi9rYEwus9T8y kMAPuy2DviNCHDVTCwoeNdJr6sxYRAKs0hHtSPXfgSsTMAaMw8ots0cs/f7anWkjGj 7VGTgvVnhwMt+4asHcLRB3EDlTnqlcwCc9iEMzOUjp3tSTY89VkIAFa1r+mA43ophK 1GcbX00+ED/rIsJ2HQ9dd1FLEm6nNyIhcJa7/49jc+kN3DEiub38JFrzNCVrqQud5h eU04lrw3dPDcsHlxGafWTeFzGCsfbAJYhyV7/QW6V0Q05OZY0+Z0k2RAN17E3KHXrT z179nJ/bqrmbQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C6C3668AEA for ; Sun, 14 Dec 2025 10:55:33 -0700 (MST) 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 2HnhTntHUg3u for ; Sun, 14 Dec 2025 10:55:33 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734933; bh=2bCaL+JLMdntS+CFiXctTbJLkrbCEA8Jxk3KaNcA2U8=; 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=Dl6v4LQlvyF9RuOGgEbCGgoUuwoQXO1oCVZyxjR5U1Vymm1ns+MTgi9rYEwus9T8y kMAPuy2DviNCHDVTCwoeNdJr6sxYRAKs0hHtSPXfgSsTMAaMw8ots0cs/f7anWkjGj 7VGTgvVnhwMt+4asHcLRB3EDlTnqlcwCc9iEMzOUjp3tSTY89VkIAFa1r+mA43ophK 1GcbX00+ED/rIsJ2HQ9dd1FLEm6nNyIhcJa7/49jc+kN3DEiub38JFrzNCVrqQud5h eU04lrw3dPDcsHlxGafWTeFzGCsfbAJYhyV7/QW6V0Q05OZY0+Z0k2RAN17E3KHXrT z179nJ/bqrmbQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id B13D168ADF for ; Sun, 14 Dec 2025 10:55:33 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734932; bh=/SISnDxF7nIGmBxwfViwjoMraCV88oJSn16j1wekX7U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Pd5rj3QM1cIbWohWn58QF6a/N4czRX5DybKX3vV4sAeYll/Ji4wWdY1aeFq82hpRp CH9TZXjosMCokXcDeNpeoSX7Dh0XPklNZFZP2af6AQ2TpjKpGKXuZHxNaNw6Q2ajNq BDNncEepwRHgKZaEt5tCQ3qiFQ7dhgoLQoCMVNt5+6Tubl4QFxyquZiTpPQp63OCEu Z0+I1ybWnflE4G+oFJh6caTmOf/+tH5NYMh3J+Md93WJ6uMxSOJy9OBgfk0PpNWc1n eVOC5QnZZ0e0h0X4PawTw+FIaD0HJpbty+jC/dWSnhjd3IiJu8dWDUIyXbcC7MC8Hj PteR0TbfH76kg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A705968AC0; Sun, 14 Dec 2025 10:55:32 -0700 (MST) 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 I3QyaYSEhZbF; Sun, 14 Dec 2025 10:55:32 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734927; bh=V3NplywnDqo7EaJFHaX0uzj8DpTMRPlyW003+0TyzT0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DeJGvs2qjVnVQj0P4ex0+DRFP4nVJK/41EILPaTck/bDRxPE4/QaTHgEGu0g9t9j8 MPd6GgAs018q8xOUnQw3iPAor8i8AoPCgEGqG5EDxpOUTobHYSiGQ0LdVIfuzqTf2J dWPeix8KPpbaeqzOsU9/OHHHM+rI8rplqzklR9yyyAfMF89Z5scxkhcmZmJE64HdGt oHSKiJ3/JXFuqfUVvONhOks7DuDasKZM2RosvD1qUPBJvqXI36eCcz5c5TGvQnQIjO Idnvhw46SK6ydp1MOracWjfQMbQG451K6I5C8EZGrlHYCTDpzU0zZDY77+meCDJRDn g4OcS5XmP7iEg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 2559F68A84; Sun, 14 Dec 2025 10:55:27 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:30 -0700 Message-ID: <20251214175449.3799539-9-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 2RZZSAIJVWJQPUKBUV3EUKFVLH64E2E4 X-Message-ID-Hash: 2RZZSAIJVWJQPUKBUV3EUKFVLH64E2E4 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 08/21] linker_lists: Fix end-marker alignment to prevent padding 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 Change the alignment of end markers in ll_entry_end() and ll_end_decl() from __aligned(4) and __aligned(CONFIG_LINKER_LIST_ALIGN) respectively to __aligned(1). The linker places zero-size end markers at aligned boundaries based on what follows them. When the next list's start marker has a high alignment requirement (e.g., 32 bytes), padding gets inserted before the end marker. This causes the byte span (end - start) to not be an exact multiple of the struct size. The compiler optimizes pointer subtraction (end - start) using magic-number multiplication for division. This optimization only produces correct results when the byte span is an exact multiple of the struct size. With padding, the result is garbage (e.g., -858993444 instead of 15). By using __aligned(1), the end marker is placed immediately after the last entry with no padding, ensuring (end - start) equals exactly n * sizeof where n is the number of entries. This makes ll_entry_count() and direct pointer arithmetic work correctly. Fixes: 0b2fa98aa5e5 ("linker_lists: Fix alignment issue") Co-developed-by: Claude Signed-off-by: Simon Glass --- include/linker_lists.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/include/linker_lists.h b/include/linker_lists.h index 0f4a2d686e2..6a018f175ca 100644 --- a/include/linker_lists.h +++ b/include/linker_lists.h @@ -145,6 +145,20 @@ * Since this macro defines an array end symbol, its leftmost index * must be 2 and its rightmost index must be 3. * + * The end symbol uses __aligned(1) to ensure it is placed immediately after + * the last entry without any padding. This is critical for ll_entry_count() + * to work correctly. + * + * If the end marker had a higher alignment (e.g., 4 or 32 bytes), the linker + * might insert padding between the last entry and the end marker to satisfy + * alignment requirements of the following section. This would cause pointer + * subtraction (end - start) to produce incorrect results because the compiler + * optimizes pointer division using magic-number multiplication, which only + * works correctly when the byte span is an exact multiple of the struct size. + * + * With __aligned(1), the end marker is placed at exactly (start + n * sizeof) + * where n is the number of entries, ensuring correct pointer arithmetic. + * * Example: * * :: @@ -153,7 +167,7 @@ */ #define ll_entry_end(_type, _list) \ ({ \ - static char end[0] __aligned(4) __attribute__((unused)) \ + static char end[0] __aligned(1) __attribute__((unused)) \ __section("__u_boot_list_2_"#_list"_3"); \ _type * tmp = (_type *)&end; \ asm("":"+r"(tmp)); \ @@ -239,8 +253,12 @@ static _type _sym[0] __aligned(CONFIG_LINKER_LIST_ALIGN) \ __maybe_unused __section("__u_boot_list_2_" #_list "_1") +/* + * ll_end_decl uses __aligned(1) to avoid padding before the end marker. + * See the comment for ll_entry_end() for a full explanation. + */ #define ll_end_decl(_sym, _type, _list) \ - static _type _sym[0] __aligned(CONFIG_LINKER_LIST_ALIGN) \ + static _type _sym[0] __aligned(1) \ __maybe_unused __section("__u_boot_list_2_" #_list "_3") /** From patchwork Sun Dec 14 17:54:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 902 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=1765734938; bh=KRCBxlgpkRCgTsSTa4o3pKi+7Idq3M8T58iGuSQQtlA=; 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=CCvr+DEy/HE+dOJtzblZzMuq7wEonvZO0R0ik6jrYBZJ+m702GgpVTmTNbqogZ3iE ZUsziliw8LzYFmlEH0VkidbMnq8m6IhjoZs1pqci4IDTt6zXGNuUFaHzCKR0BmT001 OAT/qz4xEGjzwKPY0NmnYfWsh9/KKvRRQ4desjgj3yuni0o5TVg8m0NU43U9i4PgkI mWQ2KA6Q9bCFdMjKGz2IyHU5dPBcAl1cEINxPbPfiM9c4CEWrRyukUlrkdDQOmAAfU NBrfmai4HHBhAVzw4L6tBvOkhghNeb4lrQV5HeaicbpIYTuPb3ZkjuKNuYHOR+RohN mQsc3XjEVzcQA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 404C368AE8 for ; Sun, 14 Dec 2025 10:55:38 -0700 (MST) 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 5ukKiWSJax1d for ; Sun, 14 Dec 2025 10:55:38 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734938; bh=KRCBxlgpkRCgTsSTa4o3pKi+7Idq3M8T58iGuSQQtlA=; 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=CCvr+DEy/HE+dOJtzblZzMuq7wEonvZO0R0ik6jrYBZJ+m702GgpVTmTNbqogZ3iE ZUsziliw8LzYFmlEH0VkidbMnq8m6IhjoZs1pqci4IDTt6zXGNuUFaHzCKR0BmT001 OAT/qz4xEGjzwKPY0NmnYfWsh9/KKvRRQ4desjgj3yuni0o5TVg8m0NU43U9i4PgkI mWQ2KA6Q9bCFdMjKGz2IyHU5dPBcAl1cEINxPbPfiM9c4CEWrRyukUlrkdDQOmAAfU NBrfmai4HHBhAVzw4L6tBvOkhghNeb4lrQV5HeaicbpIYTuPb3ZkjuKNuYHOR+RohN mQsc3XjEVzcQA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2E84768A91 for ; Sun, 14 Dec 2025 10:55:38 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734936; bh=KdcMffrHuSkYxx6oOV+jczuYNDdfW7SSpS7vJC3FeUY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aZkRN+t2TiDT5jdfQ+Md2wMAXtrCAJtom+7IkHxjZFezfTQnLDF9HUK/ocd13urNk paD5bkmC+KW3P1+F176TBQASFLlGIIEvULEXcr1BA8a+CCCiV8JW/L4jAgIsjb1Q8X +He/QLVAiUPtYK4uATq8uNtdg+STRYpIlPoLlJcaW4QeHRSbDpDbOmfpiUo/PQS+70 KVrSOfXaGc58y4jVBuyB41fZdr9H/JK5igofqmqQdwbFB4LCBMRr+KARFT572qIKA9 W5rpdOS1fOgTpGS4QvwdGANGtZV4CH2DjFsXr8g+3Ajgwx0zVF7HBBcEO9eRe8xyan IJU+d6pf/HNew== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 38B7268A84; Sun, 14 Dec 2025 10:55:36 -0700 (MST) 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 0nDvC70AhZVj; Sun, 14 Dec 2025 10:55:36 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734932; bh=s33gHlBG8P1wecWj4VQq5GVGQUVL0EqOEBkC5gyU9go=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RkhnWNakMZIv0ez5vaKyolS4h22hBRbSteuWNlatg5S2F4lOQnMcuSRG9Q6xkkRWa zBBoMyTKWfU4lE7emuE0xjGtH2GvaAx4m6Ddo8C6zJnciY/xydMx3GQRNEVCQfn7iE tzFgV9SIPLj6nunQYLSLsIOrIx4NMRpwiRrtneo/kLor4KZZTUULc6oon+UvHlap8N KPVIQ5K5Pi8RKLTXTnbmeOlVUBJuVliz37n76tmR7gCykU2YFZznLaLRVpwp9AennC Vh/iHe1GWgjF9TyXVEmk9/IzbDtCGKyR+4EXCtXTDz5QYbs/1qX1P775LY2JyzCpSa sfXXz1mdT4TdA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id C81EC68A89; Sun, 14 Dec 2025 10:55:31 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:31 -0700 Message-ID: <20251214175449.3799539-10-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 7HLKBPTOPMGS7F2MYH5EZCEIXHS6LPFV X-Message-ID-Hash: 7HLKBPTOPMGS7F2MYH5EZCEIXHS6LPFV 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 09/21] test: vbe: Fix the ut-flag order in vbe_test_fixup_norun() 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 Move the -f flag before the suite name since ut parses flags before the suite argument. Co-developed-by: Claude Signed-off-by: Simon Glass --- test/py/tests/test_vbe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/py/tests/test_vbe.py b/test/py/tests/test_vbe.py index e5b489bc819..4ccf4fb937b 100644 --- a/test/py/tests/test_vbe.py +++ b/test/py/tests/test_vbe.py @@ -87,7 +87,7 @@ bootm loados bootm prep fdt addr fdt print -ut bootstd -f vbe_test_fixup_norun +ut -f bootstd vbe_test_fixup_norun ''' @pytest.mark.boardspec('sandbox') From patchwork Sun Dec 14 17:54:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 903 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=1765734942; bh=Zf49s6aXAEc5+2gtCwVgxRfP+7IL9sFoqWO+/CSlxYc=; 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=XBK/9z3q+CwOV8r8LRzuezDnFEZ/Zkdrn6JMhheZ7RQ1PZaDbsmmsed8ZBOVFSuZS VGgpiTtvI/SGWvDuxqiSDy8vJItq0hz+nWkXt7ZkKKLDlk8H/v3GEDiMvSbUWqiDd0 jkEZwiLMBESdpJWbYUn0mZGjt0pj5LrQlbWqvnUkkHvUpWqpYNNgcPhvXxffF3VpGC +G4Xoa8Yi/biep0LO6zZGs3V248vhbuKSbc799PzTDD6w6LUXQpu4SPxBFojpip2T2 OQIx6HvJu27ePNJgEJiNlUh0e2BezNYt21wK+yTZArKOnUb4psorgWAHaU8l2EsO/L GFRS1tMKLT+Lg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id F33CC68AFE for ; Sun, 14 Dec 2025 10:55:42 -0700 (MST) 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 jYcOIeSBpM2e for ; Sun, 14 Dec 2025 10:55:42 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734942; bh=Zf49s6aXAEc5+2gtCwVgxRfP+7IL9sFoqWO+/CSlxYc=; 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=XBK/9z3q+CwOV8r8LRzuezDnFEZ/Zkdrn6JMhheZ7RQ1PZaDbsmmsed8ZBOVFSuZS VGgpiTtvI/SGWvDuxqiSDy8vJItq0hz+nWkXt7ZkKKLDlk8H/v3GEDiMvSbUWqiDd0 jkEZwiLMBESdpJWbYUn0mZGjt0pj5LrQlbWqvnUkkHvUpWqpYNNgcPhvXxffF3VpGC +G4Xoa8Yi/biep0LO6zZGs3V248vhbuKSbc799PzTDD6w6LUXQpu4SPxBFojpip2T2 OQIx6HvJu27ePNJgEJiNlUh0e2BezNYt21wK+yTZArKOnUb4psorgWAHaU8l2EsO/L GFRS1tMKLT+Lg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DE9A168A84 for ; Sun, 14 Dec 2025 10:55:42 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734941; bh=EmcI4OxTi1IDiJuXJcmjaDiCbhSoww6mHEJ/zZyQbto=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r5XJLTP6F0tDTePkhhjR+xbr/C3dn1J0mt9iCb6X/RiPZuXRBTBMNaPGg374JNBMh wFG0PDZQ9zCvq+381pdl6Eb8dF5PXqtYfjJiDO2WYktUggessJmccx+dfSgr28eAA+ WXEZUCpMGtC0CemoMVfD5HfOVtDDMY9RsaCvyVQ8fIRC4DZpZftFZFpJE9/Q36lWGd Shc4PbsifIkE0JFJdQtrqRNGCQp4Hk43j6HiHbDxosA5wfIpFEQnbR3MMRPPaaINh/ Rxl+qoj/VUzDjlNP+5ZXkLfqOsVqv8YeFoknL0JHJxALVLul0xeFkuaPyZ/+ZsuRHr hfxkM5Jry1UJA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2FD0B68A84; Sun, 14 Dec 2025 10:55:41 -0700 (MST) 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 K4LlccnYmeC8; Sun, 14 Dec 2025 10:55:41 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734937; bh=W641O1WM04SiWVEbRs5XbVl73jEnY0DQen6phSmhR0o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Yykqct3lJi5wjUwA6IAMLDWy/OsYhu6nQYh1JogMBfpR37VJihlZUKN8/dM84mHtr RKA4GiKIpHBLjvnXQfZG6uTdT0bFT2xOFDA11POYDkARUtfd3Y2Rhufy08RDbI2COR DdDeZDwucv828hgfq8B1ds7OulkKdmVPp4sxz3yY5sprhZiCQLhFI/ZVxAxroTXh1s rf/+m4YYQw0w5KACVam2szzZis9tAh/XjAYW/Prg1XQqwpqZMq6BGNiYSXQmxPoFQf N+MStJEsKoyaO3+NcgzK+Ls4SKpMFdNMwoPGdpvOUR8uyp26Bkl/QFRG6WPqV0YwvH dfowu5ylDdkGA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 80B3668A89; Sun, 14 Dec 2025 10:55:36 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:32 -0700 Message-ID: <20251214175449.3799539-11-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: LIOKTDOC4TTVQMOCP5AK4PHLCCMGOYF4 X-Message-ID-Hash: LIOKTDOC4TTVQMOCP5AK4PHLCCMGOYF4 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 10/21] test: Add a helper to check the next line against a regex 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 Add a new ut_assert_nextline_regex() macro and ut_check_console_line_regex() helper to check console output against a regex pattern. This is useful when the exact output varies (e.g., file paths or line numbers in error messages). Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/tests_writing.rst | 3 +++ include/test/ut.h | 29 +++++++++++++++++++++++++++++ test/ut.c | 21 +++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst index 43756989d43..41612a9e21b 100644 --- a/doc/develop/tests_writing.rst +++ b/doc/develop/tests_writing.rst @@ -451,6 +451,9 @@ ut_assert_nextlinen(fmt, args...) Assert that the next console output line matches up to the format string length +ut_assert_nextline_regex(pattern) + Assert that the next console output line matches a regex pattern + ut_assert_nextline_empty() Assert that the next console output line is empty diff --git a/include/test/ut.h b/include/test/ut.h index a2b42cdf414..7098c9be7d6 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -87,6 +87,20 @@ int ut_check_console_line(struct unit_test_state *uts, const char *fmt, ...) int ut_check_console_linen(struct unit_test_state *uts, const char *fmt, ...) __attribute__ ((format (__printf__, 2, 3))); +/** + * ut_check_console_line_regex() - Check the next console line against a regex + * + * This checks the next line of console output against a regex pattern. + * + * After the function returns, uts->expect_str holds the regex pattern and + * uts->actual_str holds the actual string read from the console. + * + * @uts: Test state + * @regex: Regular expression pattern to match against + * Return: 0 if OK, other value on error + */ +int ut_check_console_line_regex(struct unit_test_state *uts, const char *regex); + /** * ut_check_skipline() - Check that the next console line exists and skip it * @@ -412,6 +426,21 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); __ret; \ }) +/* Assert that the next console output line matches a regex pattern */ +#define ut_assert_nextline_regex(pattern) ({ \ + int __ret = 0; \ + \ + if (ut_check_console_line_regex(uts, pattern)) { \ + ut_failf(uts, __FILE__, __LINE__, __func__, \ + "console regex", \ + "\nExpected regex '%s',\n got '%s'", \ + uts->expect_str, uts->actual_str); \ + if (!uts->soft_fail) \ + return CMD_RET_FAILURE; \ + } \ + __ret; \ +}) + /* Assert that there is a 'next' console output line, and skip it */ #define ut_assert_skipline() ({ \ int __ret = 0; \ diff --git a/test/ut.c b/test/ut.c index 94b09364687..aed59cae0b9 100644 --- a/test/ut.c +++ b/test/ut.c @@ -150,6 +150,27 @@ int ut_check_console_linen(struct unit_test_state *uts, const char *fmt, ...) strlen(uts->expect_str)); } +int ut_check_console_line_regex(struct unit_test_state *uts, const char *regex) +{ + char err[UT_REGEX_ERR_SIZE]; + int len; + int ret; + + len = strlcpy(uts->expect_str, regex, sizeof(uts->expect_str)); + if (len >= sizeof(uts->expect_str)) { + ut_fail(uts, __FILE__, __LINE__, __func__, + "unit_test_state->expect_str too small"); + return -EOVERFLOW; + } + ret = readline_check(uts); + if (ret == -ENOENT) + return 1; + + ret = ut_check_regex(regex, uts->actual_str, err); + + return ret; +} + int ut_check_skipline(struct unit_test_state *uts) { int ret; From patchwork Sun Dec 14 17:54: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: 904 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=1765734947; bh=+C08RbliFRFoZd9tSUHcSiMa0ztwf8voksLf2JI+7Do=; 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=ThK8EURy7XMxkKugUdj4L57aIWZdynC/OLsrZMAIukI2ZKgpu0qFjF1ZhyC5Wuaq/ QUMt26H5JKUdmSLp0NMhSZoXarjDzzyjo9tzw8XLgrxQZQ7hb8oKbB8jI4OM4Z2mMo ChMhBB7AiElO/cdqAE7VLqfpsGx4IwtKz12hi2pSp485sNE4fpG4+KQSnOEQjy2O3r aaVEqTT7iG/4PccOUbQmQx5RHaUBE6dKVbHDlIy4xhT/7VwQBQBBD2OW058exe4532 jd5MImAj/BRDipyZBQv5b5kvqJTwL2a8wPoND7Gw3WR826jVMANjPLp2jrSndZ98vz sN9XGz+pmukDg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 70B3768B0B for ; Sun, 14 Dec 2025 10:55:47 -0700 (MST) 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 LPQeLY1bwxCq for ; Sun, 14 Dec 2025 10:55:47 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734947; bh=+C08RbliFRFoZd9tSUHcSiMa0ztwf8voksLf2JI+7Do=; 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=ThK8EURy7XMxkKugUdj4L57aIWZdynC/OLsrZMAIukI2ZKgpu0qFjF1ZhyC5Wuaq/ QUMt26H5JKUdmSLp0NMhSZoXarjDzzyjo9tzw8XLgrxQZQ7hb8oKbB8jI4OM4Z2mMo ChMhBB7AiElO/cdqAE7VLqfpsGx4IwtKz12hi2pSp485sNE4fpG4+KQSnOEQjy2O3r aaVEqTT7iG/4PccOUbQmQx5RHaUBE6dKVbHDlIy4xhT/7VwQBQBBD2OW058exe4532 jd5MImAj/BRDipyZBQv5b5kvqJTwL2a8wPoND7Gw3WR826jVMANjPLp2jrSndZ98vz sN9XGz+pmukDg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 6062768ADC for ; Sun, 14 Dec 2025 10:55:47 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734945; bh=ix4VzLLcRF6GTV90xKu+e/tH0ZB7GojBW5yINCvoXmk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NCvIxGtWxuGqpISAXtpVt32/Sci79e/kE2bpZu8UxoPC2KbVTJMnAsrfe2lQUaRvD 28rL0EDzDWEd0axD0XduPHDF7SNTj5hLHHZZavK9JUpzOd+lshyFQnJkTz+OmkkISz M1+FbnijLnAlANqaroOecckTp7rVt45ym2AtnDah1GXaDK9eeGID7kr94+U/MBU2pj bhqQYQwAITciAAygAhFCZQR+46eswBHRFyek/xguyuXVJhWitkyzBA9Yr1DOOB1Afj NmMv8BFR4jsUEdovx0UepqaF+x4erBH0j00E+7/7AfT6Opr1UL69jI5Ek2Zi5kEoED V7QQkaFSt9WfA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D2E0E68A84; Sun, 14 Dec 2025 10:55:45 -0700 (MST) 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 dIMeg8w9G-VH; Sun, 14 Dec 2025 10:55:45 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734941; bh=gxAsHmXmQnTaaLwyiqT/SGuN7m0vimyywapuYutudJY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CFxQIy0kqNi64MYCMOKOQykXKAv2QAV21hcRE39Y0HL3n3VWsS/hxHSWNsfUHqW74 kQPJRk+P5ZVwrMJcpbv6TQ2/gWs34Ov/6J97sc/4k9vGnAzPUu9zWeIFzmS+ns278/ b4ELyc1bTXtGH4vTl7YsOJQa7KdtWdb9gZoi618swOTErFuHiIF+/kwCI/6nk//dMD VGrmxv3PRcUTVWlq/EaVhTC+COUSLyECsvjMGgTxrblWqoUmecvJn4fpkymmFCMIKB yT4eAc80FuTMrKS84PEJ/CWychuYT1L3xIE8mDIiQY31lCweWG/NRc3O1T51U1UYiq ZmCwjkg70pQew== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 72FFF68A89; Sun, 14 Dec 2025 10:55:41 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:33 -0700 Message-ID: <20251214175449.3799539-12-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: HPLHC7TQ7WMNKLISIZGABVSUR32XEV44 X-Message-ID-Hash: HPLHC7TQ7WMNKLISIZGABVSUR32XEV44 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: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 11/21] test: Add argument-type definitions 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 Add types for declaring and storing unit test arguments: - enum ut_arg_type: INT, BOOL, STR types - enum ut_arg_flags: OPTIONAL flag for non-required args - struct ut_arg_def: declares expected args with defaults - struct ut_arg: holds parsed argument values This prepares for passing key=value arguments to tests via the 'ut' command instead of needing to use environment variables. Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- include/test/test.h | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/include/test/test.h b/include/test/test.h index 086fff1ca26..5ead1200a40 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -27,6 +27,40 @@ struct ut_stats { ulong duration_ms; }; +/** + * enum ut_arg_type - Type of a unit test argument + * + * @UT_ARG_INT: Integer argument (hex with 0x prefix, or decimal) -> vint + * @UT_ARG_BOOL: Boolean argument (0 or 1) -> vbool + * @UT_ARG_STR: String argument -> vstr + */ +enum ut_arg_type { + UT_ARG_INT, + UT_ARG_BOOL, + UT_ARG_STR, +}; + +/** + * struct ut_arg - Parsed unit test argument value + * + * Holds the parsed value of an argument after command-line processing. + * + * @name: Name of the argument (points to ut_arg_def.name) + * @type: Type of the argument + * @vint: Integer value (when type is UT_ARG_INT) + * @vbool: Boolean value (when type is UT_ARG_BOOL) + * @vstr: String value (when type is UT_ARG_STR, points into argv) + */ +struct ut_arg { + const char *name; + enum ut_arg_type type; + union { + long vint; + bool vbool; + const char *vstr; + }; +}; + /* * struct unit_test_state - Entire state of test system * @@ -107,6 +141,37 @@ enum ut_flags { UTF_UNINIT = BIT(14), /* test uninits a suite */ }; +/** + * enum ut_arg_flags - Flags for unit test arguments + * + * @UT_ARGF_OPTIONAL: Argument is optional; use default value if not provided + */ +enum ut_arg_flags { + UT_ARGF_OPTIONAL = BIT(0), +}; + +/** + * struct ut_arg_def - Definition of a unit test argument + * + * Declares an expected argument for a test, including its name, type, + * whether it is optional, and its default value. + * + * @name: Name of the argument (used in key=value matching) + * @type: Type of the argument (int, bool, or string) + * @flags: Argument flags (e.g., UT_ARGF_OPTIONAL) + * @def: Default value (used when argument is optional and not provided) + */ +struct ut_arg_def { + const char *name; + enum ut_arg_type type; + int flags; + union { + long vint; + bool vbool; + const char *vstr; + } def; +}; + /** * struct unit_test - Information about a unit test * From patchwork Sun Dec 14 17:54:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 905 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=1765734952; bh=WuZAog6ipOxDEVt1dzXj4xyRcxrJJpiMfVkRDrQLRHM=; 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=TC8GFGIkQZ1ZECc4IVqokcD8CHvl2T0geATX7ZJCfT7ITGpvMu6aaRiKJF6kJu8la o3k7KCrLwYt5YK94JtbeRt20J9AJ5SCRQiu2B2uQku+gdAFYr9PAfDcU4o9FGx+vTM KarY7I5XoLYCCF31TP6NJZXKL6Rke+7iZ1G6S80fXakRaDvGkQk4DtMrcPp/GujBUC ldimy4jOXOCAp5PecrIgbSlsdrEK9Wm253SrAZgYeqcGsoTDU+LDmWZ0fqND6ci3qI 77ecm5bKveVzpJYuJ3wcbgd5p+C1PB8S6Lv9PFgbUtq+CF8m/tmUs3DTjR2KDIAZnM lp6eXiC8mYayA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D396E68AEA for ; Sun, 14 Dec 2025 10:55:52 -0700 (MST) 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 HPG6yFmqi-mT for ; Sun, 14 Dec 2025 10:55:52 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734952; bh=WuZAog6ipOxDEVt1dzXj4xyRcxrJJpiMfVkRDrQLRHM=; 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=TC8GFGIkQZ1ZECc4IVqokcD8CHvl2T0geATX7ZJCfT7ITGpvMu6aaRiKJF6kJu8la o3k7KCrLwYt5YK94JtbeRt20J9AJ5SCRQiu2B2uQku+gdAFYr9PAfDcU4o9FGx+vTM KarY7I5XoLYCCF31TP6NJZXKL6Rke+7iZ1G6S80fXakRaDvGkQk4DtMrcPp/GujBUC ldimy4jOXOCAp5PecrIgbSlsdrEK9Wm253SrAZgYeqcGsoTDU+LDmWZ0fqND6ci3qI 77ecm5bKveVzpJYuJ3wcbgd5p+C1PB8S6Lv9PFgbUtq+CF8m/tmUs3DTjR2KDIAZnM lp6eXiC8mYayA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C214768AC0 for ; Sun, 14 Dec 2025 10:55:52 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734950; bh=kwsUquihrUSZxl8fvvOBzJ2MydYOh1tAnW8T/D2u4gQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oGBLpVC7sa7w+AUbTis4BZfnyz00582lfd4kfUU6XOzKcUPOvslrLeNuMiBu31qev M9mF0W+gCh8FxvYPNqm2vAieK0cnr/gXSGKqswhwv9RS+DINOT36haVgp7Q83Wd/Ci VvGiY9XXAg22bJQlg7eH9ZXC5BYEUjl2vHCgxGSVHo6wrrWxL51dXrWRhJI/IKVwqt nYvFVrXoSu9mjuQj4h7NhSPfC3+0d9eiuY17gFHkwIdV6rsqcpuokNHivKBWzSOvXN Nr0uX203rThti1Ad0s911AyWfnBosm4SKePQu90+t4Of4rvT0QjKLmPXdxBo4WfSFW CgBdU3J6AI/lA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 80BDB68A84; Sun, 14 Dec 2025 10:55:50 -0700 (MST) 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 tqGv9TApfTZo; Sun, 14 Dec 2025 10:55:50 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734946; bh=D1UJvzitjqxgNMv62mrsG53M87plpI5zky5IQRJztWE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LBhANKvrLpzaxc89AunXlnL0DHEwHA4UDRRAm2FwbLTHpahVxiHt27k4GR0fAF0AH HB8KChxgukoXm9gGSkVJ8xHbZwhZ2r8EcB5W2o1+Tt2Zj8S4avhErGYucpRtTRAwwj OvSFzaKkrGStIf8BVjV7mYGxmhfcHN03Fvt/pogD4tu0RAS5F0WA0Kzoa9F+SkyWpx MrWp8ylwiwPXsOyV+YhuxvxVIR/4cwM5o7AkgXyfI4DIE4Q+A364EvgIaiCBaGNqN1 xFDGKmg8rnR7pKpAtANSrJ+XBrhlXr6liICgRmMMtb5WdKLoPhScWsIOBnm9xfM9aQ 8ttUhUkHzrBRg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 212BA68A89; Sun, 14 Dec 2025 10:55:46 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:34 -0700 Message-ID: <20251214175449.3799539-13-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: PSSFVKLWQO5BYW537CIDERZ6J67QFZ7G X-Message-ID-Hash: PSSFVKLWQO5BYW537CIDERZ6J67QFZ7G 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: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 12/21] test: Add a macro to declare unit tests with arguments 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 Add a UNIT_TEST_ARGS() macro to declare and register a test with inline argument definitions. The variadic arguments use struct ut_arg_def and a NULL terminator is added automatically to the list. Example usage: static int my_test(struct unit_test_state *uts) { ... } UNIT_TEST_ARGS(my_test, UTF_CONSOLE, my_suite, { "path", UT_ARG_STR }, { "count", UT_ARG_INT, UT_ARGF_OPTIONAL, { .vint = 10 } }); Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- include/test/test.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/test/test.h b/include/test/test.h index 5ead1200a40..cb0539e3bdd 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -47,6 +47,7 @@ enum ut_arg_type { * * @name: Name of the argument (points to ut_arg_def.name) * @type: Type of the argument + * @provided: true if value was provided on command line * @vint: Integer value (when type is UT_ARG_INT) * @vbool: Boolean value (when type is UT_ARG_BOOL) * @vstr: String value (when type is UT_ARG_STR, points into argv) @@ -54,6 +55,7 @@ enum ut_arg_type { struct ut_arg { const char *name; enum ut_arg_type type; + bool provided; union { long vint; bool vbool; @@ -178,12 +180,14 @@ struct ut_arg_def { * @name: Name of test * @func: Function to call to perform test * @flags: Flags indicated pre-conditions for test + * @arg_defs: Argument definitions (NULL-terminated array), or NULL */ struct unit_test { const char *file; const char *name; int (*func)(struct unit_test_state *state); int flags; + const struct ut_arg_def *arg_defs; }; /** @@ -235,6 +239,33 @@ struct unit_test { .func = _name, \ } +/** + * UNIT_TEST_ARGS() - create unit test entry with inline argument definitions + * + * Like UNIT_TEST() but allows specifying argument definitions inline. + * The variadic arguments are struct ut_arg_def initializers. The NULL + * terminator is added automatically by the macro. + * + * Example: + * UNIT_TEST_ARGS(my_test, UTF_CONSOLE, my_suite, + * { "path", UT_ARG_STR }, + * { "count", UT_ARG_INT, UT_ARGF_OPTIONAL, { .vint = 10 } }); + * + * @_name: Test function name + * @_flags: Test flags (see enum ut_flags) + * @_suite: Test suite name + * @...: Argument definitions (struct ut_arg_def initializers) + */ +#define UNIT_TEST_ARGS(_name, _flags, _suite, ...) \ + static const struct ut_arg_def _name##_args[] = { __VA_ARGS__, { NULL } }; \ + ll_entry_declare(struct unit_test, _name, ut_ ## _suite) = { \ + .file = __FILE__, \ + .name = #_name, \ + .flags = _flags, \ + .func = _name, \ + .arg_defs = _name##_args, \ + } + /* Get the start of a list of unit tests for a particular suite */ #define UNIT_TEST_SUITE_START(_suite) \ ll_entry_start(struct unit_test, ut_ ## _suite) From patchwork Sun Dec 14 17:54:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 906 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=1765734957; bh=JaQB2xO/Q0Vv8B0t0sVQMFGIr+WoEGVhXutxcPYwBZw=; 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=D4Msd2x2W1kxodyJ2ybV0owbr6rkZqtZbIDC+k4ZAjud5OHOfW6ZWt50VkN9qNjuG /Srx4OMdOfjiDcpZHHGMnFF4wWQeXTkVuMPnN3zGUpDfzSN9tB/jm6Qie1eQoSz5dH mVTKQtcljVqZKnur0gIiriZfG7GqjBqnOtnxKFa52NoVS5Vl+87b+RutndOwWWsK1R O2UQf/GkbWNsz2w2rccOHRWwTmVYY9SS/nwBzjF/iMxArakfOGe6xO7ynPuOPFEBd7 KQTQhhP3MXIOITPwzJeyJfzWPr44IR/iESZPcEg/HHuTenvaSySLbnzuTyf4Spp82L XGlewjXubpGSQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 435BF68A96 for ; Sun, 14 Dec 2025 10:55:57 -0700 (MST) 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 ReNPpfrdDMBF for ; Sun, 14 Dec 2025 10:55:57 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734957; bh=JaQB2xO/Q0Vv8B0t0sVQMFGIr+WoEGVhXutxcPYwBZw=; 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=D4Msd2x2W1kxodyJ2ybV0owbr6rkZqtZbIDC+k4ZAjud5OHOfW6ZWt50VkN9qNjuG /Srx4OMdOfjiDcpZHHGMnFF4wWQeXTkVuMPnN3zGUpDfzSN9tB/jm6Qie1eQoSz5dH mVTKQtcljVqZKnur0gIiriZfG7GqjBqnOtnxKFa52NoVS5Vl+87b+RutndOwWWsK1R O2UQf/GkbWNsz2w2rccOHRWwTmVYY9SS/nwBzjF/iMxArakfOGe6xO7ynPuOPFEBd7 KQTQhhP3MXIOITPwzJeyJfzWPr44IR/iESZPcEg/HHuTenvaSySLbnzuTyf4Spp82L XGlewjXubpGSQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2E63F68ADF for ; Sun, 14 Dec 2025 10:55:57 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734955; bh=dkMe7uAhjYOv8pW/l5Eqx/SHmaELk6r4/ggg6+AfLqU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HWYCtXG22vuZIkAMD5zc4feYl7pSeHyn/fk7qudaUEeH9gwW539bA8AYYXU71ijyQ yKuduXf1bnepu9IS2RHD1SDVK5uEogF+c3xTTbuBSy7vT/oE8ugcY00GhnIOQp4Il4 qYHrp/fjtf6/iYX0iROUOzC3RYEfLN3I7MYWvYtgegLgRJrVDw0cIFfuE4uYF/G9sy bAbSDaypT3P8jWe7hrPtCWNeUcwdM5tBBR8h//CMzM/FIOhxbKKd2AtIPxlEaY7hLd kJEfFt2K4F5FB2athowfTlixspaJ5TA1BeoucQCFKbcFC1bInWlk2fap8oxpiUaLh0 Gutoxx3dmX6yg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3403C68A91; Sun, 14 Dec 2025 10:55:55 -0700 (MST) 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 QisGQ7I14cBd; Sun, 14 Dec 2025 10:55:55 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734951; bh=JqpN1v2Tki4WFot9SBddjhSh1QpbpSr/eaBQ6n7E/ig=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oTTcqZrAH/jFVXfNgVIfGCVylSK08IPYeKRBKS1bYlC/PMGwmx099XgwiynVDQKCY AxXd4OjIcMqQtRYLLVTlt1BgG0fx/fCCaesA29bxLVzR2BrjHXDpwi3tL0pYJM7ty6 5rjv8Lj4YjCQ3Mg9JCL7yNaeq4hOCLJfvXXLwxe6A5Q6xU/5yi9mKhg2Qvamcb+Z5C LUIzNhwzRV701ILodOqVuIsoEhf5wbrXlwncuavPgWMWwGU25H+UEuayKDJfYRUcAB wm/IokPaSQAML06GJp+5CHRrQipRTJCgBQy3/demt+U1tpccpvXRpWwClCwQeWEepY qRM6/hTMS+xUA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id C240468A89; Sun, 14 Dec 2025 10:55:50 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:35 -0700 Message-ID: <20251214175449.3799539-14-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: BGSSZCPJXYUKQYS4OHL5WRUPKNACKQSY X-Message-ID-Hash: BGSSZCPJXYUKQYS4OHL5WRUPKNACKQSY 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: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 13/21] test: Add support for passing arguments to C tests 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 Add support for passing key=value arguments to unit tests. The test framework parses arguments based on definitions provided by each test and makes them available via uts->args[] For now the 'ut' command does not support this new feature. Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- arch/sandbox/cpu/spl.c | 3 +- include/test/test.h | 6 ++ include/test/ut.h | 4 +- test/cmd_ut.c | 3 +- test/test-main.c | 169 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 178 insertions(+), 7 deletions(-) diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 7ee4975523e..162b678314e 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -152,7 +152,8 @@ void spl_board_init(void) ut_init_state(&uts); ret = ut_run_list(&uts, "spl", NULL, tests, count, - state->select_unittests, 1, false, NULL); + state->select_unittests, 1, false, NULL, + 0, NULL); ut_report(&uts.cur, 1); ut_uninit_state(&uts); /* continue execution into U-Boot */ diff --git a/include/test/test.h b/include/test/test.h index cb0539e3bdd..da38b8ee4f0 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -9,6 +9,8 @@ #include #include +#define UT_MAX_ARGS 8 + /** * struct ut_stats - Statistics about tests run * @@ -90,6 +92,8 @@ struct ut_arg { * @soft_fail: continue execution of the test even after it fails * @expect_str: Temporary string used to hold expected string value * @actual_str: Temporary string used to hold actual string value + * @args: Parsed argument values for current test + * @arg_count: Number of parsed arguments */ struct unit_test_state { struct ut_stats cur; @@ -116,6 +120,8 @@ struct unit_test_state { bool soft_fail; char expect_str[1024]; char actual_str[1024]; + struct ut_arg args[UT_MAX_ARGS]; + int arg_count; }; /* Test flags for each test */ diff --git a/include/test/ut.h b/include/test/ut.h index 7098c9be7d6..90b9bf79929 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -618,12 +618,14 @@ void ut_uninit_state(struct unit_test_state *uts); * name is the name of the test to run. This is used to find which test causes * another test to fail. If the one test fails, testing stops immediately. * Pass NULL to disable this + * @argc: Number of test arguments (key=value pairs), 0 if none + * @argv: Test argument array, NULL if none * Return: 0 if all tests passed, -1 if any failed */ int ut_run_list(struct unit_test_state *uts, const char *category, const char *prefix, struct unit_test *tests, int count, const char *select_name, int runs_per_test, bool force_run, - const char *test_insert); + const char *test_insert, int argc, char *const argv[]); /** * ut_report() - Report stats on a test run diff --git a/test/cmd_ut.c b/test/cmd_ut.c index d8b3c325c41..bad123a75fd 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -132,7 +132,8 @@ static int run_suite(struct unit_test_state *uts, struct suite *ste, snprintf(prefix, sizeof(prefix), "%s_test_", ste->name); ret = ut_run_list(uts, ste->name, prefix, ste->start, n_ents, - select_name, runs_per_test, force_run, test_insert); + select_name, runs_per_test, force_run, test_insert, + 0, NULL); return ret; } diff --git a/test/test-main.c b/test/test-main.c index 941b883e156..ac5680d77d0 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -89,6 +89,154 @@ void ut_uninit_state(struct unit_test_state *uts) } } +/** + * ut_count_args() - Count the number of arguments in a NULL-terminated array + * + * @defs: Argument definitions array (NULL-terminated) + * Return: Number of arguments + */ +static int ut_count_args(const struct ut_arg_def *defs) +{ + int count = 0; + + if (defs) { + while (defs[count].name) + count++; + } + + return count; +} + +/** + * ut_set_arg() - Find and set an argument value + * + * Search through argument definitions to find a matching key and set its value. + * + * @defs: Argument definitions array + * @args: Argument values array to update + * @count: Number of argument definitions + * @key: Key name to search for + * @key_len: Length of key name + * @val: Value string to parse + * Return: true if argument was found and set, false otherwise + */ +static bool ut_set_arg(const struct ut_arg_def *defs, struct ut_arg *args, + int count, const char *key, int key_len, const char *val) +{ + int j; + + for (j = 0; j < count; j++) { + if (strlen(defs[j].name) == key_len && + !strncmp(defs[j].name, key, key_len)) { + switch (defs[j].type) { + case UT_ARG_INT: + args[j].vint = simple_strtol(val, NULL, 0); + break; + case UT_ARG_BOOL: + args[j].vbool = *val == '1'; + break; + case UT_ARG_STR: + args[j].vstr = val; + break; + } + args[j].provided = true; + return true; + } + } + + return false; +} + +/** + * ut_parse_args() - Parse command-line arguments for a test + * + * Parse key=value arguments from the command line and set up uts->args based on + * the test's argument definitions. + * + * @uts: Unit test state (args and arg_count will be set) + * @test: Test being run (provides arg_defs) + * @argc: Number of arguments + * @argv: Argument array (key=value strings) + * Return: 0 on success, -EINVAL on parse error + */ +static int ut_parse_args(struct unit_test_state *uts, struct unit_test *test, + int argc, char *const argv[]) +{ + const struct ut_arg_def *defs = test->arg_defs; + struct ut_arg *args = uts->args; + int count = ut_count_args(defs); + int i; + + uts->arg_count = 0; + + /* No arguments expected */ + if (!count) { + if (argc > 0) { + printf("Test '%s' does not accept arguments\n", + test->name); + return -EINVAL; + } + return 0; + } + + if (count > UT_MAX_ARGS) { + printf("Test '%s' has too many arguments (%d > %d)\n", + test->name, count, UT_MAX_ARGS); + return -EINVAL; + } + + /* Initialise from defaults */ + for (i = 0; i < count; i++) { + args[i].name = defs[i].name; + args[i].type = defs[i].type; + args[i].provided = false; + switch (defs[i].type) { + case UT_ARG_INT: + args[i].vint = defs[i].def.vint; + break; + case UT_ARG_BOOL: + args[i].vbool = defs[i].def.vbool; + break; + case UT_ARG_STR: + args[i].vstr = defs[i].def.vstr; + break; + } + } + + /* Parse command-line key=value pairs */ + for (i = 0; i < argc; i++) { + const char *arg = argv[i]; + const char *eq = strchr(arg, '='); + int key_len; + + if (!eq) { + printf("Invalid argument '%s' (expected key=value)\n", + arg); + return -EINVAL; + } + key_len = eq - arg; + + if (!ut_set_arg(defs, args, count, arg, key_len, eq + 1)) { + printf("Unknown argument '%.*s' for test '%s'\n", + key_len, arg, test->name); + return -EINVAL; + } + } + + /* Check required arguments are provided */ + for (i = 0; i < count; i++) { + if (!args[i].provided && !(defs[i].flags & UT_ARGF_OPTIONAL)) { + printf("Missing required argument '%s' for test '%s'\n", + defs[i].name, test->name); + return -EINVAL; + } + } + + uts->arg_count = count; + + return 0; +} + /** * dm_test_pre_run() - Get ready to run a driver model test * @@ -593,12 +741,15 @@ static int ut_run_test_live_flat(struct unit_test_state *uts, * @test_insert: String describing a test to run after n other tests run, in the * format n:name where n is the number of tests to run before this one and * name is the name of the test to run + * @argc: Number of test arguments (key=value pairs) + * @argv: Test argument array * Return: 0 if all tests passed, -ENOENT if test @select_name was not found, * -EBADF if any failed */ static int ut_run_tests(struct unit_test_state *uts, const char *prefix, struct unit_test *tests, int count, - const char *select_name, const char *test_insert) + const char *select_name, const char *test_insert, + int argc, char *const argv[]) { int prefix_len = prefix ? strlen(prefix) : 0; struct unit_test *test, *one; @@ -654,6 +805,11 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix, uts->cur.test_count++; if (one && upto == pos) { + ret = ut_parse_args(uts, one, argc, argv); + if (ret) { + uts->cur.fail_count++; + return ret; + } ret = ut_run_test_live_flat(uts, one, NULL); if (uts->cur.fail_count != old_fail_count) { printf("Test '%s' failed %d times (position %d)\n", @@ -667,6 +823,12 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix, if (prefix_len && !strncmp(test_name, prefix, prefix_len)) test_name = test_name + prefix_len; + ret = ut_parse_args(uts, test, argc, argv); + if (ret) { + found++; + uts->cur.fail_count++; + continue; + } for (i = 0; i < uts->runs_per_test; i++) ret = ut_run_test_live_flat(uts, test, test_name); if (uts->cur.fail_count != old_fail_count) { @@ -706,9 +868,8 @@ void ut_report(struct ut_stats *stats, int run_count) int ut_run_list(struct unit_test_state *uts, const char *category, const char *prefix, struct unit_test *tests, int count, const char *select_name, int runs_per_test, bool force_run, - const char *test_insert) + const char *test_insert, int argc, char *const argv[]) { - ; bool was_bypassed, has_dm_tests = false; ulong start_offset = 0; ulong test_offset = 0; @@ -751,7 +912,7 @@ int ut_run_list(struct unit_test_state *uts, const char *category, uts->force_run = force_run; was_bypassed = pager_set_test_bypass(gd_pager(), true); ret = ut_run_tests(uts, prefix, tests, count, select_name, - test_insert); + test_insert, argc, argv); pager_set_test_bypass(gd_pager(), was_bypassed); /* Best efforts only...ignore errors */ From patchwork Sun Dec 14 17:54:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 907 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=1765734959; bh=Z632tXGVlwt8eOeraTN8UISECp+J4y/x/+tAHjgvSi4=; 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=RXi2DHPMKneKx9IXGGhjQjwMN5RNCJYCS3+EVUG+9EG2Gp+GmuF9jNj8vtpMcmSg8 lR6og/cKlcP1ssK4Shui0aJ16q98q30SlBepOAb0z2ZHwP6+toqZQKTFdGM2o//Jx5 PCm5Vxki6cc/qrJUyW3R5RG6xDA4iEhwzJYPphww0u77uUmO/F9IkI17sAGFcdOnlH x0OlJ9vM6S1mRHtxkLGOFUBE9ID3OKJT8eD1B1NxZBX2DSIoCqgj3IG7exeVl+soWn 5AQVezz9nXPRj1kogLRSNkDHLNBgmhLblr4rdwUsRXvui11GYL2T6yZkSQQEaKz44t +7wmJE4lUyDhA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A311D68A92 for ; Sun, 14 Dec 2025 10:55:59 -0700 (MST) 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 U_S_-mS_QKvd for ; Sun, 14 Dec 2025 10:55:59 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734958; bh=Z632tXGVlwt8eOeraTN8UISECp+J4y/x/+tAHjgvSi4=; 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=uTg77ZyK40PbRYJG1ecFRj2v0v/8opAVcZbRHX8nlxixeew5Kr65sKoEV0d3qFy5q dN4wm57g+RSf6rzdO+2iCTuOaNTPryUl+gITycPvNeMNfjdQDYEuT/Qxi7WmYOc82Y Z5TgqwqltmeLFNncGHO75GmrCefgsipeKEALqY7ZvXkdmqRrfhl8j1u3l110ijhGV9 INIwODdl8avH0CKbx7P+fca7/rOxSUGd2yNbRdl0VnarfRXeDNws2xh+Anug/XcaKt g85IteVp1l53NFzz827w8q4ek/uYASSR3ZDEoGE0gXAEtxN+9ttK1fnq+qkxWN7H/U X8diVXYwlbC/g== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 159E968A84 for ; Sun, 14 Dec 2025 10:55:58 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734956; bh=nsJpdnM1toGFl7UjcBtX5zqwQdrNvOVwkHPY6kToQvY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QsZN54IJr4VHUxKRtlaYoF8B/sqA8CWeQx/mVYSSD5PfU2tXlIkXTHxnFBTQFKNFn ObWwt7CXcXQrzdi1FjU6a8SD33oZN3SVQqVCO9GIIjyQCJFdGkmuLvRsyrZUFlzA2k aENdKwqgh5imYKio7pkOBfQouLL1rVs8db6ERZAohtuDiGtcG2WbZaxjIGkJEimyh2 DsLJ9K9P3gYjlBNuxKdccns7r0S11UmdXlXmxSPWbQ1EKD0jJH8RfE/CiiVruUpE9p HXsB6fibQCVw95+lJVjCfCkiQD67KAK/ADPIj2yAB4TxoAkX3vgaFcUKQFpy4KZqTF zIaC2JVmAm70A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2451168A92; Sun, 14 Dec 2025 10:55:56 -0700 (MST) 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 6lzzNUw0DpCS; Sun, 14 Dec 2025 10:55:56 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734955; bh=G5zN5/q5fAf1MTwn+L1K/8YttPid2/EcxepHgyx9W7U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d9PvaTJ5Sjy6MJS5n6A/Qju15yj51p2rXxHyAc4CcCQ/2FOMRUabBRScMBbDfNZE6 AOZ69gSM5K+SK62f1G+NLR+bTqpoMw26yW3fZQI1atN6Xg5ph95FfhjenXC+fC+ZLk /pd+zyoVMQnPCS4Rdd87qgtBt0+9ewxn5WAOFYszSdTLb+0MfinKJE7H3rqTscdgeH 7T3Y35lULSMR7uqja8z1JdYQDcazwZnj5v2HYXAQpr4ShvCWnV4/RJ95L5KBb3HP13 Tvo8KUEyywD+zhtDLXIHUrJzymXXFeFkQILPW/UeYCp9ebeQM0H8DM/ROyv5C+pQL/ Cr2OcpvoqTlpA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 7401C68A89; Sun, 14 Dec 2025 10:55:55 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:36 -0700 Message-ID: <20251214175449.3799539-15-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: FW5I3PCTENXTTDZJP76LZLY4SBMTWXRO X-Message-ID-Hash: FW5I3PCTENXTTDZJP76LZLY4SBMTWXRO 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: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 14/21] test: Enhance the ut command to pass test arguments 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 Update the ut command to permit passing arguments to tests. Usage: ut -f fs test_name key1=value1 key2=value2 Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- doc/usage/cmd/ut.rst | 11 ++++++++++- test/cmd_ut.c | 29 ++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/doc/usage/cmd/ut.rst b/doc/usage/cmd/ut.rst index 1acf3126680..d8c3cbf496c 100644 --- a/doc/usage/cmd/ut.rst +++ b/doc/usage/cmd/ut.rst @@ -11,7 +11,7 @@ Synopsis :: - ut [-r] [-f] [-I:] [-r] [ | 'all' []] + ut [-r] [-f] [-I:] [ | all []] [...] ut [-s] info Description @@ -37,6 +37,11 @@ test causes another test to fail. If the one test fails, testing stops immediately. +args + Optional arguments to pass to the test, in `name=value` format. These are + used by tests declared with `UNIT_TEST_ARGS()` which define expected + argument names and types. + Typically the command is run on :ref:`arch/sandbox/sandbox:sandbox` since it includes a near-complete set of emulators, no code-size limits, many CONFIG options enabled and runs easily in CI without needing QEMU. It is also possible @@ -201,3 +206,7 @@ Run a selection of three suites:: Tests run: 10, 12 ms, average: 1 ms, failures: 0 Suites run: 3, total tests run: 37, 26 ms, average: 0 ms, failures: 0 Average test time: 0 ms, worst case 'mem' took 1 ms + +Run a test with arguments (used by tests declared with UNIT_TEST_ARGS):: + + => ut -f fs fs_test_ls_norun fs_type=ext4 fs_image=/tmp/img small=1MB.file diff --git a/test/cmd_ut.c b/test/cmd_ut.c index bad123a75fd..adc96fcbcdc 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -30,7 +30,7 @@ struct suite { static int do_ut_all(struct unit_test_state *uts, const char *select_name, int runs_per_test, bool force_run, - const char *test_insert); + const char *test_insert, int argc, char *const argv[]); static int do_ut_info(bool show_suites); @@ -122,7 +122,7 @@ static bool has_tests(struct suite *ste) /** run_suite() - Run a suite of tests */ static int run_suite(struct unit_test_state *uts, struct suite *ste, const char *select_name, int runs_per_test, bool force_run, - const char *test_insert) + const char *test_insert, int argc, char *const argv[]) { int n_ents = ste->end - ste->start; char prefix[30]; @@ -133,7 +133,7 @@ static int run_suite(struct unit_test_state *uts, struct suite *ste, ret = ut_run_list(uts, ste->name, prefix, ste->start, n_ents, select_name, runs_per_test, force_run, test_insert, - 0, NULL); + argc, argv); return ret; } @@ -169,7 +169,8 @@ static void update_stats(struct unit_test_state *uts, const struct suite *ste) } static int do_ut_all(struct unit_test_state *uts, const char *select_name, - int runs_per_test, bool force_run, const char *test_insert) + int runs_per_test, bool force_run, const char *test_insert, + int argc, char *const argv[]) { int i; int retval; @@ -181,7 +182,7 @@ static int do_ut_all(struct unit_test_state *uts, const char *select_name, if (has_tests(ste)) { printf("----Running %s tests----\n", ste->name); retval = run_suite(uts, ste, select_name, runs_per_test, - force_run, test_insert); + force_run, test_insert, argc, argv); if (!any_fail) any_fail = retval; update_stats(uts, ste); @@ -246,6 +247,8 @@ static struct suite *find_suite(const char *name) static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { const char *test_insert = NULL, *select_name; + int test_argc; + char *const *test_argv; struct unit_test_state uts; bool show_suites = false; bool force_run = false; @@ -287,9 +290,14 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ut_init_state(&uts); name = argv[0]; select_name = cmd_arg1(argc, argv); + + /* Test arguments are after suite name and test name */ + test_argc = argc > 2 ? argc - 2 : 0; + test_argv = argc > 2 ? argv + 2 : NULL; + if (!strcmp(name, "all")) { ret = do_ut_all(&uts, select_name, runs_per_text, force_run, - test_insert); + test_insert, test_argc, test_argv); } else if (!strcmp(name, "info")) { ret = do_ut_info(show_suites); } else { @@ -308,7 +316,8 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } ret = run_suite(&uts, ste, select_name, runs_per_text, - force_run, test_insert); + force_run, test_insert, test_argc, + test_argv); if (!any_fail) any_fail = ret; update_stats(&uts, ste); @@ -324,12 +333,14 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } U_BOOT_LONGHELP(ut, - "[-rs] [-f] [-I:][] - run unit tests\n" + "[-rs] [-f] [-I:] [ [...]] - run unit tests\n" " -r Number of times to run each test\n" " -f Force 'manual' tests to run as well\n" " -I Test to run after other tests have run\n" " -s Show all suites with ut info\n" - " Comma-separated list of suites to run\n" + " Test suite to run (or comma-separated list)\n" + " Specific test to run (optional)\n" + " Test arguments as key=value pairs (optional)\n" "\n" "Options for :\n" "all - execute all enabled tests\n" From patchwork Sun Dec 14 17:54:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 908 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=1765734963; bh=UvBU4wMutMuImQVNsKG7ueKPPkwmjmQSemgW4dAcYe4=; 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=CSNvEPeWCvx/Rn7krG2Pl+LQUa5sWimxqvzeSIAsi+BBV4sEuciGM4lc5/FWyayQ9 h5sTAuzMPIk3LQuMqeeR8Jb441KUMSSW/Y4XIZr/gzPQO/3THvt4lrFf1/XfkoDrFy p0Q/uo855ukF5GbiinJhYedKnMWLwCIxd5eG6pGiq1IcVFenqELM/ReADcibgxVzW1 n8ZDTWBSXmfcxnrz2YwLvtzq8DIx5bkz+hekPWpnlBF3qhEP66ljMKoP0vL0CFSck/ Zcx1C/52c+rWCaLJyirjJHc5bMMvuH0f1UTkREqLITmxm+Ii9Rg+tL0IMiVVQn7G2K tNJZzm7JN66NQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 93B0668AEA for ; Sun, 14 Dec 2025 10:56:03 -0700 (MST) 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 1YVSmnsIW9j4 for ; Sun, 14 Dec 2025 10:56:03 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734963; bh=UvBU4wMutMuImQVNsKG7ueKPPkwmjmQSemgW4dAcYe4=; 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=CSNvEPeWCvx/Rn7krG2Pl+LQUa5sWimxqvzeSIAsi+BBV4sEuciGM4lc5/FWyayQ9 h5sTAuzMPIk3LQuMqeeR8Jb441KUMSSW/Y4XIZr/gzPQO/3THvt4lrFf1/XfkoDrFy p0Q/uo855ukF5GbiinJhYedKnMWLwCIxd5eG6pGiq1IcVFenqELM/ReADcibgxVzW1 n8ZDTWBSXmfcxnrz2YwLvtzq8DIx5bkz+hekPWpnlBF3qhEP66ljMKoP0vL0CFSck/ Zcx1C/52c+rWCaLJyirjJHc5bMMvuH0f1UTkREqLITmxm+Ii9Rg+tL0IMiVVQn7G2K tNJZzm7JN66NQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8296B68A96 for ; Sun, 14 Dec 2025 10:56:03 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734961; bh=K1MyuAhTnWuNehMmYfh2RTEf+OnXxfw+tLol2FyGxqI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hzFkj1ECJqkPlzdQen0mYBl72krEuXbBr+p9rfbkH+hJFvaWL05tw4/TB/GxsHjJq qxLFtw3JnKD3a5AGmyolQAASc4mc+OktxaSB66jrwkGBzLLYV/lAxn4NLsorDjQ/Td SLGlxeXxleZALCUiniyDPKcmJc7HQCWZqiASYUlnrsxQ9M3c4+GxQjT2Eh72sSjto/ GWW4SYdJaEHMwqOXESbz2W7He+0O0lPi7NzbO0d+dFNg3hKDFlZthtfIOm1z9NEOV3 QhxxA6Cm6T4tRtK8zzxAa7MWPZqSisGnPa7bt44FYPvQhJNVJP24e98v8whjiGxBcn hYw0lcIEmVwRg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DE8BE68A92; Sun, 14 Dec 2025 10:56:01 -0700 (MST) 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 iaVpSm2vEPrV; Sun, 14 Dec 2025 10:56:01 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734956; bh=4jFrpVZmvyDWcHdfMTEo+3mZvY/FXzvrerR6IKRcBwU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tspHB2eTvvkM+JZ4v/AOgIUyfTIsXJDVs+y6RH+GkonhP2Gwjo5I3T8q0QDswDuPG UtlB79diLYNBk7XabDAcXApjloXWMwjUWJKUfH0+r5XtV6tz7Tlimt6S9lpAN9U+O6 OlqZYVHdPa8YFM1u7ZkiluxNjUCcKwKDxyHvwC78EjAuD8IAklxdN0QrBAL/zsjnRk 9j8gIN7GQB0CdvVEoxHYHcItAZoHIaod6btYYjCXsCN3kKdxWtIn1PYRslzimkCnwG J2uOyiTdRkR5qKeaY06Qvmsdzg2nfz2laFnpyWX7ND+EPPzIpPmC2CZaXiU6WTG+EB UZug06CRJS/RQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 675C768A89; Sun, 14 Dec 2025 10:55:56 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:37 -0700 Message-ID: <20251214175449.3799539-16-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 47QDEIXDIQJQLOWO5TFXOK3GMO24WAS5 X-Message-ID-Hash: 47QDEIXDIQJQLOWO5TFXOK3GMO24WAS5 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 15/21] test: Add type-checked argument accessor functions 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 Add ut_get_str(), ut_get_int(), and ut_get_bool() functions with corresponding ut_str(), ut_int(), and ut_bool() macros for accessing test arguments with type checking. These functions check that the argument index is within bounds and the type matches what was requested. The first failure for a test is reported via ut_failf() which should make it fairly easy to debug the test. Co-developed-by: Claude Signed-off-by: Simon Glass --- include/test/test.h | 2 ++ include/test/ut.h | 50 ++++++++++++++++++++++++++++++++++ test/test-main.c | 1 + test/ut.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+) diff --git a/include/test/test.h b/include/test/test.h index da38b8ee4f0..15ed8b37890 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -94,6 +94,7 @@ struct ut_arg { * @actual_str: Temporary string used to hold actual string value * @args: Parsed argument values for current test * @arg_count: Number of parsed arguments + * @arg_error: Set if ut_str/int/bool() detects a type mismatch */ struct unit_test_state { struct ut_stats cur; @@ -122,6 +123,7 @@ struct unit_test_state { char actual_str[1024]; struct ut_arg args[UT_MAX_ARGS]; int arg_count; + bool arg_error; }; /* Test flags for each test */ diff --git a/include/test/ut.h b/include/test/ut.h index 90b9bf79929..4a9a401cf48 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -635,4 +635,54 @@ int ut_run_list(struct unit_test_state *uts, const char *category, */ void ut_report(struct ut_stats *stats, int run_count); +/** + * ut_get_str() - Get a string test argument + * + * Fails the test if the argument type is not UT_ARG_STR. + * + * @uts: Test state + * @n: Argument index + * @file: Filename of caller + * @line: Line number of caller + * @func: Function name of caller + * Return: String value, or NULL if type mismatch + */ +const char *ut_get_str(struct unit_test_state *uts, int n, const char *file, + int line, const char *func); + +/** + * ut_get_int() - Get an integer test argument + * + * Fails the test if the argument type is not UT_ARG_INT. + * + * @uts: Test state + * @n: Argument index + * @file: Filename of caller + * @line: Line number of caller + * @func: Function name of caller + * Return: Integer value, or 0 if type mismatch + */ +long ut_get_int(struct unit_test_state *uts, int n, const char *file, + int line, const char *func); + +/** + * ut_get_bool() - Get a boolean test argument + * + * Fails the test if the argument type is not UT_ARG_BOOL. + * + * @uts: Test state + * @n: Argument index + * @file: Filename of caller + * @line: Line number of caller + * @func: Function name of caller + * Return: Boolean value, or false if type mismatch + */ +bool ut_get_bool(struct unit_test_state *uts, int n, const char *file, + int line, const char *func); + +/* Helpers for accessing test arguments with type checking */ +#define ut_str(n) ut_get_str(uts, n, __FILE__, __LINE__, __func__) +#define ut_int(n) ut_get_int(uts, n, __FILE__, __LINE__, __func__) +#define ut_bool(n) ut_get_bool(uts, n, __FILE__, __LINE__, __func__) + #endif diff --git a/test/test-main.c b/test/test-main.c index ac5680d77d0..c9e164da678 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -639,6 +639,7 @@ static int ut_run_test(struct unit_test_state *uts, struct unit_test *test, if (ret) return ret; + uts->arg_error = false; ret = test->func(uts); if (ret == -EAGAIN) skip_test(uts); diff --git a/test/ut.c b/test/ut.c index aed59cae0b9..fe9a177ab53 100644 --- a/test/ut.c +++ b/test/ut.c @@ -295,3 +295,69 @@ void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays) state_set_skip_delays(skip_delays); #endif } + +const char *ut_get_str(struct unit_test_state *uts, int n, const char *file, + int line, const char *func) +{ + if (n < 0 || n >= uts->arg_count) { + if (!uts->arg_error) + ut_failf(uts, file, line, func, "ut_str() arg check", + "arg %d is invalid (arg_count=%d)", n, + uts->arg_count); + uts->arg_error = true; + return NULL; + } + if (uts->args[n].type != UT_ARG_STR) { + if (!uts->arg_error) + ut_failf(uts, file, line, func, "ut_str() type check", + "arg %d is not a string", n); + uts->arg_error = true; + return NULL; + } + + return uts->args[n].vstr; +} + +long ut_get_int(struct unit_test_state *uts, int n, const char *file, + int line, const char *func) +{ + if (n < 0 || n >= uts->arg_count) { + if (!uts->arg_error) + ut_failf(uts, file, line, func, "ut_int() arg check", + "arg %d is invalid (arg_count=%d)", n, + uts->arg_count); + uts->arg_error = true; + return 0; + } + if (uts->args[n].type != UT_ARG_INT) { + if (!uts->arg_error) + ut_failf(uts, file, line, func, "ut_int() type check", + "arg %d is not an int", n); + uts->arg_error = true; + return 0; + } + + return uts->args[n].vint; +} + +bool ut_get_bool(struct unit_test_state *uts, int n, const char *file, + int line, const char *func) +{ + if (n < 0 || n >= uts->arg_count) { + if (!uts->arg_error) + ut_failf(uts, file, line, func, "ut_bool() arg check", + "arg %d is invalid (arg_count=%d)", n, + uts->arg_count); + uts->arg_error = true; + return false; + } + if (uts->args[n].type != UT_ARG_BOOL) { + if (!uts->arg_error) + ut_failf(uts, file, line, func, "ut_bool() type check", + "arg %d is not a bool", n); + uts->arg_error = true; + return false; + } + + return uts->args[n].vbool; +} From patchwork Sun Dec 14 17:54:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 909 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=1765734968; bh=KBDeXJrXl/rz3yUTmBiRMPCah2aXIEpxYdTm6yIeEgk=; 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=D17ytoCw4cf3xkJo/11xdnd3q8sZyc+pLUpadqPUh2aqnvimahxDgvn2/7dtA1LY/ iwqbzNZF0zp3OljZe3gBcmRTqZlj9KyxOEYw2XzF98OxGZS8v7JYH21dc/SoxXiIBT giwOyY4wiSwZi8fv9nSRpxiWPFpaX9o3FVHwhrcePtFetIl9NzTf5awIvDw/9z5ag6 nelIE7I1dgaY4NfbHIepoDMn93L3Nqn0XDGgPuxK5tJCktl5uXJau4AHLTx3qvMooX gBo5BVmmaoo72HmCFlUmBIXagxmnY+tivc/1RONu7WNFn7IU27UT3g2Dc1ODNLtDLF T2Nk3j0yf0zig== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1246168ADF for ; Sun, 14 Dec 2025 10:56:08 -0700 (MST) 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 MYf8aEVTdApn for ; Sun, 14 Dec 2025 10:56:08 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734968; bh=KBDeXJrXl/rz3yUTmBiRMPCah2aXIEpxYdTm6yIeEgk=; 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=D17ytoCw4cf3xkJo/11xdnd3q8sZyc+pLUpadqPUh2aqnvimahxDgvn2/7dtA1LY/ iwqbzNZF0zp3OljZe3gBcmRTqZlj9KyxOEYw2XzF98OxGZS8v7JYH21dc/SoxXiIBT giwOyY4wiSwZi8fv9nSRpxiWPFpaX9o3FVHwhrcePtFetIl9NzTf5awIvDw/9z5ag6 nelIE7I1dgaY4NfbHIepoDMn93L3Nqn0XDGgPuxK5tJCktl5uXJau4AHLTx3qvMooX gBo5BVmmaoo72HmCFlUmBIXagxmnY+tivc/1RONu7WNFn7IU27UT3g2Dc1ODNLtDLF T2Nk3j0yf0zig== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 010EE68A92 for ; Sun, 14 Dec 2025 10:56:08 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734966; bh=Hkb5D380grelXrbUtYk+0vzURG7EHF+krdai609dgWw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=upHIUOFZ7gRVivoRP2eW/6V+UA/BVpZFh65wDUIyx1H18YhBGXtyNlnPRS1qYiyh/ eLI1XgpPQyH0EAnXu0sHaX1uS1x6o8f7aozN4+wA6e9PpudyE0URMNg+Poam8/v1J3 wen5Lup0DxJU+fzcLskHtK6RF6cqdZhv7Go+v6DIJ9GXwrVMoopzDgQb/5hvssCqP9 ThY8sVNyJ286ALrmOE9ImqBmvPOIIt/N/h0ofbMYzH1yXIJBf9e3XzmlzAQhHOz3J9 SJvauDijhOrZohbr013HGuSjWoAREgIg5eCKBqq9HfMtdYiGe6wbw7czBohLYU5vhM WUayuF2ukp12Q== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id F40CD68A92; Sun, 14 Dec 2025 10:56:05 -0700 (MST) 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 4VzixJhw8HDU; Sun, 14 Dec 2025 10:56:05 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734961; bh=Zh09Q4c87syBNRrze7xWGyCss3cMdMIwYlLgW230AZE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CnaqltO52jI7VVkXvvBurHxzfCbp1izAmeQ/dUtTAMROv3gPBvsOFUx4mgeGOa+3R gObp0ShR88j3DkwZQoD+osJUzQJX0p8zGAymgCaf8AWQMhmdojrq7lJbNBwNO0i9ja /PsGF7gpQKHwXsWnIgsvw0v2jNmb5iAAU26Up1d2J7dxNCgh4gPC5YccJbOdUQ5dfX 2KGcZgez6vuqXq9lGCn7wnBy+wdjjumHRiCZwemsc5Y3oKiD/Nqxe6IbEAfWxtujzY wcq3EvjK9yJHRh2PtTMtMfo197XhylTEZQWExjaIRVmL1zg0in9QatO+KiRJZ/OGOw +oKa0bEoYSZCQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 114A268A84; Sun, 14 Dec 2025 10:56:01 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:38 -0700 Message-ID: <20251214175449.3799539-17-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: BTFTTXPPWGMP5JSHQZ3SINQZI4HQ555M X-Message-ID-Hash: BTFTTXPPWGMP5JSHQZ3SINQZI4HQ555M 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 16/21] test: Add a private buffer for tests 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 Add a priv[] buffer to struct unit_test_state that tests can use for their own data. This avoids the need to allocate memory or use global variables for test-specific state. Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/tests_writing.rst | 14 ++++++++++++++ include/test/test.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst index 41612a9e21b..6842533e2c6 100644 --- a/doc/develop/tests_writing.rst +++ b/doc/develop/tests_writing.rst @@ -486,6 +486,20 @@ ut_check_delta(last) Return the change in free memory since ``last`` was obtained from ``ut_check_free()``. A positive value means more memory has been allocated. +Private buffer +~~~~~~~~~~~~~~ + +Each test has access to a private buffer ``uts->priv`` (256 bytes) for temporary +data. This avoids the need to allocate memory or use global variables:: + + static int my_test(struct unit_test_state *uts) + { + snprintf(uts->priv, sizeof(uts->priv), "/%s", filename); + /* use uts->priv as a path string */ + + return 0; + } + Writing Python tests -------------------- diff --git a/include/test/test.h b/include/test/test.h index 15ed8b37890..2facf5b3675 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -10,6 +10,7 @@ #include #define UT_MAX_ARGS 8 +#define UT_PRIV_SIZE 256 /** * struct ut_stats - Statistics about tests run @@ -95,6 +96,7 @@ struct ut_arg { * @args: Parsed argument values for current test * @arg_count: Number of parsed arguments * @arg_error: Set if ut_str/int/bool() detects a type mismatch + * @priv: Private data for tests to use as needed */ struct unit_test_state { struct ut_stats cur; @@ -124,6 +126,7 @@ struct unit_test_state { struct ut_arg args[UT_MAX_ARGS]; int arg_count; bool arg_error; + char priv[UT_PRIV_SIZE]; }; /* Test flags for each test */ From patchwork Sun Dec 14 17:54:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 910 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=1765734972; bh=vFoH+csh8sBeIK57DAV71YjFwVv2/Xvm4GNQz9DiJbU=; 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=AuhbO4seq+kQvVAWKbP696fKZ2rTxRZ45IWVHxDegrwjn112Y55PM5+XjVqCNtMfj 31lKsWwcDrlXFMPZt1xSe+VYS5g/czNbmg5v5fmmRROOK/oPCtuZ6QxOkIn+HDwFZJ P7w6qaD64c8PYdJHTBl9tGIwwfHuF5kKpsksAP4YTwPieJKflSSEz+uCt1L19VuXFb 10Yuo31pkIESiQxxoIB1R0RnCGscyskzSpDFnvwlFZ/0aLXstbuv3oBWh5D0c+XIRq CqJUgLbs2AHHlptDWQUwXBX11cAK26Dfv2XYCI9x8klYHQGdZIMtPcnVwuCkgFq5Oy JThaDFP3lXv/A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8B05D68A91 for ; Sun, 14 Dec 2025 10:56:12 -0700 (MST) 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 k7oFsSIawQos for ; Sun, 14 Dec 2025 10:56:12 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734972; bh=vFoH+csh8sBeIK57DAV71YjFwVv2/Xvm4GNQz9DiJbU=; 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=AuhbO4seq+kQvVAWKbP696fKZ2rTxRZ45IWVHxDegrwjn112Y55PM5+XjVqCNtMfj 31lKsWwcDrlXFMPZt1xSe+VYS5g/czNbmg5v5fmmRROOK/oPCtuZ6QxOkIn+HDwFZJ P7w6qaD64c8PYdJHTBl9tGIwwfHuF5kKpsksAP4YTwPieJKflSSEz+uCt1L19VuXFb 10Yuo31pkIESiQxxoIB1R0RnCGscyskzSpDFnvwlFZ/0aLXstbuv3oBWh5D0c+XIRq CqJUgLbs2AHHlptDWQUwXBX11cAK26Dfv2XYCI9x8klYHQGdZIMtPcnVwuCkgFq5Oy JThaDFP3lXv/A== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 79A5468A96 for ; Sun, 14 Dec 2025 10:56:12 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734970; bh=4R2AivVIASG9Q9dWQkEWz2NmwP7vWPsIV6GNJius5g8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r+/AzZNy+Mn8f9NnufNVqEPBUC2nziK6Pmpx5MlTLmuamX6xpAWfF2XABY+rqPNmb bQ9QrTi+THUBodklx9J+gHbED1pgWbDyGTybzeu0AYWFvlx7iDi1sJ/Gwk+GR0j7Gf UDN0yJdp3EpkavkDHmnufWqZ13u/PenGR1y1DUoW5pSP4Q0q/T/1WH/r65dAR7fDzn mugpzuT0eoN6K7GpwG6AEjwz0pxEBCMNQdaOj4TKaLL6gz++P6CMFNUETwJPTQflOy adIrvPg6Fv4IqPRX4nEaaFJwRkwhopU98nNuF/hlqjo3gfT838F0WThjLVh9a5MFCt Ka1sLC6GG5Xww== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 777BD68A91; Sun, 14 Dec 2025 10:56:10 -0700 (MST) 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 1zfo0Z4Vc9_W; Sun, 14 Dec 2025 10:56:10 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734966; bh=gucRtqFLiucsgrEfY9k3C96U4pZrf8xKv/JyivFQL50=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MdLGJIGN8zmM1unQL9xnWMBWf9YC4l0yqOFJlgNX5vdqWG1LirqmNfKBUjxGjmRjd cXwJXaGTTLkMP84F5kP4aON/uPYmtVzd4R2B7rbAjdZjLzRm6upsNP6Hr8+kDSguAk I9NOABqUm88YPyPf3cD8LenBa2akFwP/dItUgeoc2Ic+QnEzzV6xAR7nFo/g78dbyS Peeb7tcz4bGXY0w09apvrkTyjD0NgCf//5ou7iLE5BtqJmlekG5UYYIIEE0aquHUN1 Z5dnqcDed/q667aCXet9XU+TEFmLXdE9mm08QRdgk8kqhejwEzBgrE5dYRDxuGlgsN gij0z1wJpwPVQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id AECE468A89; Sun, 14 Dec 2025 10:56:05 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:39 -0700 Message-ID: <20251214175449.3799539-18-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: AFO6EQJXNBBLSDEOZEOGMLPU77TJIDTX X-Message-ID-Hash: AFO6EQJXNBBLSDEOZEOGMLPU77TJIDTX 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 17/21] test: Allow preserving console recording on failure 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 Update the 'ut' command to have a -R command option to prevent ut_fail() and ut_failf() from clearing GD_FLG_RECORD. This is useful when testing the test framework itself, where error messages need to be captured. Refactor ut_fail() and ut_failf() to call ut_unsilence_console() instead of duplicating the flag-clearing logic. Co-developed-by: Claude Signed-off-by: Simon Glass --- include/test/test.h | 2 ++ test/cmd_ut.c | 8 +++++++- test/ut.c | 7 ++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/test/test.h b/include/test/test.h index 2facf5b3675..5ae90e39e00 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -96,6 +96,7 @@ struct ut_arg { * @args: Parsed argument values for current test * @arg_count: Number of parsed arguments * @arg_error: Set if ut_str/int/bool() detects a type mismatch + * @keep_record: Preserve console recording when ut_fail() is called * @priv: Private data for tests to use as needed */ struct unit_test_state { @@ -126,6 +127,7 @@ struct unit_test_state { struct ut_arg args[UT_MAX_ARGS]; int arg_count; bool arg_error; + bool keep_record; char priv[UT_PRIV_SIZE]; }; diff --git a/test/cmd_ut.c b/test/cmd_ut.c index adc96fcbcdc..6358f27a64f 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -252,6 +252,7 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) struct unit_test_state uts; bool show_suites = false; bool force_run = false; + bool keep_record = false; int runs_per_text = 1; struct suite *ste; char *name; @@ -276,6 +277,9 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if (!strchr(test_insert, ':')) return CMD_RET_USAGE; break; + case 'R': + keep_record = true; + break; case 's': show_suites = true; break; @@ -288,6 +292,7 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_USAGE; ut_init_state(&uts); + uts.keep_record = keep_record; name = argv[0]; select_name = cmd_arg1(argc, argv); @@ -333,10 +338,11 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } U_BOOT_LONGHELP(ut, - "[-rs] [-f] [-I:] [ [...]] - run unit tests\n" + "[-rs] [-f] [-R] [-I:] [ [...]] - run unit tests\n" " -r Number of times to run each test\n" " -f Force 'manual' tests to run as well\n" " -I Test to run after other tests have run\n" + " -R Preserve console recording on test failure\n" " -s Show all suites with ut info\n" " Test suite to run (or comma-separated list)\n" " Specific test to run (optional)\n" diff --git a/test/ut.c b/test/ut.c index fe9a177ab53..0677e3fbee9 100644 --- a/test/ut.c +++ b/test/ut.c @@ -23,7 +23,7 @@ DECLARE_GLOBAL_DATA_PTR; void ut_fail(struct unit_test_state *uts, const char *fname, int line, const char *func, const char *cond) { - gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); + ut_unsilence_console(uts); printf("%s:%d, %s(): %s\n", fname, line, func, cond); uts->cur.fail_count++; } @@ -33,7 +33,7 @@ void ut_failf(struct unit_test_state *uts, const char *fname, int line, { va_list args; - gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); + ut_unsilence_console(uts); printf("%s:%d, %s(): %s: ", fname, line, func, cond); va_start(args, fmt); vprintf(fmt, args); @@ -286,7 +286,8 @@ void ut_silence_console(struct unit_test_state *uts) void ut_unsilence_console(struct unit_test_state *uts) { - gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); + if (!uts->keep_record) + gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); } void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays) From patchwork Sun Dec 14 17:54:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 911 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=1765734977; bh=pmDA5VpJRP6J8FO67ZERq/lmgEedvRxGPaXuLjdKba8=; 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=wf80zLUIlL4QHjXy6Xb/NtuuDZ3MCpfjsP4cReLqUclR7I8GL0Z/bs5A/iNaryyjg iypPhBA8ZK1v8iD9LyJ+L1vPeJsLZRpWkE4wXMqUq508JiUL3xGXAJ1Ke9d4V//OMD 60GEFA/cVEUfG6vCz/ihrPIZYRTtU470LgnuiqjxDVfM9da/8oX35DJziQW8C/y7zH 31PDPaSZsV+W8TDWsKzyPXYMTRR3it/dLwbCzo7H0BuO8DT4+KIQ5EEEvYtcNUjf9O ubP0nuM/bEL1kDGq5Lq0TJ+NKbJkgPOMm9+iIKsZGhWpLx4YI/mn/BA3zEq0Vm+VI/ 3CUB2SYtnpx1w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 4899668AFE for ; Sun, 14 Dec 2025 10:56:17 -0700 (MST) 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 Q_aaA8X2CoSH for ; Sun, 14 Dec 2025 10:56:17 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734977; bh=pmDA5VpJRP6J8FO67ZERq/lmgEedvRxGPaXuLjdKba8=; 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=wf80zLUIlL4QHjXy6Xb/NtuuDZ3MCpfjsP4cReLqUclR7I8GL0Z/bs5A/iNaryyjg iypPhBA8ZK1v8iD9LyJ+L1vPeJsLZRpWkE4wXMqUq508JiUL3xGXAJ1Ke9d4V//OMD 60GEFA/cVEUfG6vCz/ihrPIZYRTtU470LgnuiqjxDVfM9da/8oX35DJziQW8C/y7zH 31PDPaSZsV+W8TDWsKzyPXYMTRR3it/dLwbCzo7H0BuO8DT4+KIQ5EEEvYtcNUjf9O ubP0nuM/bEL1kDGq5Lq0TJ+NKbJkgPOMm9+iIKsZGhWpLx4YI/mn/BA3zEq0Vm+VI/ 3CUB2SYtnpx1w== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3107568ADE for ; Sun, 14 Dec 2025 10:56:17 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734975; bh=V3j4/4WevZ4mhKhdfLZQCvjw8wteaAFaQ6S4izJH7AQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wSGz5iizL5pNFYOjR4zWsenUuVx88h7OjnEfdwGAI55AaXWLHf60vmoA0fX+oPoe9 YgTwoMyHQKDMBFPNBqTs2gNDD8MotfBArCtPoVGxnMYDRT9m3rw5ccKIrpzaEGsznp lzrAMFOlcIQxgrqcjOb0g94jexZNJdiwlTYnzG8aiKD/SffHrUDhiVX9drCbxRuSjl 4e432mx/XtlEVCXfA58mKi8epqDlmidmoOWoLeCUsJ0RQwzlbH116rKcbmsxASZMc3 FKe1ylZRhbWZFk/q4Nl6UP5dpGbBS5ihqnLaDcyg3g5Mw9EwkTt2TJh+KhGo/+zp2C jI9/78Es1qIuA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3287468A96; Sun, 14 Dec 2025 10:56:15 -0700 (MST) 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 10S3dwYbHtbc; Sun, 14 Dec 2025 10:56:15 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734970; bh=Fs36/QrNewFS6wxSVcg7X+1o7fNfg5eaFupl8K5WjbM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hbMJ/BYze2bmBrTbhVH/XE455Uj4zC+nzaljcaI1OHGMOyyP2SfnWmCtMtl2cxENO XoWdy41GUqlP0RTz24I4PiEXebbTXtekAbPkmJBe79W32R/G5l8471sGmoacL4ANWl +qTomBcR5SJANiWun1oQWOcDwj/ps4uuFgdVOTxHrotX0Psv5w0HUpCusvbqhbsQNg knE/EBhDnVZDTbr/kwlFs76h4pORb3mpaBh9mZuhiRSwnjzGJkjD3RAFfNrZy4bNAy eRn87xuxSEuT3gzJB+yiUkxBVRS1Ba/WoUR/xU6WP702kkVeGJ6oLFviFEM7qTlfmv 3RFRiPin2BS+A== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 5C1A368A84; Sun, 14 Dec 2025 10:56:10 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:40 -0700 Message-ID: <20251214175449.3799539-19-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: ZBDE3GAJPOATZAYIS4MBT7CMH55YY4YD X-Message-ID-Hash: ZBDE3GAJPOATZAYIS4MBT7CMH55YY4YD 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 18/21] test: Add tests for unit-test arguments 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 Add a set of tests to check the behaviour of test arguments and the ut command. This includes failure cases, where the wrong type or a non-existent argument is requested. Co-developed-by: Claude Signed-off-by: Simon Glass --- test/common/Makefile | 1 + test/common/test_args.c | 186 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 test/common/test_args.c diff --git a/test/common/Makefile b/test/common/Makefile index 9674bbec030..eba4f8c125f 100644 --- a/test/common/Makefile +++ b/test/common/Makefile @@ -16,3 +16,4 @@ obj-y += cread.o obj-y += malloc.o obj-$(CONFIG_CONSOLE_PAGER) += pager.o obj-$(CONFIG_$(PHASE_)CMDLINE) += print.o +obj-$(CONFIG_$(PHASE_)CMDLINE) += test_args.o diff --git a/test/common/test_args.c b/test/common/test_args.c new file mode 100644 index 00000000000..745caeb8991 --- /dev/null +++ b/test/common/test_args.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for unit test arguments + * + * Copyright 2025 Canonical Ltd + * Written by Simon Glass + */ + +#include +#include +#include +#include + +/* Test that string arguments work correctly */ +static int test_args_str_norun(struct unit_test_state *uts) +{ + ut_asserteq_str("hello", ut_str(0)); + + return 0; +} +UNIT_TEST_ARGS(test_args_str_norun, UTF_CONSOLE | UTF_MANUAL, common, + { "strval", UT_ARG_STR }); + +/* Test that integer arguments work correctly */ +static int test_args_int_norun(struct unit_test_state *uts) +{ + ut_asserteq(1234, ut_int(0)); + + return 0; +} +UNIT_TEST_ARGS(test_args_int_norun, UTF_CONSOLE | UTF_MANUAL, common, + { "intval", UT_ARG_INT }); + +/* Test that boolean arguments work correctly */ +static int test_args_bool_norun(struct unit_test_state *uts) +{ + ut_asserteq(true, ut_bool(0)); + + return 0; +} +UNIT_TEST_ARGS(test_args_bool_norun, UTF_CONSOLE | UTF_MANUAL, common, + { "boolval", UT_ARG_BOOL }); + +/* Test multiple arguments of different types */ +static int test_args_multi_norun(struct unit_test_state *uts) +{ + ut_asserteq_str("test", ut_str(0)); + ut_asserteq(42, ut_int(1)); + ut_asserteq(true, ut_bool(2)); + + return 0; +} +UNIT_TEST_ARGS(test_args_multi_norun, UTF_CONSOLE | UTF_MANUAL, common, + { "str", UT_ARG_STR }, + { "num", UT_ARG_INT }, + { "flag", UT_ARG_BOOL }); + +/* Test optional arguments with defaults */ +static int test_args_optional_norun(struct unit_test_state *uts) +{ + /* Required arg should match what was passed */ + ut_asserteq_str("required", ut_str(0)); + + /* Optional args should have default values if not provided */ + ut_asserteq(99, ut_int(1)); + ut_asserteq(false, ut_bool(2)); + + return 0; +} +UNIT_TEST_ARGS(test_args_optional_norun, UTF_CONSOLE | UTF_MANUAL, common, + { "req", UT_ARG_STR }, + { "opt_int", UT_ARG_INT, UT_ARGF_OPTIONAL, { .vint = 99 } }, + { "opt_bool", UT_ARG_BOOL, UT_ARGF_OPTIONAL, { .vbool = false } }); + +/* + * Test requesting wrong type - ut_int() on a string arg should fail + * This test deliberately causes a type mismatch to verify error handling + */ +static int test_args_wrongtype_norun(struct unit_test_state *uts) +{ + /* This should fail - asking for int but arg is string */ + ut_asserteq(0, ut_int(0)); + ut_asserteq(true, uts->arg_error); + + return 0; +} +UNIT_TEST_ARGS(test_args_wrongtype_norun, UTF_MANUAL, common, + { "strval", UT_ARG_STR }); + +/* + * Test requesting invalid arg number - ut_str(1) when only arg 0 exists + * This test deliberately causes an out-of-bounds access to verify error handling + */ +static int test_args_badnum_norun(struct unit_test_state *uts) +{ + /* This should fail - asking for arg 1 but only arg 0 exists */ + ut_asserteq_ptr(NULL, ut_str(1)); + ut_asserteq(true, uts->arg_error); + + return 0; +} +UNIT_TEST_ARGS(test_args_badnum_norun, UTF_MANUAL, common, + { "strval", UT_ARG_STR }); + +/* Wrapper test that runs the manual tests with proper arguments */ +static int test_args(struct unit_test_state *uts) +{ + ut_assertok(run_command("ut -f common test_args_str_norun strval=hello", + 0)); + ut_assertok(run_command("ut -f common test_args_int_norun intval=1234", + 0)); + ut_assertok(run_command("ut -f common test_args_bool_norun boolval=1", + 0)); + ut_assertok(run_command("ut -f common test_args_multi_norun str=test num=42 flag=1", + 0)); + ut_assertok(run_command("ut -f common test_args_optional_norun req=required", + 0)); + + return 0; +} +COMMON_TEST(test_args, UTF_CONSOLE); + +/* + * Test argument-parsing failure cases - these should all fail + * + * Note: Running 'ut' within a test is not normal practice since do_ut() + * creates a new test state. But it works here for testing the argument + * parsing itself. + */ +static int test_args_fail(struct unit_test_state *uts) +{ + /* Missing required argument - should fail */ + ut_asserteq(1, run_command("ut -f common test_args_str_norun", 0)); + ut_assert_nextline("Missing required argument 'strval' for test 'test_args_str_norun'"); + ut_assert_nextline_regex("Tests run: 1,.*failures: 1"); + ut_assert_console_end(); + + /* Unknown argument name - should fail */ + ut_asserteq(1, run_command("ut -f common test_args_str_norun badarg=x", + 0)); + ut_assert_nextline("Unknown argument 'badarg' for test 'test_args_str_norun'"); + ut_assert_nextline_regex("Tests run: 1,.*failures: 1"); + ut_assert_console_end(); + + /* Invalid format (no = sign) - should fail */ + ut_asserteq(1, run_command("ut -f common test_args_str_norun strval", + 0)); + ut_assert_nextline("Invalid argument 'strval' (expected key=value)"); + ut_assert_nextline_regex("Tests run: 1,.*failures: 1"); + ut_assert_console_end(); + + return 0; +} +COMMON_TEST(test_args_fail, UTF_CONSOLE); + +/* Test that requesting wrong type fails - ut_int() on string arg */ +static int test_args_wrongtype(struct unit_test_state *uts) +{ + ut_asserteq(1, + run_command("ut -R -f common test_args_wrongtype_norun strval=hello", + 0)); + ut_assert_nextline("Test: test_args_wrongtype_norun: test_args.c"); + ut_assert_nextline_regex("test/common/test_args.c:.*, test_args_wrongtype_norun\\(\\): ut_int\\(\\) type check: arg 0 is not an int"); + ut_assert_nextline("Test 'test_args_wrongtype_norun' failed 1 times"); + ut_assert_nextline_regex("Tests run: 1,.*failures: 1"); + ut_assert_console_end(); + + return 0; +} +COMMON_TEST(test_args_wrongtype, UTF_CONSOLE); + +/* Test that requesting invalid arg number fails */ +static int test_args_badnum(struct unit_test_state *uts) +{ + ut_asserteq(1, + run_command("ut -R -f common test_args_badnum_norun strval=hello", + 0)); + ut_assert_nextline("Test: test_args_badnum_norun: test_args.c"); + ut_assert_nextline_regex("test/common/test_args.c:.*, test_args_badnum_norun\\(\\): ut_str\\(\\) arg check: arg 1 is invalid \\(arg_count=1\\)"); + ut_assert_nextline("Test 'test_args_badnum_norun' failed 1 times"); + ut_assert_nextline_regex("Tests run: 1,.*failures: 1"); + ut_assert_console_end(); + + return 0; +} +COMMON_TEST(test_args_badnum, UTF_CONSOLE); From patchwork Sun Dec 14 17:54:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 912 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=1765734979; bh=dE9eack/GEDMWnVbjG0RM9NVHF9iJClDybEElzljn6o=; 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=RBIZjkd8AgW4gO1/FAKrShWCoS5DG9LFJCZrqzKWGi1qSH0K/dqE7PB2JG8k75rCj 0zakpS0g/saTIsPKNBGjCkujUTU4OoyK8fbF1cRRXFO3aDdJ0LKTymZ2Chp6T5LJOp ZFvKb2/LplvYXm53aKEby0wSZzipvhoD3fcZO59H7+v1TwlpL7K+2xDehcUkOkWKep dvrP94nzvudbxpaF3uAdvhtnw55qC0z3watky9qloI1g6q3ZnRdS3otmq02kbQ8NAH RNsKMIYYEB30QxNPJRgUEAbo/5l7ail/uuKZ01Xd06tIb0Ho8+iQ4JTmH4lHbz5Wzq groGiS2xCuH7A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A3F7068AFE for ; Sun, 14 Dec 2025 10:56:19 -0700 (MST) 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 IiKnURryENkD for ; Sun, 14 Dec 2025 10:56:19 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734977; bh=dE9eack/GEDMWnVbjG0RM9NVHF9iJClDybEElzljn6o=; 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=EOHnRYNHkCcZmiwXjGBsBO0FppODml9mU/gaV0KBcI/iTz6aNyFUkdbsSkHhO65Ya ZkjfGYezhKa1k9cd12/1kzyDPSl6MZMqwr2bO9m+a8tyqZq3okNkpT1lJT1R9GjvfD w1cRvmzTL4kx2JcrJJ5dezt6FKaNVsX08Pphy3HUYvIPxKDrx6AoL9hHUTIjPgPTdl s7PUctMdNRlpsx5hrnyEDSKVpd6898jk2w15UfHRp9dqq0WneV5UFduMDdHrusBg2J +KZBnj3bANiIkV45Lbe/8BeKGp4h6CrZgUnq2JjjV7HJ6yceJy28Z5tWQ7XZ2LKi95 6E7G1Wpcb2Pug== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 98C6F68A96 for ; Sun, 14 Dec 2025 10:56:17 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734976; bh=X/5HEJ4zx0UsqMhwD5SQrNbUXuN/SN+P+fk19M6/Gu4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kGPJspW1WgqEzAG8ZapBDOmzw4NXwirUCx6eRQef9QjuIpswTZ1q9ugiQMuCjWqVj aZp6xpNRc5u9aCCmSE4BvyjeSW9Go6YeauIRauRW+HElZGanXUaDAwseSKpXmkfUlW 681rL/j80aGwX1vBgJHSGxDApdawbhuX4O4ZhMpRpcm2eF9zIXcm5e6Ql5z9Flv2gf ZSxUs9v9KdBvTj8CVrve/TU0cEEOtb2yBELIvFWK+WGaiqFu0719JrgMU5l51dme6/ 4G0kQE3ANZRwZVJ2Sbr3F0HWvvYEdp8Mc/Dd8mO871pVz2VaKVU2NV/oR51lsAy9D3 wy8EL+y6DQsLw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1BF3168A84; Sun, 14 Dec 2025 10:56:16 -0700 (MST) 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 WOxwezb6ED30; Sun, 14 Dec 2025 10:56:16 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734975; bh=HLQBjiSPVL1vcDYwJs8TLr4FT1hemGweUQwscnmh504=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JGNE3pfDyVrBRumNQSKnVOb+/I+whUj6tDCKnubqT9c4o86j8aOM+s+FLcCLCWYNa 4xWVe3dzk9IPzAWGuBEXwYMqDx4AuvFdn8zvEdpPYpNN9MjUxrz2wJgs/aLllDIhuJ 4CaPFES8uON4/sCYCUzT27wEEt6eR1RaTaNHF90vhYhYZhB2rId2yWg+orvGWHSluN 3q3nl8Vhs0QKzgRzXibO1Ebn/RdfjlXnjEDidwWd+cXovFuyT0wppiCBogtrnvv59V vloYIH6ssEE0CDbYz0w2eRUC7KCZEoE0PZDqLoOfz7p5ekRsH0MulRogG51cssM57y Ky4BnkkUzQzdQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 1019F68A91; Sun, 14 Dec 2025 10:56:15 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:41 -0700 Message-ID: <20251214175449.3799539-20-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: SF2F2LW5ECCBTYATCZLY3R2XLR4QXN3Q X-Message-ID-Hash: SF2F2LW5ECCBTYATCZLY3R2XLR4QXN3Q 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 19/21] test: fs: add C-based filesystem tests 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 Add C implementations of filesystem tests that can be called via the 'ut fs' command. These tests use UTF_MANUAL flag since they require external setup, i.e. creation of filesystem images. This covers the existing TestFsBasic tests. The tests use typed arguments (fs_type, fs_image, md5 values) passed via the command line. Add a few helpers to make the code easier to read. Co-developed-by: Claude Signed-off-by: Simon Glass --- include/test/fs.h | 39 ++++ test/Makefile | 1 + test/cmd_ut.c | 2 + test/fs/Makefile | 3 + test/fs/fs_basic.c | 492 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 537 insertions(+) create mode 100644 include/test/fs.h create mode 100644 test/fs/Makefile create mode 100644 test/fs/fs_basic.c diff --git a/include/test/fs.h b/include/test/fs.h new file mode 100644 index 00000000000..58fc105a94a --- /dev/null +++ b/include/test/fs.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2025 Google LLC + */ + +#ifndef __TEST_FS_H +#define __TEST_FS_H + +#include +#include + +/** + * FS_TEST() - Define a new filesystem test + * + * @name: Name of test function + * @flags: Flags for the test (see enum ut_flags) + */ +#define FS_TEST(_name, _flags) UNIT_TEST(_name, UTF_DM | (_flags), fs) + +/** + * FS_TEST_ARGS() - Define a filesystem test with inline arguments + * + * Like FS_TEST() but for tests that take arguments. + * The test can access arguments via uts->args[]. + * The NULL terminator is added automatically. + * + * Example: + * FS_TEST_ARGS(my_test, UTF_MANUAL, + * { "fs_type", UT_ARG_STR }, + * { "fs_image", UT_ARG_STR }); + * + * @name: Name of test function + * @flags: Flags for the test (see enum ut_flags) + * @...: Argument definitions (struct ut_arg_def initializers) + */ +#define FS_TEST_ARGS(_name, _flags, ...) \ + UNIT_TEST_ARGS(_name, UTF_DM | (_flags), fs, __VA_ARGS__) + +#endif /* __TEST_FS_H */ diff --git a/test/Makefile b/test/Makefile index f7ab9a36b2a..1edd931f3e8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,6 +22,7 @@ obj-y += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-$(CONFIG_UT_ENV) += env/ obj-$(CONFIG_UT_FDT_OVERLAY) += fdt_overlay/ +obj-$(CONFIG_SANDBOX) += fs/ obj-y += log/ else obj-$(CONFIG_SPL_UT_LOAD) += image/ diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 6358f27a64f..8d8a2d763a2 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -61,6 +61,7 @@ SUITE_DECL(exit); SUITE_DECL(fdt); SUITE_DECL(fdt_overlay); SUITE_DECL(font); +SUITE_DECL(fs); SUITE_DECL(hush); SUITE_DECL(lib); SUITE_DECL(loadm); @@ -89,6 +90,7 @@ static struct suite suites[] = { SUITE(fdt, "fdt command"), SUITE(fdt_overlay, "device tree overlays"), SUITE(font, "font command"), + SUITE(fs, "filesystem tests"), SUITE(hush, "hush behaviour"), SUITE(lib, "library functions"), SUITE(loadm, "loadm command parameters and loading memory blob"), diff --git a/test/fs/Makefile b/test/fs/Makefile new file mode 100644 index 00000000000..5899be8e667 --- /dev/null +++ b/test/fs/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += fs_basic.o diff --git a/test/fs/fs_basic.c b/test/fs/fs_basic.c new file mode 100644 index 00000000000..d3b18275fac --- /dev/null +++ b/test/fs/fs_basic.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Basic filesystem tests - C implementation for Python wrapper + * + * These tests are marked UTF_MANUAL and are intended to be called from + * test_basic.py which sets up the filesystem image and expected values. + * + * Copyright 2025 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Test constants matching fstest_defs.py */ +#define ADDR 0x01000008 + +/* + * Common argument indices. Each test declares only the arguments it needs, + * so indices 2+ vary per test - see comments in each test. + */ +#define FS_ARG_TYPE 0 /* fs_type: ext4, fat, exfat, fs_generic */ +#define FS_ARG_IMAGE 1 /* fs_image: path to filesystem image */ + +/* Common arguments for all filesystem tests (indices 0 and 1) */ +#define COMMON_ARGS \ + { "fs_type", UT_ARG_STR }, \ + { "fs_image", UT_ARG_STR } + +/** + * get_fs_type(uts) - Get filesystem type enum from test argument + * + * Reads the fs_type argument and returns the appropriate FS_TYPE_* enum value. + * + * Return: filesystem type enum + */ +static int get_fs_type(struct unit_test_state *uts) +{ + const char *fs_type = ut_str(FS_ARG_TYPE); + + if (!fs_type) + return FS_TYPE_ANY; + + if (!strcmp(fs_type, "ext4")) + return FS_TYPE_EXT; + if (!strcmp(fs_type, "fat")) + return FS_TYPE_FAT; + if (!strcmp(fs_type, "exfat")) + return FS_TYPE_EXFAT; + + /* fs_generic uses FS_TYPE_ANY */ + return FS_TYPE_ANY; +} + +/* Set up the host filesystem block device */ +static int set_fs(struct unit_test_state *uts) +{ + return fs_set_blk_dev("host", "0:0", get_fs_type(uts)); +} + +/* Build a path by prepending "/" to the leaf filename, with optional suffix */ +static const char *getpath(struct unit_test_state *uts, const char *leaf, + const char *suffix) +{ + snprintf(uts->priv, sizeof(uts->priv), "/%s%s", leaf, suffix ?: ""); + + return uts->priv; +} + +/** + * prep_fs() - Prepare filesystem for testing + * + * Binds the fs_image argument as host device 0, sets up the block device, + * and optionally returns a zeroed buffer. + * + * @uts: Unit test state + * @len: Length of buffer to allocate and zero, or 0 for none + * @bufp: Returns pointer to zeroed buffer, or NULL if @len is 0 + * Return: 0 on success, negative on error + */ +static int prep_fs(struct unit_test_state *uts, uint len, void **bufp) +{ + const char *fs_image = ut_str(FS_ARG_IMAGE); + + ut_assertnonnull(fs_image); + ut_assertok(run_commandf("host bind 0 %s", fs_image)); + ut_assertok(set_fs(uts)); + + if (len) { + *bufp = map_sysmem(ADDR, len); + memset(*bufp, '\0', len); + } + + return 0; +} + +/** + * fs_write_supported(uts) - Check if write is supported for current fs type + * + * Reads the fs_type argument and checks if write support is enabled + * for that filesystem type. + * + * Return: true if write is supported, false otherwise + */ +static bool fs_write_supported(struct unit_test_state *uts) +{ + const char *fs_type = ut_str(FS_ARG_TYPE); + + if (!fs_type) + return false; + + if (!strcmp(fs_type, "ext4")) + return IS_ENABLED(CONFIG_EXT4_WRITE); + if (!strcmp(fs_type, "fat")) + return IS_ENABLED(CONFIG_CMD_FAT_WRITE); + + /* fs_generic and exfat use generic write which is always available */ + return true; +} + +/** + * verify_md5() - Calculate MD5 of buffer and verify against expected + * + * Uses arg 3 (md5val) as the expected MD5 hex string. + * + * @uts: Unit test state + * @buf: Buffer to calculate MD5 of + * @len: Length of buffer + * + * Return: 0 if MD5 matches, -EINVAL otherwise + */ +static int verify_md5(struct unit_test_state *uts, const void *buf, size_t len) +{ + u8 digest[MD5_SUM_LEN], expected[MD5_SUM_LEN]; + const char *expected_hex = ut_str(3); + + ut_assertok(hex2bin(expected, expected_hex, MD5_SUM_LEN)); + + md5_wd(buf, len, digest, CHUNKSZ_MD5); + ut_asserteq_mem(expected, digest, MD5_SUM_LEN); + + return 0; +} + +/** + * Test Case 1 - ls command, listing root directory and invalid directory + */ +static int fs_test_ls_norun(struct unit_test_state *uts) +{ + const char *small = ut_str(2); + const char *big = ut_str(3); + struct fs_dir_stream *dirs; + struct fs_dirent *dent; + int found_big = 0, found_small = 0, found_subdir = 0; + + ut_assertok(prep_fs(uts, 0, NULL)); + + /* Test listing root directory */ + dirs = fs_opendir("/"); + ut_assertnonnull(dirs); + + while ((dent = fs_readdir(dirs))) { + if (!strcmp(dent->name, big)) { + found_big = 1; + ut_asserteq(FS_DT_REG, dent->type); + } else if (!strcmp(dent->name, small)) { + found_small = 1; + ut_asserteq(FS_DT_REG, dent->type); + } else if (!strcmp(dent->name, "SUBDIR")) { + found_subdir = 1; + ut_asserteq(FS_DT_DIR, dent->type); + } + } + fs_closedir(dirs); + + ut_asserteq(1, found_big); + ut_asserteq(1, found_small); + ut_asserteq(1, found_subdir); + + /* Test invalid directory returns error */ + ut_assertok(set_fs(uts)); + dirs = fs_opendir("/invalid_d"); + ut_assertnull(dirs); + + /* Test file exists */ + ut_assertok(set_fs(uts)); + ut_asserteq(1, fs_exists(small)); + + /* Test non-existent file */ + ut_assertok(set_fs(uts)); + ut_asserteq(0, fs_exists("nonexistent.file")); + + return 0; +} +FS_TEST_ARGS(fs_test_ls_norun, UTF_SCAN_FDT | UTF_CONSOLE | UTF_MANUAL, + COMMON_ARGS, { "small", UT_ARG_STR }, { "big", UT_ARG_STR }); + +/** + * Test Case 2 - size command for small file (1MB) + */ +static int fs_test_size_small_norun(struct unit_test_state *uts) +{ + const char *small = ut_str(2); + loff_t size; + + ut_assertok(prep_fs(uts, 0, NULL)); + ut_assertok(fs_size(getpath(uts, small, NULL), &size)); + ut_asserteq(SZ_1M, size); + + /* Test size via path with '..' */ + ut_assertok(set_fs(uts)); + snprintf(uts->priv, sizeof(uts->priv), "/SUBDIR/../%s", small); + ut_assertok(fs_size(uts->priv, &size)); + ut_asserteq(SZ_1M, size); + + return 0; +} +FS_TEST_ARGS(fs_test_size_small_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "small", UT_ARG_STR }); + +/** + * Test Case 3 - size command for large file (2500 MiB) + */ +static int fs_test_size_big_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t size; + + ut_assertok(prep_fs(uts, 0, NULL)); + ut_assertok(fs_size(getpath(uts, big, NULL), &size)); + ut_asserteq_64((loff_t)SZ_1M * 2500, size); /* 2500 MiB = 0x9c400000 */ + + return 0; +} +FS_TEST_ARGS(fs_test_size_big_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }); + +/** + * Test Case 4 - load small file, verify MD5 + */ +static int fs_test_load_small_norun(struct unit_test_state *uts) +{ + const char *small = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + ut_assertok(fs_legacy_read(getpath(uts, small, NULL), ADDR, 0, 0, + &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_load_small_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "small", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 5 - load first 1MB of big file + */ +static int fs_test_load_big_first_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + ut_assertok(fs_legacy_read(getpath(uts, big, NULL), ADDR, 0, SZ_1M, + &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_load_big_first_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 6 - load last 1MB of big file (offset 0x9c300000) + */ +static int fs_test_load_big_last_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + ut_assertok(fs_legacy_read(getpath(uts, big, NULL), ADDR, 0x9c300000ULL, + SZ_1M, &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_load_big_last_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 7 - load 1MB from last 1MB chunk of 2GB (offset 0x7ff00000) + */ +static int fs_test_load_big_2g_last_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + ut_assertok(fs_legacy_read(getpath(uts, big, NULL), ADDR, 0x7ff00000ULL, + SZ_1M, &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_load_big_2g_last_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 8 - load first 1MB in 2GB region (offset 0x80000000) + */ +static int fs_test_load_big_2g_first_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + ut_assertok(fs_legacy_read(getpath(uts, big, NULL), ADDR, 0x80000000ULL, + SZ_1M, &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_load_big_2g_first_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 9 - load 1MB crossing 2GB boundary (offset 0x7ff80000) + */ +static int fs_test_load_big_2g_cross_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + ut_assertok(fs_legacy_read(getpath(uts, big, NULL), ADDR, 0x7ff80000ULL, + SZ_1M, &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_load_big_2g_cross_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 10 - load beyond file end (2MB from offset where only 1MB remains) + */ +static int fs_test_load_beyond_norun(struct unit_test_state *uts) +{ + const char *big = ut_str(2); + loff_t actread; + void *buf; + + ut_assertok(prep_fs(uts, SZ_2M, &buf)); /* 2MB buffer */ + + /* Request 2MB starting at 1MB before EOF - should get 1MB */ + ut_assertok(fs_legacy_read(getpath(uts, big, NULL), ADDR, 0x9c300000ULL, + SZ_2M, &actread)); + ut_asserteq(SZ_1M, actread); /* Only 1MB available */ + + return 0; +} +FS_TEST_ARGS(fs_test_load_beyond_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "big", UT_ARG_STR }); + +/** + * Test Case 11 - write file + */ +static int fs_test_write_norun(struct unit_test_state *uts) +{ + const char *small = ut_str(2); + + loff_t actread, actwrite; + void *buf; + + if (!fs_write_supported(uts)) + return -EAGAIN; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + + /* Read small file */ + ut_assertok(fs_legacy_read(getpath(uts, small, NULL), ADDR, 0, 0, + &actread)); + ut_asserteq(SZ_1M, actread); + + /* Write it back with new name */ + ut_assertok(set_fs(uts)); + ut_assertok(fs_write(getpath(uts, small, ".w"), ADDR, 0, SZ_1M, + &actwrite)); + ut_asserteq(SZ_1M, actwrite); + + /* Read back and verify MD5 */ + ut_assertok(set_fs(uts)); + memset(buf, '\0', SZ_1M); + ut_assertok(fs_legacy_read(getpath(uts, small, ".w"), ADDR, 0, 0, + &actread)); + ut_asserteq(SZ_1M, actread); + + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_write_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "small", UT_ARG_STR }, { "md5val", UT_ARG_STR }); + +/** + * Test Case 12 - write to "." directory (should fail) + */ +static int fs_test_write_dot_norun(struct unit_test_state *uts) +{ + loff_t actwrite; + + if (!fs_write_supported(uts)) + return -EAGAIN; + + ut_assertok(prep_fs(uts, 0, NULL)); + + /* Writing to "." should fail */ + ut_assert(fs_write("/.", ADDR, 0, 0x10, &actwrite)); + + return 0; +} +FS_TEST_ARGS(fs_test_write_dot_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS); + +/** + * Test Case 13 - write via "./" path + */ +static int fs_test_write_dotpath_norun(struct unit_test_state *uts) +{ + const char *small = ut_str(2); + loff_t actread, actwrite; + void *buf; + + if (!fs_write_supported(uts)) + return -EAGAIN; + + ut_assertok(prep_fs(uts, SZ_1M, &buf)); + + /* Read small file */ + ut_assertok(fs_legacy_read(getpath(uts, small, NULL), ADDR, 0, 0, + &actread)); + ut_asserteq(SZ_1M, actread); + + /* Write via "./" path */ + ut_assertok(set_fs(uts)); + snprintf(uts->priv, sizeof(uts->priv), "/./%s2", small); + ut_assertok(fs_write(uts->priv, ADDR, 0, SZ_1M, &actwrite)); + ut_asserteq(SZ_1M, actwrite); + + /* Read back via "./" path and verify */ + ut_assertok(set_fs(uts)); + memset(buf, '\0', SZ_1M); + ut_assertok(fs_legacy_read(uts->priv, ADDR, 0, 0, &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + /* Also verify via normal path */ + ut_assertok(set_fs(uts)); + memset(buf, '\0', SZ_1M); + ut_assertok(fs_legacy_read(getpath(uts, small, "2"), ADDR, 0, 0, + &actread)); + ut_asserteq(SZ_1M, actread); + ut_assertok(verify_md5(uts, buf, SZ_1M)); + + return 0; +} +FS_TEST_ARGS(fs_test_write_dotpath_norun, UTF_SCAN_FDT | UTF_MANUAL, + COMMON_ARGS, { "small", UT_ARG_STR }, { "md5val", UT_ARG_STR }); From patchwork Sun Dec 14 17:54:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 913 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=1765734984; bh=cfXnK79G4VohvmtDu/tyiNN7/2ixRWq6XjnZgXJ9I6w=; 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=mObhwQT3eRklIrPdzQqJo+9inhJzhWVip5qETANOB+ombg4fwIBXmplcB5OhAXmfG po83ynVTU46ckJwHpODzPOl1gSBDmzhurjSGjhG1wc4fTqom6VQhO/QmYdOJ5omMlk vBr/z/bfEJz8iWM8TI4fk2W2K9UO9OwlyEvdfwpYmhUt4u4rZk3AZJYfiMYr1jKuFZ xK+0oc8HUxPfk9ybgkjdarFkqp9X4ztRguQDONkHqmnanVWi/wiT3rA3r2nDmYlB+3 KhbVRQYuJ522A17lnr9RXLcO4BNXvepCHMI2nQf7KuA1l8rMpIcRxibLdomsihmpG1 EU65EVZc7xazA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1EC3368ADF for ; Sun, 14 Dec 2025 10:56:24 -0700 (MST) 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 zFkiMtuU9g50 for ; Sun, 14 Dec 2025 10:56:24 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734984; bh=cfXnK79G4VohvmtDu/tyiNN7/2ixRWq6XjnZgXJ9I6w=; 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=mObhwQT3eRklIrPdzQqJo+9inhJzhWVip5qETANOB+ombg4fwIBXmplcB5OhAXmfG po83ynVTU46ckJwHpODzPOl1gSBDmzhurjSGjhG1wc4fTqom6VQhO/QmYdOJ5omMlk vBr/z/bfEJz8iWM8TI4fk2W2K9UO9OwlyEvdfwpYmhUt4u4rZk3AZJYfiMYr1jKuFZ xK+0oc8HUxPfk9ybgkjdarFkqp9X4ztRguQDONkHqmnanVWi/wiT3rA3r2nDmYlB+3 KhbVRQYuJ522A17lnr9RXLcO4BNXvepCHMI2nQf7KuA1l8rMpIcRxibLdomsihmpG1 EU65EVZc7xazA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0E8AC68A91 for ; Sun, 14 Dec 2025 10:56:24 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734982; bh=goXri8lDIxxm4R5tTAqm4avpvSd0NAat/3xKIBuNnuc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CYB/r3y+Uh+V82MSl72oGR/3NzhS4/Az2Br8eblhGj1e7mzkSwsFhbsNUecL4Ha/r xQ5oGr9PKdbU7kzmLY52BcT8ahJV1mv7QdtiSHlagSFx//+c2gbXgc7qcFETh2EBS+ PGLVYIKAZ3Vlk2ulKrt1jn1iwawsYM39sTmE3xgaH58DtTyafASJ/94rieh2Uay7iI wBLUDDCtAqfuSSeVfA0NiVKnh8TGBAxV+2jFJrra2mvMU7xh4bylfLdeqkaFE20pAE +KfAiwztj2yv6t7fglbJv88/UDYLBO+z2egWBdlmvce8FS/CxfImYG1v4Lrt/9u6vl TC5CkRlWPbwqg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0054F68A96; Sun, 14 Dec 2025 10:56:22 -0700 (MST) 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 SZpn1nrJW5Dk; Sun, 14 Dec 2025 10:56:21 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734976; bh=Tu3unAVyZiOi9sjZpkgFOgS4QnNBChuHRr0mX3StNrk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cj3ER8zuZaZbvIcb/To8JAho3eyJyTCMPzSkyHHB8dEgDVZ/O3nbmKo/ByHtgzAj/ 1cRJ1HHAqnut0fgZPNo5uY/UjKczJZXwt2zla2kz7mZIRyOjRsb00NkDW4/mtZoUVm S/+rogeqzZhaeVqkwHC4UGeE1rNWDSD1VcRKA4IoJeRexvKsuRvON0uKZ3E0A7oDCP nsuG757zTkSgaHx5rGRpO0DGk+TuQOWKt1GkJMFqRCJ0H3M0EtL8wvXXHM261QoWtZ HSZGsqaK1ovsT4e0clB8PhZ3OXMjeZhiJ9Nym/QLmwZl/x1BSvHfX5j6SspEhGK+yY xC3KiGG+X7t0w== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 59A0E68A91; Sun, 14 Dec 2025 10:56:16 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:42 -0700 Message-ID: <20251214175449.3799539-21-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: PBRIWRNZVSP6FGJZKNCWLK44C66MY2BQ X-Message-ID-Hash: PBRIWRNZVSP6FGJZKNCWLK44C66MY2BQ 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 20/21] test: fs: Update Python tests to call C implementations 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 Update test_basic.py to call the new C-based filesystem tests via the 'ut' command. This allows tests to run more directly, calling the actual FS layer, without having to go through the command interface and worrying about which filesystem command to use. Co-developed-by: Claude Signed-off-by: Simon Glass --- test/py/tests/test_fs/conftest.py | 4 +- test/py/tests/test_fs/test_basic.py | 346 ++++++++-------------------- 2 files changed, 98 insertions(+), 252 deletions(-) diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index 0205048e73a..5fc796097e3 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -198,8 +198,6 @@ def fs_obj_basic(request, u_boot_config): volume file name and a list of MD5 hashes. """ fs_type = request.param - fs_cmd_prefix = fstype_to_prefix(fs_type) - fs_cmd_write = 'save' if fs_type == 'fs_generic' or fs_type == 'exfat' else 'write' fs_img = '' fs_ubtype = fstype_to_ubname(fs_type) @@ -289,7 +287,7 @@ def fs_obj_basic(request, u_boot_config): pytest.skip('Setup failed for filesystem: ' + fs_type + '. {}'.format(err)) return else: - yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fs_img, md5val] + yield [fs_ubtype, fs_img, md5val] finally: call('rm -rf %s' % scratch_dir, shell=True) call('rm -f %s' % fs_img, shell=True) diff --git a/test/py/tests/test_fs/test_basic.py b/test/py/tests/test_fs/test_basic.py index 88b163ce305..7f805d04dd5 100644 --- a/test/py/tests/test_fs/test_basic.py +++ b/test/py/tests/test_fs/test_basic.py @@ -6,298 +6,146 @@ """ This test verifies basic read/write operation on file system. + +Tests are implemented in C (test/fs/fs_basic.c) and called from here. +Python handles filesystem image setup and environment variable configuration. """ import pytest -import re -from fstest_defs import * +from fstest_defs import SMALL_FILE, BIG_FILE from fstest_helpers import assert_fs_integrity -@pytest.mark.boardspec('sandbox') -@pytest.mark.slow -class TestFsBasic(object): - def test_fs1(self, ubman, fs_obj_basic): - """ - Test Case 1 - ls command, listing a root directory and invalid directory - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic - with ubman.log.section('Test Case 1a - ls'): - # Test Case 1 - ls - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sls host 0:0' % fs_cmd_prefix]) - assert(re.search('2621440000 *%s' % BIG_FILE, ''.join(output))) - assert(re.search('1048576 *%s' % SMALL_FILE, ''.join(output))) - with ubman.log.section('Test Case 1b - ls (invalid dir)'): - # In addition, test with a nonexistent directory to see if we crash. - output = ubman.run_command( - '%sls host 0:0 invalid_d' % fs_cmd_prefix) - assert('' == output) +def run_c_test(ubman, fs_type, fs_img, test_name, small=None, big=None, + md5val=None): + """Run a C unit test with proper setup. - with ubman.log.section('Test Case 1c - test -e'): - # Test Case 1 - test -e - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - 'test -e host 0:0 1MB.file && echo PASS']) - assert('PASS' in ''.join(output)) + Args: + ubman (ConsoleBase): U-Boot console manager + fs_type (str): Filesystem type (ext4, fat, fs_generic, exfat) + fs_img (str): Path to filesystem image + test_name (str): Name of C test function (without _norun suffix) + small (str): Filename of small test file (optional) + big (str): Filename of big test file (optional) + md5val (str): Expected MD5 value for verification (optional) - with ubman.log.section('Test Case 1d - test -e (invalid file)'): - # In addition, test with a nonexistent file to see if we crash. - output = ubman.run_command( - 'test -e host 0:0 2MB.file || echo PASS') - assert('PASS' in ''.join(output)) + Returns: + bool: True if test passed, False otherwise + """ + # Build the command with arguments + cmd = f'ut -f fs {test_name}_norun fs_type={fs_type} fs_image={fs_img}' + if small: + cmd += f' small={small}' + if big: + cmd += f' big={big}' + if md5val: + cmd += f' md5val={md5val}' - def test_fs2(self, ubman, fs_obj_basic): - """ - Test Case 2 - size command for a small file - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic - with ubman.log.section('Test Case 2a - size (small)'): - # 1MB is 0x0010 0000 - # Test Case 2a - size of small file - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%ssize host 0:0 /%s' % (fs_cmd_prefix, SMALL_FILE), - 'printenv filesize', - 'setenv filesize']) - assert('filesize=100000' in ''.join(output)) + # Run the C test + ubman.run_command(cmd) + + # Check result + result = ubman.run_command('echo $?') + return result.strip() == '0' + + +@pytest.mark.boardspec('sandbox') +@pytest.mark.slow +class TestFsBasic: + """Test basic filesystem operations via C unit tests.""" + + def test_fs1(self, ubman, fs_obj_basic): + """Test Case 1 - ls command, listing root and invalid directories""" + fs_type, fs_img, _ = fs_obj_basic + with ubman.log.section('Test Case 1 - ls'): + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_ls', + small=SMALL_FILE, big=BIG_FILE) - with ubman.log.section('Test Case 2b - size (/../)'): - # Test Case 2b - size of small file via a path using '..' - output = ubman.run_command_list([ - '%ssize host 0:0 /SUBDIR/../%s' % (fs_cmd_prefix, SMALL_FILE), - 'printenv filesize', - 'setenv filesize']) - assert('filesize=100000' in ''.join(output)) + def test_fs2(self, ubman, fs_obj_basic): + """Test Case 2 - size command for a small file""" + fs_type, fs_img, _ = fs_obj_basic + with ubman.log.section('Test Case 2 - size (small)'): + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_size_small', + small=SMALL_FILE) def test_fs3(self, ubman, fs_obj_basic): - """ - Test Case 3 - size command for a large file - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 3 - size command for a large file""" + fs_type, fs_img, _ = fs_obj_basic with ubman.log.section('Test Case 3 - size (large)'): - # 2.5GB (1024*1024*2500) is 0x9C40 0000 - # Test Case 3 - size of big file - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%ssize host 0:0 /%s' % (fs_cmd_prefix, BIG_FILE), - 'printenv filesize', - 'setenv filesize']) - assert('filesize=9c400000' in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_size_big', + big=BIG_FILE) def test_fs4(self, ubman, fs_obj_basic): - """ - Test Case 4 - load a small file, 1MB - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 4 - load a small file, 1MB""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 4 - load (small)'): - # Test Case 4a - Read full 1MB of small file - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s' % (fs_cmd_prefix, ADDR, SMALL_FILE), - 'printenv filesize']) - assert('filesize=100000' in ''.join(output)) - - # Test Case 4b - Read full 1MB of small file - output = ubman.run_command_list([ - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[0] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_load_small', + small=SMALL_FILE, md5val=md5val[0]) def test_fs5(self, ubman, fs_obj_basic): - """ - Test Case 5 - load, reading first 1MB of 3GB file - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 5 - load, reading first 1MB of 3GB file""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 5 - load (first 1MB)'): - # Test Case 5a - First 1MB of big file - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s %x 0x0' % (fs_cmd_prefix, ADDR, BIG_FILE, LENGTH), - 'printenv filesize']) - assert('filesize=100000' in ''.join(output)) - - # Test Case 5b - First 1MB of big file - output = ubman.run_command_list([ - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[1] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_load_big_first', + big=BIG_FILE, md5val=md5val[1]) def test_fs6(self, ubman, fs_obj_basic): - """ - Test Case 6 - load, reading last 1MB of 3GB file - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 6 - load, reading last 1MB of 3GB file""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 6 - load (last 1MB)'): - # fails for ext as no offset support - # Test Case 6a - Last 1MB of big file - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s %x 0x9c300000' - % (fs_cmd_prefix, ADDR, BIG_FILE, LENGTH), - 'printenv filesize']) - assert('filesize=100000' in ''.join(output)) - - # Test Case 6b - Last 1MB of big file - output = ubman.run_command_list([ - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[2] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_load_big_last', + big=BIG_FILE, md5val=md5val[2]) def test_fs7(self, ubman, fs_obj_basic): - """ - Test Case 7 - load, 1MB from the last 1MB in 2GB - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 7 - load, 1MB from the last 1MB in 2GB""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 7 - load (last 1MB in 2GB)'): - # fails for ext as no offset support - # Test Case 7a - One from the last 1MB chunk of 2GB - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s %x 0x7ff00000' - % (fs_cmd_prefix, ADDR, BIG_FILE, LENGTH), - 'printenv filesize']) - assert('filesize=100000' in ''.join(output)) - - # Test Case 7b - One from the last 1MB chunk of 2GB - output = ubman.run_command_list([ - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[3] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, + 'fs_test_load_big_2g_last', + big=BIG_FILE, md5val=md5val[3]) def test_fs8(self, ubman, fs_obj_basic): - """ - Test Case 8 - load, reading first 1MB in 2GB - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 8 - load, reading first 1MB in 2GB""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 8 - load (first 1MB in 2GB)'): - # fails for ext as no offset support - # Test Case 8a - One from the start 1MB chunk from 2GB - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s %x 0x80000000' - % (fs_cmd_prefix, ADDR, BIG_FILE, LENGTH), - 'printenv filesize']) - assert('filesize=100000' in ''.join(output)) - - # Test Case 8b - One from the start 1MB chunk from 2GB - output = ubman.run_command_list([ - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[4] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, + 'fs_test_load_big_2g_first', + big=BIG_FILE, md5val=md5val[4]) def test_fs9(self, ubman, fs_obj_basic): - """ - Test Case 9 - load, 1MB crossing 2GB boundary - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 9 - load, 1MB crossing 2GB boundary""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 9 - load (crossing 2GB boundary)'): - # fails for ext as no offset support - # Test Case 9a - One 1MB chunk crossing the 2GB boundary - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s %x 0x7ff80000' - % (fs_cmd_prefix, ADDR, BIG_FILE, LENGTH), - 'printenv filesize']) - assert('filesize=100000' in ''.join(output)) - - # Test Case 9b - One 1MB chunk crossing the 2GB boundary - output = ubman.run_command_list([ - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[5] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, + 'fs_test_load_big_2g_cross', + big=BIG_FILE, md5val=md5val[5]) def test_fs10(self, ubman, fs_obj_basic): - """ - Test Case 10 - load, reading beyond file end'): - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 10 - load, reading beyond file end""" + fs_type, fs_img, _ = fs_obj_basic with ubman.log.section('Test Case 10 - load (beyond file end)'): - # Generic failure case - # Test Case 10 - 2MB chunk from the last 1MB of big file - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s 0x00200000 0x9c300000' - % (fs_cmd_prefix, ADDR, BIG_FILE), - 'printenv filesize', - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert('filesize=100000' in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_load_beyond', + big=BIG_FILE) def test_fs11(self, ubman, fs_obj_basic): - """ - Test Case 11 - write' - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 11 - write""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 11 - write'): - # Read 1MB from small file - # Write it back to test the writes - # Test Case 11a - Check that the write succeeded - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s' % (fs_cmd_prefix, ADDR, SMALL_FILE), - '%s%s host 0:0 %x /%s.w $filesize' - % (fs_cmd_prefix, fs_cmd_write, ADDR, SMALL_FILE)]) - assert('1048576 bytes written' in ''.join(output)) - - # Test Case 11b - Check md5 of written to is same - # as the one read from - output = ubman.run_command_list([ - '%sload host 0:0 %x /%s.w' % (fs_cmd_prefix, ADDR, SMALL_FILE), - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[0] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_write', + small=SMALL_FILE, md5val=md5val[0]) assert_fs_integrity(fs_type, fs_img) def test_fs12(self, ubman, fs_obj_basic): - """ - Test Case 12 - write to "." directory - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 12 - write to "." directory""" + fs_type, fs_img, _ = fs_obj_basic with ubman.log.section('Test Case 12 - write (".")'): - # Next test case checks writing a file whose dirent - # is the first in the block, which is always true for "." - # The write should fail, but the lookup should work - # Test Case 12 - Check directory traversal - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%s%s host 0:0 %x /. 0x10' - % (fs_cmd_prefix, fs_cmd_write, ADDR)]) - assert('Unable to write' in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_write_dot') assert_fs_integrity(fs_type, fs_img) def test_fs13(self, ubman, fs_obj_basic): - """ - Test Case 13 - write to a file with "/./" - """ - fs_type,fs_cmd_prefix,fs_cmd_write,fs_img,md5val = fs_obj_basic + """Test Case 13 - write to a file with '/./'""" + fs_type, fs_img, md5val = fs_obj_basic with ubman.log.section('Test Case 13 - write ("./")'): - # Read 1MB from small file - # Write it via "same directory", i.e. "." dirent - # Test Case 13a - Check directory traversal - output = ubman.run_command_list([ - 'host bind 0 %s' % fs_img, - '%sload host 0:0 %x /%s' % (fs_cmd_prefix, ADDR, SMALL_FILE), - '%s%s host 0:0 %x /./%s2 $filesize' - % (fs_cmd_prefix, fs_cmd_write, ADDR, SMALL_FILE)]) - assert('1048576 bytes written' in ''.join(output)) - - # Test Case 13b - Check md5 of written to is same - # as the one read from - output = ubman.run_command_list([ - 'mw.b %x 00 100' % ADDR, - '%sload host 0:0 %x /./%s2' % (fs_cmd_prefix, ADDR, SMALL_FILE), - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[0] in ''.join(output)) - - # Test Case 13c - Check md5 of written to is same - # as the one read from - output = ubman.run_command_list([ - 'mw.b %x 00 100' % ADDR, - '%sload host 0:0 %x /%s2' % (fs_cmd_prefix, ADDR, SMALL_FILE), - 'md5sum %x $filesize' % ADDR, - 'setenv filesize']) - assert(md5val[0] in ''.join(output)) + assert run_c_test(ubman, fs_type, fs_img, 'fs_test_write_dotpath', + small=SMALL_FILE, md5val=md5val[0]) assert_fs_integrity(fs_type, fs_img) From patchwork Sun Dec 14 17:54:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 914 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=1765734986; bh=Kjidm9z/1+ZAFuCI0kF/zbQe5YBmJJ0jJY8nJKoeZjA=; 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=AzSs2pEWjYIDV0lSc3UnDskCY4V4l3StdqNQ5OFIabg2TteZUNNmuFTeHem0Lyo+M ji8dh5RUOBJYbaRxk5vag7Uyg3XbUgTZPpfL+JS0yLN/VUUZniKZ5ivpXoZ2prQKYH TMAZADoYq9Y6b8AVB0utlUhqsF/asiStJex9bQSsmj9SYV/ZyV/pCIUPt2HNmsDIPp V03vnVGpqWq8kN4quDJFm/+QBZoBrnlg7ixT50u4ZEAkZJZoIzLm1zavD0opMp2c1e ZwZdHsdg243EPHAJQzd9dIS/Vdxdu9fD0fzYBXFNKPvy7Eee70GNeJdzye5sVKfkY6 FKBKsYdFL6xmQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 79D2068A91 for ; Sun, 14 Dec 2025 10:56:26 -0700 (MST) 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 NlXgNIwCrjqp for ; Sun, 14 Dec 2025 10:56:26 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734984; bh=Kjidm9z/1+ZAFuCI0kF/zbQe5YBmJJ0jJY8nJKoeZjA=; 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=DJ0QDYmApF6gy4KuOhYWjOZq1rmG3Bm3FSn3vmPfdOgHV0FbWvgqQvDiUIZT6m148 pFWX748gucfZnK2ICfAxVM6WCDq+DWXGOhfSyAUykvmV60+Sb+7Ws9Eln6PZ/ctXMh Kd8O40C6+EL7YwxvkLVqiP0jvNdqoxoZOJElJ7aJk7n8ZmeKbRc8J3H+fS0BTlRSfn cxZ9b1SU/vvkG4iHRSca3ZpJQoHC5dr0Sc6Nc+gcWRc2nB9LAh/57DegfWXzG6y9mw cL99WNrEY74tCFBMUkh6jC1dOHznXojhjyAzS9ijLrNgHPIYnTlz7S2eOz582ogfbj 6LHyNBM/7oSWw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DC0FB68ADF for ; Sun, 14 Dec 2025 10:56:24 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734982; bh=PfiVZHeRs3EsMW/O32ROycf/19qudrdYWmUyVc5l+6o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iNQNX1ZLATLLsdUeKcpup8TXNTLnNFYb/Xxy29g4jL73vI4NiiOqsTLGewuGkou2E NWea7MyPnK+xBMdhd9zVzA+yuRENoj5N3/+KiDpZq2HiMK7w9xCeaKnVTJ5H4XrO7y qYPdVFE10n5qN73ooiZ/F8MbonFbRIUrFk736PiY2TgARUJSjvCO+oUj6Gh8HNvWIa ubYLabG0UrqwSiODWWHTKwuj+jy6BQFjRAEu5WZ/ikDnBaEl0YAqcTLp1QhQ5WBDpK 68FiMgeyQnLKYWCPWCLQYa57klttfYVtyvLUfxVy4oXHRu1+ea0V3BYV+rgjzxdhI4 nCevSZOQ+Xoww== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 0554B68A91; Sun, 14 Dec 2025 10:56:22 -0700 (MST) 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 8bJeIqjI3YPP; Sun, 14 Dec 2025 10:56:21 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734981; bh=z1LoqfKvIzpUFgZq2RPYajvfyI3qxK6wlqcgzW1JhG0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UAZ3ixtZIkAJ6PCAEJgljcrxnbF/mA3aqO3KBuKq/K3+hI0EfyLSzAGI/gf032iJC 7RlCVkBjT8cEs89on8gAfnUqZup5QKZYq9w1kuFIuvVshquqC8MgD2YLGFPv1N2Cuc I4+OKL80S0a1q6kzYTU1qGgdf+ESKE2PJ1y0Is7peWD8SwimHUbl3SP8ithvluEayy eXBZDAPNlyhngFzzxpE/OuW1ykciMb47gN532FB55h071BnwaYhMqflRe9pRCrw2cm /sVh1LtmXRnoBZygJ2hce2zpKTAiwdspSG8Tggoq0RrSMja7Sqt9iS2JO3Pi4PWURr ffTA8k49Qc+HQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 517E268A84; Sun, 14 Dec 2025 10:56:21 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:43 -0700 Message-ID: <20251214175449.3799539-22-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: SUJFOS37HNFGQBD5JKBIC2HV75QSUG3R X-Message-ID-Hash: SUJFOS37HNFGQBD5JKBIC2HV75QSUG3R 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: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 21/21] test: Add documentation for test parameters 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 Add a description of how test parameters work. This helps to make it easier to write C tests which need setup to be done in Python. Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/tests_writing.rst | 41 +++++++++++++++++++++++++++++++++++ doc/usage/cmd/ut.rst | 11 ++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst index 6842533e2c6..d322cf60e26 100644 --- a/doc/develop/tests_writing.rst +++ b/doc/develop/tests_writing.rst @@ -101,6 +101,47 @@ constructs, in this case to check that the expected things happened in the Python test. +Passing arguments to C tests +---------------------------- + +Sometimes a C test needs parameters from Python, such as filenames or expected +values that are generated at runtime. The test-argument feature allows this. + +Use the `UNIT_TEST_ARGS` macro to declare a test with arguments:: + + static int my_test_norun(struct unit_test_state *uts) + { + const char *filename = ut_str(0); + int count = ut_int(1); + + /* test code using filename and count */ + + return 0; + } + UNIT_TEST_ARGS(my_test_norun, UTF_CONSOLE | UTF_MANUAL, my_suite, + { "filename", UT_ARG_STR }, + { "count", UT_ARG_INT }); + +Each argument definition specifies a name and type: + +- `UT_ARG_STR` - string argument, accessed via `ut_str(n)` +- `UT_ARG_INT` - integer argument, accessed via `ut_int(n)` +- `UT_ARG_BOOL` - boolean argument, accessed via `ut_bool(n)` + (use `1` for true, any other value for false) + +Arguments are passed on the command line in `name=value` format:: + + ut -f my_suite my_test_norun filename=/path/to/file count=42 + +From Python, you can call the test like this:: + + cmd = f'ut -f my_suite my_test_norun filename={filepath} count={count}' + ubman.run_command(cmd) + +This approach combines Python's flexibility for setup (creating files, +generating values) with C's speed and debuggability for the actual test logic. + + How slow are Python tests? -------------------------- diff --git a/doc/usage/cmd/ut.rst b/doc/usage/cmd/ut.rst index d8c3cbf496c..a26ee6ad7de 100644 --- a/doc/usage/cmd/ut.rst +++ b/doc/usage/cmd/ut.rst @@ -11,7 +11,7 @@ Synopsis :: - ut [-r] [-f] [-I:] [ | all []] [...] + ut [-r] [-f] [-R] [-I:] [ | all []] [...] ut [-s] info Description @@ -37,10 +37,17 @@ test causes another test to fail. If the one test fails, testing stops immediately. +-R + Preserve console recording on test failure. Normally when a test fails, + console recording is disabled so error messages go directly to output. + This flag keeps recording enabled, which is useful when testing the test + framework itself. + args Optional arguments to pass to the test, in `name=value` format. These are used by tests declared with `UNIT_TEST_ARGS()` which define expected - argument names and types. + argument names and types. See :ref:`develop/tests_writing:passing arguments + to c tests` for details. Typically the command is run on :ref:`arch/sandbox/sandbox:sandbox` since it includes a near-complete set of emulators, no code-size limits, many CONFIG