git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] t-strvec: use test_msg()
@ 2024-07-04 18:04 René Scharfe
  2024-07-04 18:31 ` Eric Sunshine
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: René Scharfe @ 2024-07-04 18:04 UTC (permalink / raw)
  To: Git List; +Cc: Patrick Steinhardt, Phillip Wood

check_strvec_loc() checks each the strvec item by looping through them
and comparing them with expected values.  If a check fails then we'd
like to know which item is affected.  It reports that information by
building a strbuf and delivering its contents using a failing assertion.

Here's an example in which there are less items in the strvec than
expected; the index of the missing item is reported in the last line:

   # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
   #    left: 1
   #   right: 1
   # check "strvec index 1" failed at t/unit-tests/t-strvec.c:71

Note that it is also reported in the third line, i.e. the variable
"nr" contains that index.

Stop printing the index explicitly for checks that already report it.
The message for the same condition as above becomes:

   # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
   #    left: 1
   #   right: 1

For the string comparison, whose error message doesn't include the
index, report it using the simpler and more appropriate test_msg()
instead.  Report the index using its actual name and format the line
like the preceding ones.  The message for an unexpected string value
becomes:

   # check "!strcmp(vec->v[nr], str)" failed at t/unit-tests/t-strvec.c:24
   #    left: "foo"
   #   right: "bar"
   #      nr: 0

Reported-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 t/unit-tests/t-strvec.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index d4615ab06d..236203af61 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -17,12 +17,12 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
 			break;

 		if (!check_uint(vec->nr, >, nr) ||
-		    !check_uint(vec->alloc, >, nr) ||
-		    !check_str(vec->v[nr], str)) {
-			struct strbuf msg = STRBUF_INIT;
-			strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
-			test_assert(loc, msg.buf, 0);
-			strbuf_release(&msg);
+		    !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;
 		}
--
2.45.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH] t-strvec: use test_msg()
  2024-07-04 18:04 [PATCH] t-strvec: use test_msg() René Scharfe
@ 2024-07-04 18:31 ` Eric Sunshine
  2024-07-05  9:44 ` Phillip Wood
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Eric Sunshine @ 2024-07-04 18:31 UTC (permalink / raw)
  To: René Scharfe; +Cc: Git List, Patrick Steinhardt, Phillip Wood

On Thu, Jul 4, 2024 at 2:04 PM René Scharfe <l.s.r@web.de> wrote:
> check_strvec_loc() checks each the strvec item by looping through them

s/each the/each/

> and comparing them with expected values.  If a check fails then we'd
> like to know which item is affected.  It reports that information by
> building a strbuf and delivering its contents using a failing assertion.
>
> Here's an example in which there are less items in the strvec than

s/less/fewer/

> expected; the index of the missing item is reported in the last line:
>
>    # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
>    #    left: 1
>    #   right: 1
>    # check "strvec index 1" failed at t/unit-tests/t-strvec.c:71
>
> Note that it is also reported in the third line, i.e. the variable
> "nr" contains that index.
>
> Stop printing the index explicitly for checks that already report it.
> The message for the same condition as above becomes:
>
>    # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
>    #    left: 1
>    #   right: 1
>
> For the string comparison, whose error message doesn't include the
> index, report it using the simpler and more appropriate test_msg()
> instead.  Report the index using its actual name and format the line
> like the preceding ones.  The message for an unexpected string value
> becomes:
>
>    # check "!strcmp(vec->v[nr], str)" failed at t/unit-tests/t-strvec.c:24
>    #    left: "foo"
>    #   right: "bar"
>    #      nr: 0
>
> Reported-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---

Missing sign-off.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] t-strvec: use test_msg()
  2024-07-04 18:04 [PATCH] t-strvec: use test_msg() René Scharfe
  2024-07-04 18:31 ` Eric Sunshine
