diff mbox series

[v2,5/5] t-reftable-tree: improve the test for infix_walk()

Message ID 20240612055031.3607-6-chandrapratap3519@gmail.com (mailing list archive)
State Superseded
Headers show
Series t: port reftable/tree_test.c to the unit testing framework | expand

Commit Message

Chandra Pratap June 12, 2024, 5:38 a.m. UTC
In the current testing setup for infix_walk(), the following
properties of an infix traversal of a tree remain untested:
- every node of the tree must be visited
- every node must be visited exactly only
and only the property 'traversal in increasing order' is tested.
Modify test_infix_walk() to check for all the properties above.

This can be achieved by storing the nodes' keys linearly, in a nullified
buffer, as we visit them and then checking the input keys against this
buffer in increasing order. By checking that the element just after
the last input key is 'NULL' in the output buffer, we ensure that
every node is traversed exactly once.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Chandra Pratap <chandrapratap3519@gmail.com>
---
 t/unit-tests/t-reftable-tree.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

Comments

Patrick Steinhardt June 12, 2024, 6:59 a.m. UTC | #1
On Wed, Jun 12, 2024 at 11:08:14AM +0530, Chandra Pratap wrote:
> In the current testing setup for infix_walk(), the following
> properties of an infix traversal of a tree remain untested:
> - every node of the tree must be visited
> - every node must be visited exactly only

s/only/once

> and only the property 'traversal in increasing order' is tested.

Nit: this reads a bit awkward. How about "In fact, we only verify that
the traversal happens in increasing order."

> @@ -51,6 +50,7 @@ static void test_infix_walk(void)
>  {
>  	struct tree_node *root = NULL;
>  	void *values[11] = { 0 };
> +	void *out[20] = { 0 };

From the test below it looks like we only expect 11 values to be added
to `out`. Why does this array have length 20?

We could of course also use something like `ALLOC_GROW()` to grow the
array dynamically. But that'd likely be overkill.

>  	struct curry c = { 0 };
>  	size_t i = 1;
>  
> @@ -59,7 +59,11 @@ static void test_infix_walk(void)
>  		i = (i * 7) % 11;
>  	} while (i != 1);
>  
> -	infix_walk(root, &check_increasing, &c);
> +	c.arr = (void **) &out;

We can initialize this variable directly when declaring `c`:

    struct curry c = {
        .arr = &out;
    };

Also, is the cast necessary? This is the only site where we use `struct
curry` if I'm not mistaken, so I'd expect that the type of `arr` should
match our expectations.

> +	infix_walk(root, &store, &c);
> +	for (i = 1; i < ARRAY_SIZE(values); i++)
> +		check_pointer_eq(values + i, out[i - 1]);

Let's also verify that `c.len` matches the expected number of nodes
visited.

Patrick

> +	check(!out[i]);
>  	tree_free(root);
>  }
Chandra Pratap June 12, 2024, 9:05 a.m. UTC | #2
On Wed, 12 Jun 2024 at 12:29, Patrick Steinhardt <ps@pks.im> wrote:
>
> On Wed, Jun 12, 2024 at 11:08:14AM +0530, Chandra Pratap wrote:
> > In the current testing setup for infix_walk(), the following
> > properties of an infix traversal of a tree remain untested:
> > - every node of the tree must be visited
> > - every node must be visited exactly only
>
> s/only/once
>
> > and only the property 'traversal in increasing order' is tested.
>
> Nit: this reads a bit awkward. How about "In fact, we only verify that
> the traversal happens in increasing order."
>
> > @@ -51,6 +50,7 @@ static void test_infix_walk(void)
> >  {
> >       struct tree_node *root = NULL;
> >       void *values[11] = { 0 };
> > +     void *out[20] = { 0 };
>
> From the test below it looks like we only expect 11 values to be added
> to `out`. Why does this array have length 20?

That's an error. I'll correct it in the next iteration.

> We could of course also use something like `ALLOC_GROW()` to grow the
> array dynamically. But that'd likely be overkill.
>
> >       struct curry c = { 0 };
> >       size_t i = 1;
> >
> > @@ -59,7 +59,11 @@ static void test_infix_walk(void)
> >               i = (i * 7) % 11;
> >       } while (i != 1);
> >
> > -     infix_walk(root, &check_increasing, &c);
> > +     c.arr = (void **) &out;
>
> We can initialize this variable directly when declaring `c`:
>
>     struct curry c = {
>         .arr = &out;
>     };

Right, this seems more concise.

> Also, is the cast necessary? This is the only site where we use `struct
> curry` if I'm not mistaken, so I'd expect that the type of `arr` should
> match our expectations.

Trying to do this without a cast produces the following compilation error
for me:
initialization of ‘void **’ from incompatible pointer type ‘void * (*)[11]’

> > +     infix_walk(root, &store, &c);
> > +     for (i = 1; i < ARRAY_SIZE(values); i++)
> > +             check_pointer_eq(values + i, out[i - 1]);
>
> Let's also verify that `c.len` matches the expected number of nodes
> visited.

Sure.
diff mbox series

Patch

diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c
index f1adab4458..917a64a7d1 100644
--- a/t/unit-tests/t-reftable-tree.c
+++ b/t/unit-tests/t-reftable-tree.c
@@ -15,15 +15,14 @@  static int test_compare(const void *a, const void *b)
 }
 
 struct curry {
-	void *last;
+	void **arr;
+	size_t i;
 };
 
-static void check_increasing(void *arg, void *key)
+static void store(void *arg, void *key)
 {
 	struct curry *c = arg;
-	if (c->last)
-		check_int(test_compare(c->last, key), <, 0);
-	c->last = key;
+	c->arr[c->i++] = key;
 }
 
 static void test_tree_search(void)
@@ -51,6 +50,7 @@  static void test_infix_walk(void)
 {
 	struct tree_node *root = NULL;
 	void *values[11] = { 0 };
+	void *out[20] = { 0 };
 	struct curry c = { 0 };
 	size_t i = 1;
 
@@ -59,7 +59,11 @@  static void test_infix_walk(void)
 		i = (i * 7) % 11;
 	} while (i != 1);
 
-	infix_walk(root, &check_increasing, &c);
+	c.arr = (void **) &out;
+	infix_walk(root, &store, &c);
+	for (i = 1; i < ARRAY_SIZE(values); i++)
+		check_pointer_eq(values + i, out[i - 1]);
+	check(!out[i]);
 	tree_free(root);
 }