From e5a0f7076fcb2e9e6b3a8d125ac0e86420a96da1 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Sun, 4 Aug 2024 19:36:45 +0530 Subject: [PATCH 1/5] reftable: remove unnecessary curly braces in reftable/tree.c According to Documentation/CodingGuidelines, single-line control-flow statements must omit curly braces (except for some special cases). Make reftable/tree.c adhere to this guideline. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap Signed-off-by: Junio C Hamano --- reftable/tree.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/reftable/tree.c b/reftable/tree.c index 528f33ae38..5ffb2e0d69 100644 --- a/reftable/tree.c +++ b/reftable/tree.c @@ -39,25 +39,20 @@ struct tree_node *tree_search(void *key, struct tree_node **rootp, void infix_walk(struct tree_node *t, void (*action)(void *arg, void *key), void *arg) { - if (t->left) { + if (t->left) infix_walk(t->left, action, arg); - } action(arg, t->key); - if (t->right) { + if (t->right) infix_walk(t->right, action, arg); - } } void tree_free(struct tree_node *t) { - if (!t) { + if (!t) return; - } - if (t->left) { + if (t->left) tree_free(t->left); - } - if (t->right) { + if (t->right) tree_free(t->right); - } reftable_free(t); } From ec9c0704fc6ad646f5482d3e31e3a5b3be1677ef Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Sun, 4 Aug 2024 19:36:46 +0530 Subject: [PATCH 2/5] t: move reftable/tree_test.c to the unit testing framework reftable/tree_test.c exercises the functions defined in reftable/tree.{c, h}. Migrate reftable/tree_test.c to the unit testing framework. Migration involves refactoring the tests to use the unit testing framework instead of reftable's test framework and renaming the tests to align with unit-tests' standards. Also add a comment to help understand the test routine. Note that this commit mostly moves the test from reftable/ to t/unit-tests/ and most of the refactoring is performed by the trailing commits. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap Signed-off-by: Junio C Hamano --- Makefile | 2 +- reftable/reftable-tests.h | 1 - reftable/tree_test.c | 60 ---------------------------------- t/helper/test-reftable.c | 1 - t/unit-tests/t-reftable-tree.c | 60 ++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 63 deletions(-) delete mode 100644 reftable/tree_test.c create mode 100644 t/unit-tests/t-reftable-tree.c diff --git a/Makefile b/Makefile index 2f5f16847a..d736b2f8bd 100644 --- a/Makefile +++ b/Makefile @@ -1336,6 +1336,7 @@ THIRD_PARTY_SOURCES += sha1dc/% UNIT_TEST_PROGRAMS += t-ctype UNIT_TEST_PROGRAMS += t-mem-pool UNIT_TEST_PROGRAMS += t-prio-queue +UNIT_TEST_PROGRAMS += t-reftable-tree UNIT_TEST_PROGRAMS += t-strbuf UNIT_TEST_PROGRAMS += t-strcmp-offset UNIT_TEST_PROGRAMS += t-strvec @@ -2681,7 +2682,6 @@ REFTABLE_TEST_OBJS += reftable/record_test.o REFTABLE_TEST_OBJS += reftable/readwrite_test.o REFTABLE_TEST_OBJS += reftable/stack_test.o REFTABLE_TEST_OBJS += reftable/test_framework.o -REFTABLE_TEST_OBJS += reftable/tree_test.o TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) diff --git a/reftable/reftable-tests.h b/reftable/reftable-tests.h index 114cc3d053..d0abcc51e2 100644 --- a/reftable/reftable-tests.h +++ b/reftable/reftable-tests.h @@ -16,7 +16,6 @@ int pq_test_main(int argc, const char **argv); int record_test_main(int argc, const char **argv); int readwrite_test_main(int argc, const char **argv); int stack_test_main(int argc, const char **argv); -int tree_test_main(int argc, const char **argv); int reftable_dump_main(int argc, char *const *argv); #endif diff --git a/reftable/tree_test.c b/reftable/tree_test.c deleted file mode 100644 index 6961a657ad..0000000000 --- a/reftable/tree_test.c +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "system.h" -#include "tree.h" - -#include "test_framework.h" -#include "reftable-tests.h" - -static int test_compare(const void *a, const void *b) -{ - return (char *)a - (char *)b; -} - -struct curry { - void *last; -}; - -static void check_increasing(void *arg, void *key) -{ - struct curry *c = arg; - if (c->last) { - EXPECT(test_compare(c->last, key) < 0); - } - c->last = key; -} - -static void test_tree(void) -{ - struct tree_node *root = NULL; - - void *values[11] = { NULL }; - struct tree_node *nodes[11] = { NULL }; - int i = 1; - struct curry c = { NULL }; - do { - nodes[i] = tree_search(values + i, &root, &test_compare, 1); - i = (i * 7) % 11; - } while (i != 1); - - for (i = 1; i < ARRAY_SIZE(nodes); i++) { - EXPECT(values + i == nodes[i]->key); - EXPECT(nodes[i] == - tree_search(values + i, &root, &test_compare, 0)); - } - - infix_walk(root, check_increasing, &c); - tree_free(root); -} - -int tree_test_main(int argc, const char *argv[]) -{ - RUN_TEST(test_tree); - return 0; -} diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c index bae731669c..9475db2f76 100644 --- a/t/helper/test-reftable.c +++ b/t/helper/test-reftable.c @@ -8,7 +8,6 @@ int cmd__reftable(int argc, const char **argv) basics_test_main(argc, argv); record_test_main(argc, argv); block_test_main(argc, argv); - tree_test_main(argc, argv); pq_test_main(argc, argv); readwrite_test_main(argc, argv); merged_test_main(argc, argv); diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c new file mode 100644 index 0000000000..8b1f9a66a0 --- /dev/null +++ b/t/unit-tests/t-reftable-tree.c @@ -0,0 +1,60 @@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "reftable/tree.h" + +static int t_compare(const void *a, const void *b) +{ + return (char *)a - (char *)b; +} + +struct curry { + void *last; +}; + +static void check_increasing(void *arg, void *key) +{ + struct curry *c = arg; + if (c->last) + check_int(t_compare(c->last, key), <, 0); + c->last = key; +} + +static void t_tree(void) +{ + struct tree_node *root = NULL; + void *values[11] = { 0 }; + struct tree_node *nodes[11] = { 0 }; + size_t i = 1; + struct curry c = { 0 }; + + /* + * Pseudo-randomly insert the pointers for elements between + * values[1] and values[10] (inclusive) in the tree. + */ + do { + nodes[i] = tree_search(&values[i], &root, &t_compare, 1); + i = (i * 7) % 11; + } while (i != 1); + + for (i = 1; i < ARRAY_SIZE(nodes); i++) { + check_pointer_eq(&values[i], nodes[i]->key); + check_pointer_eq(nodes[i], tree_search(&values[i], &root, &t_compare, 0)); + } + + infix_walk(root, check_increasing, &c); + tree_free(root); +} + +int cmd_main(int argc, const char *argv[]) +{ + TEST(t_tree(), "tree_search and infix_walk work"); + + return test_done(); +} From abf1a96773bfaee5e354909d3a6dc172bfbdee96 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Sun, 4 Aug 2024 19:36:47 +0530 Subject: [PATCH 3/5] t-reftable-tree: split test_tree() into two sub-test functions In the current testing setup, tests for both tree_search() and infix_walk() defined by reftable/tree.{c, h} are performed by a single test function, test_tree(). Split tree_test() into test_tree_search() and test_infix_walk() responsible for independently testing tree_search() and infix_walk() respectively. This improves the overall readability of the test file as well as simplifies debugging. Note that the last parameter in the tree_search() functiom is 'int insert' which when set, inserts the key if it is not found in the tree. Otherwise, the function returns NULL for such cases. While at it, use 'func' to pass function pointers and not '&func'. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap Signed-off-by: Junio C Hamano --- t/unit-tests/t-reftable-tree.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c index 8b1f9a66a0..7cc52a1925 100644 --- a/t/unit-tests/t-reftable-tree.c +++ b/t/unit-tests/t-reftable-tree.c @@ -26,13 +26,12 @@ static void check_increasing(void *arg, void *key) c->last = key; } -static void t_tree(void) +static void t_tree_search(void) { struct tree_node *root = NULL; void *values[11] = { 0 }; struct tree_node *nodes[11] = { 0 }; size_t i = 1; - struct curry c = { 0 }; /* * Pseudo-randomly insert the pointers for elements between @@ -48,13 +47,29 @@ static void t_tree(void) check_pointer_eq(nodes[i], tree_search(&values[i], &root, &t_compare, 0)); } - infix_walk(root, check_increasing, &c); + tree_free(root); +} + +static void t_infix_walk(void) +{ + struct tree_node *root = NULL; + void *values[11] = { 0 }; + struct curry c = { 0 }; + size_t i = 1; + + do { + tree_search(&values[i], &root, t_compare, 1); + i = (i * 7) % 11; + } while (i != 1); + + infix_walk(root, &check_increasing, &c); tree_free(root); } int cmd_main(int argc, const char *argv[]) { - TEST(t_tree(), "tree_search and infix_walk work"); + TEST(t_tree_search(), "tree_search works"); + TEST(t_infix_walk(), "infix_walk works"); return test_done(); } From c70022c1b9b3a6ea4d4d3f4b54edf0d759e520e3 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Sun, 4 Aug 2024 19:36:48 +0530 Subject: [PATCH 4/5] t-reftable-tree: add test for non-existent key In the current testing setup for tree_search(), the case for non-existent key is not exercised. Improve this by adding a test-case for the same. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap Signed-off-by: Junio C Hamano --- t/unit-tests/t-reftable-tree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c index 7cc52a1925..2220414a18 100644 --- a/t/unit-tests/t-reftable-tree.c +++ b/t/unit-tests/t-reftable-tree.c @@ -47,6 +47,7 @@ static void t_tree_search(void) check_pointer_eq(nodes[i], tree_search(&values[i], &root, &t_compare, 0)); } + check(!tree_search(values, &root, t_compare, 0)); tree_free(root); } From 3a498b49d1b7d1ffc939b87310533a40ecbd8c43 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Sun, 4 Aug 2024 19:36:49 +0530 Subject: [PATCH 5/5] t-reftable-tree: improve the test for infix_walk() 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 once In fact, 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 Mentored-by: Christian Couder Signed-off-by: Chandra Pratap Signed-off-by: Junio C Hamano --- t/unit-tests/t-reftable-tree.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/t/unit-tests/t-reftable-tree.c b/t/unit-tests/t-reftable-tree.c index 2220414a18..e7d774d774 100644 --- a/t/unit-tests/t-reftable-tree.c +++ b/t/unit-tests/t-reftable-tree.c @@ -15,15 +15,14 @@ static int t_compare(const void *a, const void *b) } struct curry { - void *last; + void **arr; + size_t len; }; -static void check_increasing(void *arg, void *key) +static void store(void *arg, void *key) { struct curry *c = arg; - if (c->last) - check_int(t_compare(c->last, key), <, 0); - c->last = key; + c->arr[c->len++] = key; } static void t_tree_search(void) @@ -55,15 +54,24 @@ static void t_infix_walk(void) { struct tree_node *root = NULL; void *values[11] = { 0 }; - struct curry c = { 0 }; + void *out[11] = { 0 }; + struct curry c = { + .arr = (void **) &out, + }; size_t i = 1; + size_t count = 0; do { tree_search(&values[i], &root, t_compare, 1); i = (i * 7) % 11; + count++; } while (i != 1); - infix_walk(root, &check_increasing, &c); + infix_walk(root, &store, &c); + for (i = 1; i < ARRAY_SIZE(values); i++) + check_pointer_eq(&values[i], out[i - 1]); + check(!out[i - 1]); + check_int(c.len, ==, count); tree_free(root); }