@ 2024-07-05  9:44 ` Phillip Wood
  2024-07-05 17:03 ` [PATCH v2] " René Scharfe
  2024-07-14 10:17 ` [PATCH v3] t-strvec: improve check_strvec() output René Scharfe
  3 siblings, 0 replies; 20+ messages in thread
From: Phillip Wood @ 2024-07-05  9:44 UTC (permalink / raw)
  To: René Scharfe, Git List; +Cc: Patrick Steinhardt, Phillip Wood

Hi René

Thanks for working on this, this looks good modulo Eric's suggestions

Best Wishes

Phillip

On 04/07/2024 19:04, René Scharfe wrote:
> check_strvec_loc() checks each the strvec item by looping through them
> and comparing them with expected values.  If a check fails then we'd
> like to know which item is affected.  It reports that information by
> building a strbuf and delivering its contents using a failing assertion.
> 
> Here's an example in which there are less items in the strvec than
> expected; the index of the missing item is reported in the last line:
> 
>     # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
>     #    left: 1
>     #   right: 1
>     # check "strvec index 1" failed at t/unit-tests/t-strvec.c:71
> 
> Note that it is also reported in the third line, i.e. the variable
> "nr" contains that index.
> 
> Stop printing the index explicitly for checks that already report it.
> The message for the same condition as above becomes:
> 
>     # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
>     #    left: 1
>     #   right: 1
> 
> For the string comparison, whose error message doesn't include the
> index, report it using the simpler and more appropriate test_msg()
> instead.  Report the index using its actual name and format the line
> like the preceding ones.  The message for an unexpected string value
> becomes:
> 
>     # check "!strcmp(vec->v[nr], str)" failed at t/unit-tests/t-strvec.c:24
>     #    left: "foo"
>     #   right: "bar"
>     #      nr: 0
> 
> Reported-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>   t/unit-tests/t-strvec.c | 12 ++++++------
>   1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
> index d4615ab06d..236203af61 100644
> --- a/t/unit-tests/t-strvec.c
> +++ b/t/unit-tests/t-strvec.c
> @@ -17,12 +17,12 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
>   			break;
> 
>   		if (!check_uint(vec->nr, >, nr) ||
> -		    !check_uint(vec->alloc, >, nr) ||
> -		    !check_str(vec->v[nr], str)) {
> -			struct strbuf msg = STRBUF_INIT;
> -			strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
> -			test_assert(loc, msg.buf, 0);
> -			strbuf_release(&msg);
> +		    !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;
>   		}
> --
> 2.45.2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2] t-strvec: use test_msg()
  2024-07-04 18:04 [PATCH] t-strvec: use test_msg() René Scharfe
  2024-07-04 18:31 ` Eric Sunshine
  2024-07-05  9:44 ` Phillip Wood
@ 2024-07-05 17:03 ` René Scharfe
  2024-07-09 11:32   ` Jeff King
                     ` (2 more replies)
  2024-07-14 10:17 ` [PATCH v3] t-strvec: improve check_strvec() output René Scharfe
  3 siblings, 3 replies; 20+ messages in thread
From: René Scharfe @ 2024-07-05 17:03 UTC (permalink / raw)
  To: Git List; +Cc: Patrick Steinhardt, Phillip Wood, Eric Sunshine

check_strvec_loc() checks each strvec item by looping through them and
comparing them with expected values.  If a check fails then we'd like
to know which item is affected.  It reports that information by building
a strbuf and delivering its contents using a failing assertion, e.g.
if there are fewer items in the strvec than expected:

   # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
   #    left: 1
   #   right: 1
   # check "strvec index 1" failed at t/unit-tests/t-strvec.c:71

Note that the index variable is "nr" and thus the interesting value is
reported twice in that example (in lines three and four).

Stop printing the index explicitly for checks that already report it.
The message for the same condition as above becomes:

   # check "vec->nr > nr" failed at t/unit-tests/t-strvec.c:19
   #    left: 1
   #   right: 1

For the string comparison, whose error message doesn't include the
index, report it using the simpler and more appropriate test_msg()
instead.  Report the index using its actual variable name and format the
line like the preceding ones.  The message for an unexpected string
value becomes:

   # check "!strcmp(vec->v[nr], str)" failed at t/unit-tests/t-strvec.c:24
   #    left: "foo"
   #   right: "bar"
   #      nr: 0

Reported-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: René Scharfe <l.s.r@web.de>
---
Changes since v1:
- Typo fix.
- Grammar fix.
- Reworded problem description for brevity.
- Qualify "name" in the last paragraph for clarity.
- Add sign-off.
- No code changes.

Thank you, Eric!

 t/unit-tests/t-strvec.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index d4615ab06d..236203af61 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -17,12 +17,12 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
 			break;

 		if (!check_uint(vec->nr, >, nr) ||
-		    !check_uint(vec->alloc, >, nr) ||
-		    !check_str(vec->v[nr], str)) {
-			struct strbuf msg = STRBUF_INIT;
-			strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
-			test_assert(loc, msg.buf, 0);
-			strbuf_release(&msg);
+		    !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;
 		}
--
2.45.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2] t-strvec: use test_msg()
  2024-07-05 17:03 ` [PATCH v2] " René Scharfe
