git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 2/1] t-strvec: improve check_strvec() output

From
René Scharfe <l.s.r@web.de>
Date
Jul 14, 2024, 17:06 UTC
Message-ID
<f2bcee2b-88fa-4dcd-8247-f68d842c6a4c@web.de>
In-Reply-To
<983be396-f47c-4573-8c33-af8367f8ddbe@web.de>

The macro check_strvec calls the function check_strvec_loc(), which performs the actual checks. They report the line number inside that function on error, which is not very helpful. Before the previous patch half of them triggered an assertion that reported the caller's line number using a custom message, which was more useful, but a bit awkward.

Improve the output by getting rid of check_strvec_loc() and performing all checks within check_strvec, as they then report the line number of the call site, aiding in finding the broken test. Determine the number of items and check it up front to avoid having to do them both in the loop and at the end.

Sanity check the expected items to make sure there are any and that the last one is NULL, as the compiler no longer does that for us with the removal of the function attribute LAST_ARG_MUST_BE_NULL.

Use only the actual strvec name passed to the macro, the internal "expect" array name and an index "i" in the output, for clarity. While "expect" does not exist at the call site, it's reasonably easy to infer that it's referring to the NULL-terminated list of expected strings, converted to an array.

Here's the output with less items than expected in the strvec before:
 # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
 #    left: 1
 #   right: 1
... and with the patch:
 # check "(&vec)->nr == ARRAY_SIZE(expect) - 1" failed at t/unit-tests/t-strvec.c:53
 #    left: 1
 #   right: 2
With too many items in the strvec we got before:
 # check "vec->nr == nr" failed at t/unit-tests/t-strvec.c:34
 #    left: 1
 #   right: 0
 # check "vec->v[nr] == NULL" failed at t/unit-tests/t-strvec.c:36
 #    left: 0x6000004b8010
 #   right: 0x0
... and with the patch:
 # check "(&vec)->nr == ARRAY_SIZE(expect) - 1" failed at t/unit-tests/t-strvec.c:53
 #    left: 1
 #   right: 0
A broken alloc value was reported like this:
 # check "vec->alloc > nr" failed at t/unit-tests/t-strvec.c:20
 #    left: 0
 #   right: 0
 ... and with the patch:
 # check "(&vec)->nr <= (&vec)->alloc" failed at t/unit-tests/t-strvec.c:56
 #    left: 2
 #   right: 0
An unexpected string value was reported like this:
 # check "!strcmp(vec->v[nr], str)" failed at t/unit-tests/t-strvec.c:24
 #    left: "foo"
 #   right: "bar"
 #      nr: 0
... and with the patch:
 # check "!strcmp((&vec)->v[i], expect[i])" failed at t/unit-tests/t-strvec.c:53
 #    left: "foo"
 #   right: "bar"
 #       i: 0
If the strvec is not NULL terminated, we got:
 # check "vec->v[nr] == NULL" failed at t/unit-tests/t-strvec.c:36
 #    left: 0x102c3abc8
 #   right: 0x0
... and with the patch we get the line number of the caller:
 # check "!strcmp((&vec)->v[i], expect[i])" failed at t/unit-tests/t-strvec.c:53
 #    left: "bar"
 #   right: NULL
 #       i: 1

check_strvec calls without a trailing NULL were detected at compile time before:

 t/unit-tests/t-strvec.c:71:2: error: missing sentinel in function call [-Werror,-Wsentinel]
... and with the patch it's only found at runtime:
 # check "expect[ARRAY_SIZE(expect) - 1] == NULL" failed at t/unit-tests/t-strvec.c:53
 #    left: 0x100e5a663
 #   right: 0x0

We can let check_strvec add the terminating NULL for us and remove it from callers, making it impossible to forget. Leave that conversion for a future patch, though, since this reimplementation is already intrusive enough.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
---
For next, on top of c6f35e529e t-strvec: use test_msg().
 t/unit-tests/t-strvec.c | 46 +++++++++++++----------------------------
 1 file changed, 14 insertions(+), 32 deletions(-)
diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index 236203af61..fdb28ba220 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -3,38 +3,20 @@
 #include "strvec.h"

 #define check_strvec(vec, ...) \
-	check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__)
-LAST_ARG_MUST_BE_NULL
-static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
-{
-	va_list ap;
-	size_t nr = 0;
-
-	va_start(ap, vec);
-	while (1) {
-		const char *str = va_arg(ap, const char *);
-		if (!str)
-			break;
-
-		if (!check_uint(vec->nr, >, nr) ||
-		    !check_uint(vec->alloc, >, nr)) {
-			va_end(ap);
-			return;
-		}
-		if (!check_str(vec->v[nr], str)) {
-			test_msg("     nr: %"PRIuMAX, (uintmax_t)nr);
-			va_end(ap);
-			return;
-		}
-
-		nr++;
-	}
-	va_end(ap);
-
-	check_uint(vec->nr, ==, nr);
-	check_uint(vec->alloc, >=, nr);
-	check_pointer_eq(vec->v[nr], NULL);
-}
+	do { \
+		const char *expect[] = { __VA_ARGS__ }; \
+		if (check_uint(ARRAY_SIZE(expect), >, 0) && \
+		    check_pointer_eq(expect[ARRAY_SIZE(expect) - 1], NULL) && \
+		    check_uint((vec)->nr, ==, ARRAY_SIZE(expect) - 1) && \
+		    check_uint((vec)->nr, <=, (vec)->alloc)) { \
+			for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \
+				if (!check_str((vec)->v[i], expect[i])) { \
+					test_msg("      i: %"PRIuMAX, i); \
+					break; \
+				} \
+			} \
+		} \
+	} while (0)

 static void t_static_init(void)
 {
--
2.45.2
Previous: René ScharfeNext: Junio C Hamano
Message 9 of 20 in “t-strvec: use test_msg()”
  1. t-strvec: use test_msg()René Scharfe, Jul 4, 2024
  2. Eric SunshineJul 4, 2024
  3. Phillip WoodJul 5, 2024
  4. t-strvec: use test_msg()René Scharfe, Jul 5, 2024
  5. Jeff KingJul 9, 2024
  6. René ScharfeJul 14, 2024
  7. Jeff KingJul 16, 2024
  8. René ScharfeJul 16, 2024
  9. 2/1 t-strvec: improve check_strvec() outputRené Scharfe, Jul 14, 2024
  10. Junio C HamanoJul 15, 2024
  11. 3/1 t-strvec: tighten .alloc check in check_strvecRené Scharfe, Jul 14, 2024
  12. Junio C HamanoJul 15, 2024
  13. René ScharfeJul 15, 2024
  14. Junio C HamanoJul 15, 2024
  15. t-strvec: improve check_strvec() outputRené Scharfe, Jul 14, 2024
  16. René ScharfeJul 14, 2024
  17. Jeff KingJul 16, 2024
  18. Junio C HamanoJul 16, 2024
  19. t-strvec: fix type mismatch in check_strvecRené Scharfe, Jul 16, 2024
  20. Junio C HamanoJul 16, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.