From patchwork Wed Dec 10 00:06:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 865 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=1765325324; bh=MQ3McUJ6v+muWQJVt2mTlBYYSeQcDNQAzNOiET8+524=; 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=FC39N6HsHPuu8LyRDJtZE3XhmMDxlEd+WuH8rN26ZlKmjPWm+3gSwRkY0V4gVTeQH c0X+HcBuEPM1ohp2qDDUnvKB+Eutj9kyw8AC4Ge5QvbBCJhGtpjftZe38jKfQxNyb9 P1KafBzxRJxFPJqkXUY65yvlX6FgkY4G4qy5SJi0cn/cFGm7s5Bl8+PXC8MWitOKvH I5pG7uVswlt/MniDI8DaitaA57z9jXG+HqiwkB/LFaI8UAdfykc0KTbk0QeacF4utE q3CSsbovxlKPECA0aO4AddIyLonsdo5jeRJmp+bdpW2LKw0c18kxMe/ZEoue6/P9C3 0kYVIVcrV0gow== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id F1E1368974 for ; Tue, 9 Dec 2025 17:08:44 -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 uSdZcczH2wse for ; Tue, 9 Dec 2025 17:08:44 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765325324; bh=MQ3McUJ6v+muWQJVt2mTlBYYSeQcDNQAzNOiET8+524=; 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=FC39N6HsHPuu8LyRDJtZE3XhmMDxlEd+WuH8rN26ZlKmjPWm+3gSwRkY0V4gVTeQH c0X+HcBuEPM1ohp2qDDUnvKB+Eutj9kyw8AC4Ge5QvbBCJhGtpjftZe38jKfQxNyb9 P1KafBzxRJxFPJqkXUY65yvlX6FgkY4G4qy5SJi0cn/cFGm7s5Bl8+PXC8MWitOKvH I5pG7uVswlt/MniDI8DaitaA57z9jXG+HqiwkB/LFaI8UAdfykc0KTbk0QeacF4utE q3CSsbovxlKPECA0aO4AddIyLonsdo5jeRJmp+bdpW2LKw0c18kxMe/ZEoue6/P9C3 0kYVIVcrV0gow== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 9D27768947 for ; Tue, 9 Dec 2025 17:08:44 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765325320; bh=NMwKenp0lHoltW2sWnZL9eoXEykQlpDBVotNnhQ3MlE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uI1bPyllIAb6JfSt5JBIf8oYUaJsnQTcCImmlUQh2x/FG89sb9Rv7SmaJGmjWYNxF TqN5qEmK27txyCgOqUolmgzHV3GFzDuCetEa7uxV875v2L/66VxB9HcrLQ9L5Dzzuk ibdlJiPt6YPNAtNn57MLJn4oDjWBvVpl7Imn4Sw0BnYWuYNuvvn2Lg3RHv17qm24fu itmUFSoplfXvIK9BwPYajIsXJ9g8x39050TOioZ3myF3R+Bos+B+NC9APNdMBg4jls VGSjMRWZv+PrlUHCWkNDigg4Ac5koCinPR2pM/liD2AXBiZvxEksWktZaq9i5UInPE oy4fcjpmE0WlA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 409E168A22; Tue, 9 Dec 2025 17:08:40 -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 vKMcAKhkciuH; Tue, 9 Dec 2025 17:08:40 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765325314; bh=Oc4XW6U3l/Abzn7VyPCNREWFYoMbVhaPkj9St5V4LfE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=v1US6jCG1UM6pseXUcFeFi5fvcUzpE/aswj604uBwZiLwfjb1llOoibcMUMdxkZPG NVUK1G4VlVWR8zhfcUubaBtjjMGjcosaCZddDck/3Z4KUO62d7AT266rVj+CDMufcZ rkjV7yE0nTkZ39nc85a09VbrlejcmlOO4L1EJ1b7R5v9zkFugUZGWjPjuPyFwbVnZA 8zRIrCDfIxi6Udg1z4jT4MVGHh+ds9/t9iqQYwloCQxPaaaG5ntV1YyNJbRM171oqx gb4UvCu/Kdhw/pWAUCbqL3G/b60/SZ5vGd1Pk7KLHwX9v1MlOz2M7mWN++9W+tnV0Y CyeBiD+KV8ciw== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 270C968972; Tue, 9 Dec 2025 17:08:34 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Tue, 9 Dec 2025 17:06:59 -0700 Message-ID: <20251210000737.180797-9-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251210000737.180797-1-sjg@u-boot.org> References: <20251210000737.180797-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: WG2ONOTGUHRTLJQPLOECTUQ74OLFRVLO X-Message-ID-Hash: WG2ONOTGUHRTLJQPLOECTUQ74OLFRVLO 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/35] test: Add ut_asserteq_regex() for regex pattern matching 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 assertion macro ut_asserteq_regex() that checks if a string matches a regular expression pattern using the SLRE library. This is useful for tests where exact string-matching is difficult, such as when output contains line numbers or other variable content. Use a helper function ut_check_regex() to avoid including slre.h in the header. Co-developed-by: Claude Signed-off-by: Simon Glass --- doc/develop/tests_writing.rst | 5 +++++ include/test/ut.h | 29 +++++++++++++++++++++++++++++ test/ut.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst index 31454aa4819..43756989d43 100644 --- a/doc/develop/tests_writing.rst +++ b/doc/develop/tests_writing.rst @@ -422,6 +422,11 @@ ut_asserteq_addr(expr1, expr2) Assert that two addresses (converted from pointers via map_to_sysmem()) are equal +ut_asserteq_regex(pattern, str) + Assert that a string matches a regular expression pattern. Uses the SLRE + library for regex matching. Useful when exact matching is fragile, e.g. + when output contains line numbers or variable content. + Pointer assertions ~~~~~~~~~~~~~~~~~~ diff --git a/include/test/ut.h b/include/test/ut.h index 70eaaea5e0e..a2b42cdf414 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -13,6 +13,9 @@ #include #include +/* Size of error buffer for ut_check_regex() */ +#define UT_REGEX_ERR_SIZE 256 + struct unit_test_state; /** @@ -41,6 +44,16 @@ void ut_failf(struct unit_test_state *uts, const char *fname, int line, const char *func, const char *cond, const char *fmt, ...) __attribute__ ((format (__printf__, 6, 7))); +/** + * ut_check_regex() - Check if a string matches a regex pattern + * + * @pattern: Regular expression pattern + * @str: String to match against + * @err: Buffer to hold error message on failure (UT_REGEX_ERR_SIZE bytes) + * Return: 0 if match, -EINVAL if pattern is invalid, -ENOENT if no match + */ +int ut_check_regex(const char *pattern, const char *str, char *err); + /** * ut_check_console_line() - Check the next console line against expectations * @@ -254,6 +267,22 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); __ret; \ }) +/* Assert that a string matches a regex pattern */ +#define ut_asserteq_regex(pattern, str) ({ \ + const char *_pattern = (pattern), *_str = (str); \ + char _err[UT_REGEX_ERR_SIZE]; \ + int __ret = 0; \ + \ + __ret = ut_check_regex(_pattern, _str, _err); \ + if (__ret) { \ + ut_failf(uts, __FILE__, __LINE__, __func__, \ + #pattern " matches " #str, "%s", _err); \ + if (!uts->soft_fail) \ + return CMD_RET_FAILURE; \ + } \ + __ret; \ +}) + /* Assert that two memory areas are equal */ #define ut_asserteq_mem(expr1, expr2, len) ({ \ const u8 *_val1 = (u8 *)(expr1), *_val2 = (u8 *)(expr2); \ diff --git a/test/ut.c b/test/ut.c index a16fdfb3a93..b4f2a8bf40f 100644 --- a/test/ut.c +++ b/test/ut.c @@ -6,7 +6,10 @@ */ #include +#include #include +#include +#include #ifdef CONFIG_SANDBOX #include #endif @@ -38,6 +41,33 @@ void ut_failf(struct unit_test_state *uts, const char *fname, int line, uts->cur.fail_count++; } +int ut_check_regex(const char *pattern, const char *str, char *err) +{ + struct slre slre; + + if (!pattern || !str) { + snprintf(err, UT_REGEX_ERR_SIZE, + "NULL value: pattern=%s, str=%s", + pattern ? pattern : "(null)", + str ? str : "(null)"); + return -EINVAL; + } + + if (!slre_compile(&slre, pattern)) { + snprintf(err, UT_REGEX_ERR_SIZE, + "Invalid regex '%s': %s", pattern, slre.err_str); + return -EINVAL; + } + + if (!slre_match(&slre, str, strlen(str), NULL)) { + snprintf(err, UT_REGEX_ERR_SIZE, + "No match: pattern '%s', str '%s'", pattern, str); + return -ENOENT; + } + + return 0; +} + ulong ut_check_free(void) { struct mallinfo info = mallinfo();