@ 2024-07-09 11:32   ` Jeff King
  2024-07-14 10:17     ` René Scharfe
  2024-07-14 17:06   ` [PATCH v2 2/1] t-strvec: improve check_strvec() output René Scharfe
  2024-07-14 17:06   ` [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec René Scharfe
  2 siblings, 1 reply; 20+ messages in thread
From: Jeff King @ 2024-07-09 11:32 UTC (permalink / raw)
  To: René Scharfe
  Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine

On Fri, Jul 05, 2024 at 07:03:36PM +0200, René Scharfe wrote:

> diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
> index d4615ab06d..236203af61 100644
> --- a/t/unit-tests/t-strvec.c
> +++ b/t/unit-tests/t-strvec.c
> @@ -17,12 +17,12 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
>  			break;
> 
>  		if (!check_uint(vec->nr, >, nr) ||
> -		    !check_uint(vec->alloc, >, nr) ||
> -		    !check_str(vec->v[nr], str)) {
> -			struct strbuf msg = STRBUF_INIT;
> -			strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
> -			test_assert(loc, msg.buf, 0);
> -			strbuf_release(&msg);
> +		    !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;
>  		}

The "loc" parameter to the function is now unused. Should it be removed,
or is it a bug that we are no longer reporting the caller's location?
Should we be using check_str_loc() in the post-image?

-Peff

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2] t-strvec: use test_msg()
  2024-07-09 11:32   ` Jeff King
@ 2024-07-14 10:17     ` René Scharfe
  2024-07-16  1:43       ` Jeff King
  0 siblings, 1 reply; 20+ messages in thread
From: René Scharfe @ 2024-07-14 10:17 UTC (permalink / raw)
  To: Jeff King; +Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine

Am 09.07.24 um 13:32 schrieb Jeff King:
> On Fri, Jul 05, 2024 at 07:03:36PM +0200, René Scharfe wrote:
>
>> diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
>> index d4615ab06d..236203af61 100644
>> --- a/t/unit-tests/t-strvec.c
>> +++ b/t/unit-tests/t-strvec.c
>> @@ -17,12 +17,12 @@ static void check_strvec_loc(const char *loc, struct strvec *vec, ...)
>>  			break;
>>
>>  		if (!check_uint(vec->nr, >, nr) ||
>> -		    !check_uint(vec->alloc, >, nr) ||
>> -		    !check_str(vec->v[nr], str)) {
>> -			struct strbuf msg = STRBUF_INIT;
>> -			strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
>> -			test_assert(loc, msg.buf, 0);
>> -			strbuf_release(&msg);
>> +		    !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;
>>  		}
>
> The "loc" parameter to the function is now unused. Should it be removed,
> or is it a bug that we are no longer reporting the caller's location?

It's a bug.  If only there was a way to detect such an unused parameter
automatically.. ;->

> Should we be using check_str_loc() in the post-image?

Yes, and check_uint_loc() and check_pointer_eq_loc() as well.  Which
would be a pain.  Or we drag everything into the macro check_strvec and
get the caller's line number for free.

René

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3] t-strvec: improve check_strvec() output
  2024-07-04 18:04 [PATCH] t-strvec: use test_msg() René Scharfe
                   ` (2 preceding siblings ...)
  2024-07-05 17:03 ` [PATCH v2] " René Scharfe
@ 2024-07-14 10:17 ` René Scharfe
  2024-07-14 17:06   ` René Scharfe
  2024-07-16  4:37   ` Jeff King
  3 siblings, 2 replies; 20+ messages in thread
From: René Scharfe @ 2024-07-14 10:17 UTC (permalink / raw)
  To: Git List; +Cc: Patrick Steinhardt, Phillip Wood, Jeff King

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.  Half of them trigger
an assertion with a custom message that reports the line of the
check_strvec call, which is 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 its referring to the NULL-terminated list of expected strings,
converted to an array.  Align the "i" with previous lines in the output.

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
 # check "strvec index 1" failed at t/unit-tests/t-strvec.c:71

... and with the patch we get the more concise and still comprehensive:

 # 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: 0x6000019a40b0
 #   right: 0x0

... and with the patch we get the more concise and informative output
that includes the caller's line number:

 # 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
 # check "strvec index 0" failed at t/unit-tests/t-strvec.c:74

 ... and with the patch:

 # check "(&vec)->nr <= (&vec)->alloc" failed at t/unit-tests/t-strvec.c:56
 #    left: 2
 #   right: 0

Note that .alloc == .nr is only valid if the strvec is empty, but
check_strvec doesn't detect this error with or without this patch.
Leave that for later.

An unexpected string value was reported like this:

 # check "!strcmp(vec->v[nr], str)" failed at t/unit-tests/t-strvec.c:21
 #    left: "foo"
 #   right: "bar"
 # check "strvec index 0" failed at t/unit-tests/t-strvec.c:71

... and with the patch we get:

 # 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: 0x10444e9e4
 #   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: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
---
Changes since v2:
- Replace check_strvec_loc() with macro code.
- Rewrite commit message and subject accordingly.

 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 d4615ab06d..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) ||
-		    !check_str(vec->v[nr], str)) {
-			struct strbuf msg = STRBUF_INIT;
-			strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr);
-			test_assert(loc, msg.buf, 0);
-			strbuf_release(&msg);
-			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

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v3] t-strvec: improve check_strvec() output
  2024-07-14 10:17 ` [PATCH v3] t-strvec: improve check_strvec() output René Scharfe
@ 2024-07-14 17:06   ` René Scharfe
  2024-07-16  4:37   ` Jeff King
  1 sibling, 0 replies; 20+ messages in thread
From: René Scharfe @ 2024-07-14 17:06 UTC (permalink / raw)
  To: Git List, Junio C Hamano; +Cc: Patrick Steinhardt, Phillip Wood, Jeff King

Oh, v2 is already on next.  Will send the equivalent of v3 as an update
on top of next as a replacement.

René

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 2/1] t-strvec: improve check_strvec() output
  2024-07-05 17:03 ` [PATCH v2] " René Scharfe
  2024-07-09 11:32   ` Jeff King
@ 2024-07-14 17:06   ` René Scharfe
  2024-07-15 14:44     ` Junio C Hamano
  2024-07-14 17:06   ` [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec René Scharfe
  2 siblings, 1 reply; 20+ messages in thread
From: René Scharfe @ 2024-07-14 17:06 UTC (permalink / raw)
  To: Git List, Junio C Hamano
  Cc: Patrick Steinhardt, Phillip Wood, Eric Sunshine, Jeff King

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

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec
  2024-07-05 17:03 ` [PATCH v2] " René Scharfe
  2024-07-09 11:32   ` Jeff King
  2024-07-14 17:06   ` [PATCH v2 2/1] t-strvec: improve check_strvec() output René Scharfe
@ 2024-07-14 17:06   ` René Scharfe
  2024-07-15 14:43     ` Junio C Hamano
  2 siblings, 1 reply; 20+ messages in thread
From: René Scharfe @ 2024-07-14 17:06 UTC (permalink / raw)
  To: Git List, Junio C Hamano
  Cc: Patrick Steinhardt, Phillip Wood, Eric Sunshine, Jeff King

The members .nr and .alloc of an empty strvec are both zero and the
trailing NULL is provided by the shared global variable empty_strvec.
Once at least one item is added, .alloc needs to be bigger than .nr to
leave room for the terminating NULL.  The current .alloc check only
tests whether it's bigger or equal to .nr in all cases.

Tighten it depending on whether the strvec is backed by empty_strvec or
not.  A report for a non-zero .alloc in an empty strvec looks like this:

 # check "(&vec)->nr == (&vec)->alloc" failed at t/unit-tests/t-strvec.c:55
 #    left: 0
 #   right: 1

And .alloc being .equal to .nr in a non-empty strvec results in:

 # check "(&vec)->nr < (&vec)->alloc" failed at t/unit-tests/t-strvec.c:55
 #    left: 1
 #   right: 1

Signed-off-by: René Scharfe <l.s.r@web.de>
---
Bonus patch.

 t/unit-tests/t-strvec.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index fdb28ba220..6a4d425840 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -8,7 +8,9 @@
 		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)) { \
+		    ((vec)->v == empty_strvec ? \
+		     check_uint((vec)->nr, ==, (vec)->alloc) : \
+		     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); \
--
2.45.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec
  2024-07-14 17:06   ` [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec René Scharfe
@ 2024-07-15 14:43     ` Junio C Hamano
  2024-07-15 16:47       ` René Scharfe
  0 siblings, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2024-07-15 14:43 UTC (permalink / raw)
  To: René Scharfe
  Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine,
	Jeff King

René Scharfe <l.s.r@web.de> writes:

> diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
> index fdb28ba220..6a4d425840 100644
> --- a/t/unit-tests/t-strvec.c
> +++ b/t/unit-tests/t-strvec.c
> @@ -8,7 +8,9 @@
>  		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)) { \
> +		    ((vec)->v == empty_strvec ? \
> +		     check_uint((vec)->nr, ==, (vec)->alloc) : \
> +		     check_uint((vec)->nr, <, (vec)->alloc))) { \

Not a huge deal but with empty_strvec, don't we want to barf if
nr==alloc==1?

>  			for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \
>  				if (!check_str((vec)->v[i], expect[i])) { \
>  					test_msg("      i: %"PRIuMAX, i); \
> --
> 2.45.2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 2/1] t-strvec: improve check_strvec() output
  2024-07-14 17:06   ` [PATCH v2 2/1] t-strvec: improve check_strvec() output René Scharfe
@ 2024-07-15 14:44     ` Junio C Hamano
  0 siblings, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2024-07-15 14:44 UTC (permalink / raw)
  To: René Scharfe
  Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine,
	Jeff King

René Scharfe <l.s.r@web.de> writes:

> 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.
> ...
> 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().

Thanks.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec
  2024-07-15 14:43     ` Junio C Hamano
@ 2024-07-15 16:47       ` René Scharfe
  2024-07-15 17:27         ` Junio C Hamano
  0 siblings, 1 reply; 20+ messages in thread
From: René Scharfe @ 2024-07-15 16:47 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine,
	Jeff King

Am 15.07.24 um 16:43 schrieb Junio C Hamano:
> René Scharfe <l.s.r@web.de> writes:
>
>> diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
>> index fdb28ba220..6a4d425840 100644
>> --- a/t/unit-tests/t-strvec.c
>> +++ b/t/unit-tests/t-strvec.c
>> @@ -8,7 +8,9 @@
>>  		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)) { \
>> +		    ((vec)->v == empty_strvec ? \
>> +		     check_uint((vec)->nr, ==, (vec)->alloc) : \
>> +		     check_uint((vec)->nr, <, (vec)->alloc))) { \
>
> Not a huge deal but with empty_strvec, don't we want to barf if
> nr==alloc==1?

Yes, and that's handled by the comparison with ARRAY_SIZE(expect) - 1
above.  Perhaps comparing to 0 explicitly would be clearer.  My thinking
was just to split up the old <= check into its < and == cases, without
changing anything else..

>
>>  			for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \
>>  				if (!check_str((vec)->v[i], expect[i])) { \
>>  					test_msg("      i: %"PRIuMAX, i); \
>> --
>> 2.45.2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec
  2024-07-15 16:47       ` René Scharfe
@ 2024-07-15 17:27         ` Junio C Hamano
  0 siblings, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2024-07-15 17:27 UTC (permalink / raw)
  To: René Scharfe
  Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine,
	Jeff King

René Scharfe <l.s.r@web.de> writes:

>>>  		    check_uint((vec)->nr, ==, ARRAY_SIZE(expect) - 1) && \
>>> -		    check_uint((vec)->nr, <=, (vec)->alloc)) { \
>>> +		    ((vec)->v == empty_strvec ? \
>>> +		     check_uint((vec)->nr, ==, (vec)->alloc) : \
>>> +		     check_uint((vec)->nr, <, (vec)->alloc))) { \
>>
>> Not a huge deal but with empty_strvec, don't we want to barf if
>> nr==alloc==1?
>
> Yes, and that's handled by the comparison with ARRAY_SIZE(expect) - 1
> above.

Ah, OK, thanks.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2] t-strvec: use test_msg()
  2024-07-14 10:17     ` René Scharfe
@ 2024-07-16  1:43       ` Jeff King
  2024-07-16 16:43         ` René Scharfe
  0 siblings, 1 reply; 20+ messages in thread
From: Jeff King @ 2024-07-16  1:43 UTC (permalink / raw)
  To: René Scharfe
  Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine

On Sun, Jul 14, 2024 at 12:17:09PM +0200, René Scharfe wrote:

> > Should we be using check_str_loc() in the post-image?
> 
> Yes, and check_uint_loc() and check_pointer_eq_loc() as well.  Which
> would be a pain.  Or we drag everything into the macro check_strvec and
> get the caller's line number for free.

Is it that big of a pain? It's mostly just passing "loc" along to the
relative functions. To me it is more a problem that it is super easy to
forget.

Are the unit tests themselves multi-threaded within a single program?
I'd think not. In which case, I kind of wonder if a simpler pattern
would be to just set a global "location" variable (probably as a stack
of strings) that all of the individual check functions used. And then we
could set it once at the top-level of the test which wants its location
reported, and any helper functions that get called in the middle would
not have to care. And existing check_foo() functions could use the
current file/line location if the stack is empty (so code that isn't
using helper functions can remain unaffected).

-Peff

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3] t-strvec: improve check_strvec() output
  2024-07-14 10:17 ` [PATCH v3] t-strvec: improve check_strvec() output René Scharfe
  2024-07-14 17:06   ` René Scharfe
@ 2024-07-16  4:37   ` Jeff King
  2024-07-16 15:20     ` Junio C Hamano
  1 sibling, 1 reply; 20+ messages in thread
From: Jeff King @ 2024-07-16  4:37 UTC (permalink / raw)
  To: René Scharfe
  Cc: Junio C Hamano, Git List, Patrick Steinhardt, Phillip Wood

On Sun, Jul 14, 2024 at 12:17:53PM +0200, René Scharfe wrote:

> +	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)

The linux32 CI job seems to complain about this, since the concrete type
of "i" (a size_t) is "unsigned int" there, but PRIuMAX is %llu.
Presumably you just need to cast to uintmax_t.

-Peff

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3] t-strvec: improve check_strvec() output
  2024-07-16  4:37   ` Jeff King
@ 2024-07-16 15:20     ` Junio C Hamano
  2024-07-16 16:14       ` [PATCH] t-strvec: fix type mismatch in check_strvec René Scharfe
  0 siblings, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2024-07-16 15:20 UTC (permalink / raw)
  To: Jeff King; +Cc: René Scharfe, Git List, Patrick Steinhardt, Phillip Wood

Jeff King <peff@peff.net> writes:

> On Sun, Jul 14, 2024 at 12:17:53PM +0200, René Scharfe wrote:
>
>> +	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)
>
> The linux32 CI job seems to complain about this, since the concrete type
> of "i" (a size_t) is "unsigned int" there, but PRIuMAX is %llu.
> Presumably you just need to cast to uintmax_t.

Yeah, I noticed it, too, but unfortunately it was after pushing it
out and seeing it break there X-<.



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH] t-strvec: fix type mismatch in check_strvec
  2024-07-16 15:20     ` Junio C Hamano
@ 2024-07-16 16:14       ` René Scharfe
  2024-07-16 16:33         ` Junio C Hamano
  0 siblings, 1 reply; 20+ messages in thread
From: René Scharfe @ 2024-07-16 16:14 UTC (permalink / raw)
  To: Junio C Hamano, Jeff King; +Cc: Git List, Patrick Steinhardt, Phillip Wood

Cast i from size_t to uintmax_t to match the format string.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
---
Oops, sorry about that. :-(

PRIuMAX is "lu" on my system, so the compiler didn't flag the mistake.

 t/unit-tests/t-strvec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
index fdb28ba220..fa1a041469 100644
--- a/t/unit-tests/t-strvec.c
+++ b/t/unit-tests/t-strvec.c
@@ -11,7 +11,8 @@
 		    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); \
+					test_msg("      i: %"PRIuMAX, \
+						 (uintmax_t)i); \
 					break; \
 				} \
 			} \
--
2.45.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH] t-strvec: fix type mismatch in check_strvec
  2024-07-16 16:14       ` [PATCH] t-strvec: fix type mismatch in check_strvec René Scharfe
@ 2024-07-16 16:33         ` Junio C Hamano
  0 siblings, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2024-07-16 16:33 UTC (permalink / raw)
  To: René Scharfe; +Cc: Jeff King, Git List, Patrick Steinhardt, Phillip Wood

René Scharfe <l.s.r@web.de> writes:

> Cast i from size_t to uintmax_t to match the format string.
>
> Reported-by: Jeff King <peff@peff.net>
> Signed-off-by: René Scharfe <l.s.r@web.de>
> ---
> Oops, sorry about that. :-(
>
> PRIuMAX is "lu" on my system, so the compiler didn't flag the mistake.
>
>  t/unit-tests/t-strvec.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

The fix is of course identical to what I added to the integration I
prepared, but the line-wrapping is better in this version, so I'll
replace ;-)

> diff --git a/t/unit-tests/t-strvec.c b/t/unit-tests/t-strvec.c
> index fdb28ba220..fa1a041469 100644
> --- a/t/unit-tests/t-strvec.c
> +++ b/t/unit-tests/t-strvec.c
> @@ -11,7 +11,8 @@
>  		    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); \
> +					test_msg("      i: %"PRIuMAX, \
> +						 (uintmax_t)i); \
>  					break; \
>  				} \
>  			} \
> --
> 2.45.2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2] t-strvec: use test_msg()
  2024-07-16  1:43       ` Jeff King
@ 2024-07-16 16:43         ` René Scharfe
  0 siblings, 0 replies; 20+ messages in thread
From: René Scharfe @ 2024-07-16 16:43 UTC (permalink / raw)
  To: Jeff King; +Cc: Git List, Patrick Steinhardt, Phillip Wood, Eric Sunshine

Am 16.07.24 um 03:43 schrieb Jeff King:
> On Sun, Jul 14, 2024 at 12:17:09PM +0200, René Scharfe wrote:
>
>>> Should we be using check_str_loc() in the post-image?
>>
>> Yes, and check_uint_loc() and check_pointer_eq_loc() as well.  Which
>> would be a pain.  Or we drag everything into the macro check_strvec and
>> get the caller's line number for free.
>
> Is it that big of a pain? It's mostly just passing "loc" along to the
> relative functions.

That part is bearable.  The pain comes from the need to pass in
arguments multiple times, for the stringified check description, as part
of the check result and as separate values.

It could be mitigated by adding a new macro that takes loc, a, op,
and b, perhaps called CHECK_UINT_LOC.  That additional evaluation step
doesn't work nicely with arguments that are themselves macros, though,
like NULL for string or pointer checks, as those will be expanded,
changing the message.

> Are the unit tests themselves multi-threaded within a single program?

No, and check_pointer_eq, check_int, check_uint, and check_char use
shared global variables to store temporary values (comments rightly
warn that "this is not thread safe").

> I'd think not. In which case, I kind of wonder if a simpler pattern
> would be to just set a global "location" variable (probably as a stack
> of strings) that all of the individual check functions used. And then we
> could set it once at the top-level of the test which wants its location
> reported, and any helper functions that get called in the middle would
> not have to care. And existing check_foo() functions could use the
> current file/line location if the stack is empty (so code that isn't
> using helper functions can remain unaffected).

That doesn't sound simpler to me, quite the opposite actually.  To the
point that I don't dare to ask for a demo. o_O

Or perhaps I need to revisit it when I'm no longer tired and hungry.

René


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2024-07-16 16:43 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-04 18:04 [PATCH] t-strvec: use test_msg() René Scharfe
2024-07-04 18:31 ` Eric Sunshine
2024-07-05  9:44 ` Phillip Wood
2024-07-05 17:03 ` [PATCH v2] " René Scharfe
2024-07-09 11:32   ` Jeff King
2024-07-14 10:17     ` René Scharfe
2024-07-16  1:43       ` Jeff King
2024-07-16 16:43         ` René Scharfe
2024-07-14 17:06   ` [PATCH v2 2/1] t-strvec: improve check_strvec() output René Scharfe
2024-07-15 14:44     ` Junio C Hamano
2024-07-14 17:06   ` [PATCH v2 3/1] t-strvec: tighten .alloc check in check_strvec René Scharfe
2024-07-15 14:43     ` Junio C Hamano
2024-07-15 16:47       ` René Scharfe
2024-07-15 17:27         ` Junio C Hamano
2024-07-14 10:17 ` [PATCH v3] t-strvec: improve check_strvec() output René Scharfe
2024-07-14 17:06   ` René Scharfe
2024-07-16  4:37   ` Jeff King
2024-07-16 15:20     ` Junio C Hamano
2024-07-16 16:14       ` [PATCH] t-strvec: fix type mismatch in check_strvec René Scharfe
2024-07-16 16:33         ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).