{"thread":{"id":"60741","subject":"[PATCH] tests: move t0009-prio-queue.sh to the new unit testing framework","startedAt":"2024-01-14T08:10:33Z","lastAt":"2024-01-25T20:02:38Z","messageCount":15,"participants":["Chandra Pratap via GitGitGadget","Chandra Pratap","Junio C Hamano","Josh Steadmon","Jeff King","Phillip Wood"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"486771","messageId":"pull.1642.git.1705219829965.gitgitgadget@gmail.com","threadId":"60741","inReplyTo":null,"subject":"[PATCH] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Chandra Pratap via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-01-14T08:10:29Z","receivedAt":"2024-01-14T08:10:33Z","isPatch":true,"sender":{"key":"chandrapratap3519@gmail.com","avatar":null},"body":"From: Chandra Pratap <chandrapratap3519@gmail.com>\n\nt/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\ntests Git's implementation of a priority queue. Migrate the\ntest over to the new unit testing framework to simplify debugging\nand reduce test run-time. Refactor the required logic and add\na new test case in addition to porting over the original ones in\nshell.\n\nSigned-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n---\n    tests: move t0009-prio-queue.sh to the new unit testing framework\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1642\n\n Makefile                    |  2 +-\n t/helper/test-prio-queue.c  | 51 -------------------\n t/helper/test-tool.c        |  1 -\n t/helper/test-tool.h        |  1 -\n t/t0009-prio-queue.sh       | 66 -------------------------\n t/unit-tests/t-prio-queue.c | 99 +++++++++++++++++++++++++++++++++++++\n 6 files changed, 100 insertions(+), 120 deletions(-)\n delete mode 100644 t/helper/test-prio-queue.c\n delete mode 100755 t/t0009-prio-queue.sh\n create mode 100644 t/unit-tests/t-prio-queue.c\n\ndiff --git a/Makefile b/Makefile\nindex 312d95084c1..d5e48e656b3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n TEST_BUILTINS_OBJS += test-path-utils.o\n TEST_BUILTINS_OBJS += test-pcre2-config.o\n TEST_BUILTINS_OBJS += test-pkt-line.o\n-TEST_BUILTINS_OBJS += test-prio-queue.o\n TEST_BUILTINS_OBJS += test-proc-receive.o\n TEST_BUILTINS_OBJS += test-progress.o\n TEST_BUILTINS_OBJS += test-reach.o\n@@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n \n UNIT_TEST_PROGRAMS += t-basic\n UNIT_TEST_PROGRAMS += t-strbuf\n+UNIT_TEST_PROGRAMS += t-prio-queue\n UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\ndiff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\ndeleted file mode 100644\nindex f0bf255f5f0..00000000000\n--- a/t/helper/test-prio-queue.c\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-#include \"test-tool.h\"\n-#include \"prio-queue.h\"\n-\n-static int intcmp(const void *va, const void *vb, void *data UNUSED)\n-{\n-\tconst int *a = va, *b = vb;\n-\treturn *a - *b;\n-}\n-\n-static void show(int *v)\n-{\n-\tif (!v)\n-\t\tprintf(\"NULL\\n\");\n-\telse\n-\t\tprintf(\"%d\\n\", *v);\n-\tfree(v);\n-}\n-\n-int cmd__prio_queue(int argc UNUSED, const char **argv)\n-{\n-\tstruct prio_queue pq = { intcmp };\n-\n-\twhile (*++argv) {\n-\t\tif (!strcmp(*argv, \"get\")) {\n-\t\t\tvoid *peek = prio_queue_peek(&pq);\n-\t\t\tvoid *get = prio_queue_get(&pq);\n-\t\t\tif (peek != get)\n-\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\tshow(get);\n-\t\t} else if (!strcmp(*argv, \"dump\")) {\n-\t\t\tvoid *peek;\n-\t\t\tvoid *get;\n-\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n-\t\t\t\tget = prio_queue_get(&pq);\n-\t\t\t\tif (peek != get)\n-\t\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\t\tshow(get);\n-\t\t\t}\n-\t\t} else if (!strcmp(*argv, \"stack\")) {\n-\t\t\tpq.compare = NULL;\n-\t\t} else {\n-\t\t\tint *v = xmalloc(sizeof(*v));\n-\t\t\t*v = atoi(*argv);\n-\t\t\tprio_queue_put(&pq, v);\n-\t\t}\n-\t}\n-\n-\tclear_prio_queue(&pq);\n-\n-\treturn 0;\n-}\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex 876cd2dc313..5f591b9718f 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n \t{ \"path-utils\", cmd__path_utils },\n \t{ \"pcre2-config\", cmd__pcre2_config },\n \t{ \"pkt-line\", cmd__pkt_line },\n-\t{ \"prio-queue\", cmd__prio_queue },\n \t{ \"proc-receive\", cmd__proc_receive },\n \t{ \"progress\", cmd__progress },\n \t{ \"reach\", cmd__reach },\ndiff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\nindex 70dd4eba119..b921138d8ec 100644\n--- a/t/helper/test-tool.h\n+++ b/t/helper/test-tool.h\n@@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n int cmd__path_utils(int argc, const char **argv);\n int cmd__pcre2_config(int argc, const char **argv);\n int cmd__pkt_line(int argc, const char **argv);\n-int cmd__prio_queue(int argc, const char **argv);\n int cmd__proc_receive(int argc, const char **argv);\n int cmd__progress(int argc, const char **argv);\n int cmd__reach(int argc, const char **argv);\ndiff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\ndeleted file mode 100755\nindex eea99107a48..00000000000\n--- a/t/t0009-prio-queue.sh\n+++ /dev/null\n@@ -1,66 +0,0 @@\n-#!/bin/sh\n-\n-test_description='basic tests for priority queue implementation'\n-\n-TEST_PASSES_SANITIZE_LEAK=true\n-. ./test-lib.sh\n-\n-cat >expect <<'EOF'\n-1\n-2\n-3\n-4\n-5\n-5\n-6\n-7\n-8\n-9\n-10\n-EOF\n-test_expect_success 'basic ordering' '\n-\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-2\n-3\n-4\n-1\n-5\n-6\n-EOF\n-test_expect_success 'mixed put and get' '\n-\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-1\n-2\n-NULL\n-1\n-2\n-NULL\n-EOF\n-test_expect_success 'notice empty queue' '\n-\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-3\n-2\n-6\n-4\n-5\n-1\n-8\n-EOF\n-test_expect_success 'stack order' '\n-\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-test_done\ndiff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\nnew file mode 100644\nindex 00000000000..98a69790f7e\n--- /dev/null\n+++ b/t/unit-tests/t-prio-queue.c\n@@ -0,0 +1,99 @@\n+#include \"test-lib.h\"\n+#include \"prio-queue.h\"\n+\n+static int intcmp(const void *va, const void *vb, void *data UNUSED)\n+{\n+\tconst int *a = va, *b = vb;\n+\treturn *a - *b;\n+}\n+\n+static int show(int *v)\n+{\n+\tint ret = -1;\n+\tif (v)\n+\t\tret = *v;\n+\tfree(v);\n+\treturn ret;\n+}\n+\n+static int test_prio_queue(const char **input, int *result)\n+{\n+\tstruct prio_queue pq = { intcmp };\n+\tint i = 0;\n+\n+\twhile (*input) {\n+\t\tif (!strcmp(*input, \"get\")) {\n+\t\t\tvoid *peek = prio_queue_peek(&pq);\n+\t\t\tvoid *get = prio_queue_get(&pq);\n+\t\t\tif (peek != get)\n+\t\t\t\tBUG(\"peek and get results do not match\");\n+\t\t\tresult[i++] = show(get);\n+\t\t} else if (!strcmp(*input, \"dump\")) {\n+\t\t\tvoid *peek;\n+\t\t\tvoid *get;\n+\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n+\t\t\t\tget = prio_queue_get(&pq);\n+\t\t\t\tif (peek != get)\n+\t\t\t\t\tBUG(\"peek and get results do not match\");\n+\t\t\t\tresult[i++] = show(get);\n+\t\t\t}\n+\t\t} else if (!strcmp(*input, \"stack\")) {\n+\t\t\tpq.compare = NULL;\n+\t\t} else if (!strcmp(*input, \"reverse\")) {\n+\t\t\tprio_queue_reverse(&pq);\n+\t\t} else {\n+\t\t\tint *v = xmalloc(sizeof(*v));\n+\t\t\t*v = atoi(*input);\n+\t\t\tprio_queue_put(&pq, v);\n+\t\t}\n+\t\tinput++;\n+\t}\n+\n+\tclear_prio_queue(&pq);\n+\n+\treturn 0;\n+}\n+\n+#define INPUT_SIZE 6\n+\n+#define BASIC_INPUT \"1\", \"2\", \"3\", \"4\", \"5\", \"5\", \"dump\"\n+#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n+\n+#define MIXED_PUT_GET_INPUT \"6\", \"2\", \"4\", \"get\", \"5\", \"3\", \"get\", \"get\", \"1\", \"dump\"\n+#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n+\n+#define EMPTY_QUEUE_INPUT \"1\", \"2\", \"get\", \"get\", \"get\", \"1\", \"2\", \"get\", \"get\", \"get\"\n+#define EMPTY_QUEUE_EXPECTED 1, 2, -1, 1, 2, -1\n+\n+#define STACK_INPUT \"stack\", \"1\", \"5\", \"4\", \"6\", \"2\", \"3\", \"dump\"\n+#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n+\n+#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n+#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n+\n+#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\\\n+  static void test_##name(void)\t\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\t\t\t\\\n+\tconst char *input[] = {INPUT};\t\t\t\t\t\t\\\n+\tint expected[] = {EXPECTED};\t\t\t\t\t\\\n+\tint result[INPUT_SIZE];\t\t\t\t\t\t\t\t\\\n+\ttest_prio_queue(input, result);\t\t\t\t\t\t\\\n+\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n+}\n+\n+TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n+TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n+TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n+TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n+TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n+\n+int cmd_main(int argc, const char **argv)\n+{\n+\tTEST(test_basic(), \"prio-queue works for basic input\");\n+\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n+\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n+\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n+\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n+\n+\treturn test_done();\n+}\n\nbase-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n-- \ngitgitgadget\n"},{"id":"486772","messageId":"CA+J6zkS3zKJ5kNfCQGsi-ra31RzX9XRKT7popnhA5YrgrxVRog@mail.gmail.com","threadId":"60741","inReplyTo":"pull.1642.git.1705219829965.gitgitgadget@gmail.com","subject":"Re: [PATCH] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Chandra Pratap","fromEmail":"chandrapratap3519@gmail.com","sentAt":"2024-01-14T08:15:58Z","receivedAt":"2024-01-14T08:16:06Z","isPatch":true,"sender":{"key":"chandrapratap3519@gmail.com","avatar":null},"body":"Please ignore the patch above, my e-mail client seems to have\nmessed up the backslash indentation. I will follow up with the\ncorrected patch shortly.\n\nOn Sun, 14 Jan 2024 at 13:40, Chandra Pratap via GitGitGadget\n<gitgitgadget@gmail.com> wrote:\n>\n> From: Chandra Pratap <chandrapratap3519@gmail.com>\n>\n> t/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\n> tests Git's implementation of a priority queue. Migrate the\n> test over to the new unit testing framework to simplify debugging\n> and reduce test run-time. Refactor the required logic and add\n> a new test case in addition to porting over the original ones in\n> shell.\n>\n> Signed-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n> ---\n>     tests: move t0009-prio-queue.sh to the new unit testing framework\n>\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v1\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v1\n> Pull-Request: https://github.com/gitgitgadget/git/pull/1642\n>\n>  Makefile                    |  2 +-\n>  t/helper/test-prio-queue.c  | 51 -------------------\n>  t/helper/test-tool.c        |  1 -\n>  t/helper/test-tool.h        |  1 -\n>  t/t0009-prio-queue.sh       | 66 -------------------------\n>  t/unit-tests/t-prio-queue.c | 99 +++++++++++++++++++++++++++++++++++++\n>  6 files changed, 100 insertions(+), 120 deletions(-)\n>  delete mode 100644 t/helper/test-prio-queue.c\n>  delete mode 100755 t/t0009-prio-queue.sh\n>  create mode 100644 t/unit-tests/t-prio-queue.c\n>\n> diff --git a/Makefile b/Makefile\n> index 312d95084c1..d5e48e656b3 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n>  TEST_BUILTINS_OBJS += test-path-utils.o\n>  TEST_BUILTINS_OBJS += test-pcre2-config.o\n>  TEST_BUILTINS_OBJS += test-pkt-line.o\n> -TEST_BUILTINS_OBJS += test-prio-queue.o\n>  TEST_BUILTINS_OBJS += test-proc-receive.o\n>  TEST_BUILTINS_OBJS += test-progress.o\n>  TEST_BUILTINS_OBJS += test-reach.o\n> @@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n>\n>  UNIT_TEST_PROGRAMS += t-basic\n>  UNIT_TEST_PROGRAMS += t-strbuf\n> +UNIT_TEST_PROGRAMS += t-prio-queue\n>  UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n>  UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n>  UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n> diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\n> deleted file mode 100644\n> index f0bf255f5f0..00000000000\n> --- a/t/helper/test-prio-queue.c\n> +++ /dev/null\n> @@ -1,51 +0,0 @@\n> -#include \"test-tool.h\"\n> -#include \"prio-queue.h\"\n> -\n> -static int intcmp(const void *va, const void *vb, void *data UNUSED)\n> -{\n> -       const int *a = va, *b = vb;\n> -       return *a - *b;\n> -}\n> -\n> -static void show(int *v)\n> -{\n> -       if (!v)\n> -               printf(\"NULL\\n\");\n> -       else\n> -               printf(\"%d\\n\", *v);\n> -       free(v);\n> -}\n> -\n> -int cmd__prio_queue(int argc UNUSED, const char **argv)\n> -{\n> -       struct prio_queue pq = { intcmp };\n> -\n> -       while (*++argv) {\n> -               if (!strcmp(*argv, \"get\")) {\n> -                       void *peek = prio_queue_peek(&pq);\n> -                       void *get = prio_queue_get(&pq);\n> -                       if (peek != get)\n> -                               BUG(\"peek and get results do not match\");\n> -                       show(get);\n> -               } else if (!strcmp(*argv, \"dump\")) {\n> -                       void *peek;\n> -                       void *get;\n> -                       while ((peek = prio_queue_peek(&pq))) {\n> -                               get = prio_queue_get(&pq);\n> -                               if (peek != get)\n> -                                       BUG(\"peek and get results do not match\");\n> -                               show(get);\n> -                       }\n> -               } else if (!strcmp(*argv, \"stack\")) {\n> -                       pq.compare = NULL;\n> -               } else {\n> -                       int *v = xmalloc(sizeof(*v));\n> -                       *v = atoi(*argv);\n> -                       prio_queue_put(&pq, v);\n> -               }\n> -       }\n> -\n> -       clear_prio_queue(&pq);\n> -\n> -       return 0;\n> -}\n> diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\n> index 876cd2dc313..5f591b9718f 100644\n> --- a/t/helper/test-tool.c\n> +++ b/t/helper/test-tool.c\n> @@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n>         { \"path-utils\", cmd__path_utils },\n>         { \"pcre2-config\", cmd__pcre2_config },\n>         { \"pkt-line\", cmd__pkt_line },\n> -       { \"prio-queue\", cmd__prio_queue },\n>         { \"proc-receive\", cmd__proc_receive },\n>         { \"progress\", cmd__progress },\n>         { \"reach\", cmd__reach },\n> diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\n> index 70dd4eba119..b921138d8ec 100644\n> --- a/t/helper/test-tool.h\n> +++ b/t/helper/test-tool.h\n> @@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n>  int cmd__path_utils(int argc, const char **argv);\n>  int cmd__pcre2_config(int argc, const char **argv);\n>  int cmd__pkt_line(int argc, const char **argv);\n> -int cmd__prio_queue(int argc, const char **argv);\n>  int cmd__proc_receive(int argc, const char **argv);\n>  int cmd__progress(int argc, const char **argv);\n>  int cmd__reach(int argc, const char **argv);\n> diff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\n> deleted file mode 100755\n> index eea99107a48..00000000000\n> --- a/t/t0009-prio-queue.sh\n> +++ /dev/null\n> @@ -1,66 +0,0 @@\n> -#!/bin/sh\n> -\n> -test_description='basic tests for priority queue implementation'\n> -\n> -TEST_PASSES_SANITIZE_LEAK=true\n> -. ./test-lib.sh\n> -\n> -cat >expect <<'EOF'\n> -1\n> -2\n> -3\n> -4\n> -5\n> -5\n> -6\n> -7\n> -8\n> -9\n> -10\n> -EOF\n> -test_expect_success 'basic ordering' '\n> -       test-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n> -       test_cmp expect actual\n> -'\n> -\n> -cat >expect <<'EOF'\n> -2\n> -3\n> -4\n> -1\n> -5\n> -6\n> -EOF\n> -test_expect_success 'mixed put and get' '\n> -       test-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n> -       test_cmp expect actual\n> -'\n> -\n> -cat >expect <<'EOF'\n> -1\n> -2\n> -NULL\n> -1\n> -2\n> -NULL\n> -EOF\n> -test_expect_success 'notice empty queue' '\n> -       test-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n> -       test_cmp expect actual\n> -'\n> -\n> -cat >expect <<'EOF'\n> -3\n> -2\n> -6\n> -4\n> -5\n> -1\n> -8\n> -EOF\n> -test_expect_success 'stack order' '\n> -       test-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n> -       test_cmp expect actual\n> -'\n> -\n> -test_done\n> diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\n> new file mode 100644\n> index 00000000000..98a69790f7e\n> --- /dev/null\n> +++ b/t/unit-tests/t-prio-queue.c\n> @@ -0,0 +1,99 @@\n> +#include \"test-lib.h\"\n> +#include \"prio-queue.h\"\n> +\n> +static int intcmp(const void *va, const void *vb, void *data UNUSED)\n> +{\n> +       const int *a = va, *b = vb;\n> +       return *a - *b;\n> +}\n> +\n> +static int show(int *v)\n> +{\n> +       int ret = -1;\n> +       if (v)\n> +               ret = *v;\n> +       free(v);\n> +       return ret;\n> +}\n> +\n> +static int test_prio_queue(const char **input, int *result)\n> +{\n> +       struct prio_queue pq = { intcmp };\n> +       int i = 0;\n> +\n> +       while (*input) {\n> +               if (!strcmp(*input, \"get\")) {\n> +                       void *peek = prio_queue_peek(&pq);\n> +                       void *get = prio_queue_get(&pq);\n> +                       if (peek != get)\n> +                               BUG(\"peek and get results do not match\");\n> +                       result[i++] = show(get);\n> +               } else if (!strcmp(*input, \"dump\")) {\n> +                       void *peek;\n> +                       void *get;\n> +                       while ((peek = prio_queue_peek(&pq))) {\n> +                               get = prio_queue_get(&pq);\n> +                               if (peek != get)\n> +                                       BUG(\"peek and get results do not match\");\n> +                               result[i++] = show(get);\n> +                       }\n> +               } else if (!strcmp(*input, \"stack\")) {\n> +                       pq.compare = NULL;\n> +               } else if (!strcmp(*input, \"reverse\")) {\n> +                       prio_queue_reverse(&pq);\n> +               } else {\n> +                       int *v = xmalloc(sizeof(*v));\n> +                       *v = atoi(*input);\n> +                       prio_queue_put(&pq, v);\n> +               }\n> +               input++;\n> +       }\n> +\n> +       clear_prio_queue(&pq);\n> +\n> +       return 0;\n> +}\n> +\n> +#define INPUT_SIZE 6\n> +\n> +#define BASIC_INPUT \"1\", \"2\", \"3\", \"4\", \"5\", \"5\", \"dump\"\n> +#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n> +\n> +#define MIXED_PUT_GET_INPUT \"6\", \"2\", \"4\", \"get\", \"5\", \"3\", \"get\", \"get\", \"1\", \"dump\"\n> +#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n> +\n> +#define EMPTY_QUEUE_INPUT \"1\", \"2\", \"get\", \"get\", \"get\", \"1\", \"2\", \"get\", \"get\", \"get\"\n> +#define EMPTY_QUEUE_EXPECTED 1, 2, -1, 1, 2, -1\n> +\n> +#define STACK_INPUT \"stack\", \"1\", \"5\", \"4\", \"6\", \"2\", \"3\", \"dump\"\n> +#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n> +\n> +#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n> +#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n> +\n> +#define TEST_INPUT(INPUT, EXPECTED, name)              \\\n> +  static void test_##name(void)                                        \\\n> +{                                                                                      \\\n> +       const char *input[] = {INPUT};                                          \\\n> +       int expected[] = {EXPECTED};                                    \\\n> +       int result[INPUT_SIZE];                                                         \\\n> +       test_prio_queue(input, result);                                         \\\n> +       check(!memcmp(expected, result, sizeof(expected)));     \\\n> +}\n> +\n> +TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n> +TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n> +TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n> +TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n> +TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n> +\n> +int cmd_main(int argc, const char **argv)\n> +{\n> +       TEST(test_basic(), \"prio-queue works for basic input\");\n> +       TEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n> +       TEST(test_empty(), \"prio-queue works when queue is empty\");\n> +       TEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n> +       TEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n> +\n> +       return test_done();\n> +}\n>\n> base-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n> --\n> gitgitgadget\n"},{"id":"486773","messageId":"pull.1642.v2.git.1705220304781.gitgitgadget@gmail.com","threadId":"60741","inReplyTo":"pull.1642.git.1705219829965.gitgitgadget@gmail.com","subject":"[PATCH v2] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Chandra Pratap via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-01-14T08:18:24Z","receivedAt":"2024-01-14T08:18:28Z","isPatch":true,"sender":{"key":"chandrapratap3519@gmail.com","avatar":null},"body":"From: Chandra Pratap <chandrapratap3519@gmail.com>\n\nt/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\ntests Git's implementation of a priority queue. Migrate the\ntest over to the new unit testing framework to simplify debugging\nand reduce test run-time. Refactor the required logic and add\na new test case in addition to porting over the original ones in\nshell.\n\nSigned-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n---\n    tests: move t0009-prio-queue.sh to the new unit testing framework\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/1642\n\nRange-diff vs v1:\n\n 1:  ca20abe95ea ! 1:  60ac9b3c259 tests: move t0009-prio-queue.sh to the new unit testing framework\n     @@ t/unit-tests/t-prio-queue.c (new)\n      +#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n      +#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n      +\n     -+#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\\\n     ++#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n      +  static void test_##name(void)\t\t\t\t\t\\\n     -+{\t\t\t\t\t\t\t\t\t\t\t\\\n     -+\tconst char *input[] = {INPUT};\t\t\t\t\t\t\\\n     -+\tint expected[] = {EXPECTED};\t\t\t\t\t\\\n     -+\tint result[INPUT_SIZE];\t\t\t\t\t\t\t\t\\\n     -+\ttest_prio_queue(input, result);\t\t\t\t\t\t\\\n     ++{\t\t\t\t\t\t\t\t\\\n     ++\tconst char *input[] = {INPUT};\t\t\t\t\\\n     ++\tint expected[] = {EXPECTED};\t\t\t\t\\\n     ++\tint result[INPUT_SIZE];\t\t\t\t\t\\\n     ++\ttest_prio_queue(input, result);\t\t\t\t\\\n      +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n      +}\n      +\n\n\n Makefile                    |  2 +-\n t/helper/test-prio-queue.c  | 51 -------------------\n t/helper/test-tool.c        |  1 -\n t/helper/test-tool.h        |  1 -\n t/t0009-prio-queue.sh       | 66 -------------------------\n t/unit-tests/t-prio-queue.c | 99 +++++++++++++++++++++++++++++++++++++\n 6 files changed, 100 insertions(+), 120 deletions(-)\n delete mode 100644 t/helper/test-prio-queue.c\n delete mode 100755 t/t0009-prio-queue.sh\n create mode 100644 t/unit-tests/t-prio-queue.c\n\ndiff --git a/Makefile b/Makefile\nindex 312d95084c1..d5e48e656b3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n TEST_BUILTINS_OBJS += test-path-utils.o\n TEST_BUILTINS_OBJS += test-pcre2-config.o\n TEST_BUILTINS_OBJS += test-pkt-line.o\n-TEST_BUILTINS_OBJS += test-prio-queue.o\n TEST_BUILTINS_OBJS += test-proc-receive.o\n TEST_BUILTINS_OBJS += test-progress.o\n TEST_BUILTINS_OBJS += test-reach.o\n@@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n \n UNIT_TEST_PROGRAMS += t-basic\n UNIT_TEST_PROGRAMS += t-strbuf\n+UNIT_TEST_PROGRAMS += t-prio-queue\n UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\ndiff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\ndeleted file mode 100644\nindex f0bf255f5f0..00000000000\n--- a/t/helper/test-prio-queue.c\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-#include \"test-tool.h\"\n-#include \"prio-queue.h\"\n-\n-static int intcmp(const void *va, const void *vb, void *data UNUSED)\n-{\n-\tconst int *a = va, *b = vb;\n-\treturn *a - *b;\n-}\n-\n-static void show(int *v)\n-{\n-\tif (!v)\n-\t\tprintf(\"NULL\\n\");\n-\telse\n-\t\tprintf(\"%d\\n\", *v);\n-\tfree(v);\n-}\n-\n-int cmd__prio_queue(int argc UNUSED, const char **argv)\n-{\n-\tstruct prio_queue pq = { intcmp };\n-\n-\twhile (*++argv) {\n-\t\tif (!strcmp(*argv, \"get\")) {\n-\t\t\tvoid *peek = prio_queue_peek(&pq);\n-\t\t\tvoid *get = prio_queue_get(&pq);\n-\t\t\tif (peek != get)\n-\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\tshow(get);\n-\t\t} else if (!strcmp(*argv, \"dump\")) {\n-\t\t\tvoid *peek;\n-\t\t\tvoid *get;\n-\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n-\t\t\t\tget = prio_queue_get(&pq);\n-\t\t\t\tif (peek != get)\n-\t\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\t\tshow(get);\n-\t\t\t}\n-\t\t} else if (!strcmp(*argv, \"stack\")) {\n-\t\t\tpq.compare = NULL;\n-\t\t} else {\n-\t\t\tint *v = xmalloc(sizeof(*v));\n-\t\t\t*v = atoi(*argv);\n-\t\t\tprio_queue_put(&pq, v);\n-\t\t}\n-\t}\n-\n-\tclear_prio_queue(&pq);\n-\n-\treturn 0;\n-}\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex 876cd2dc313..5f591b9718f 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n \t{ \"path-utils\", cmd__path_utils },\n \t{ \"pcre2-config\", cmd__pcre2_config },\n \t{ \"pkt-line\", cmd__pkt_line },\n-\t{ \"prio-queue\", cmd__prio_queue },\n \t{ \"proc-receive\", cmd__proc_receive },\n \t{ \"progress\", cmd__progress },\n \t{ \"reach\", cmd__reach },\ndiff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\nindex 70dd4eba119..b921138d8ec 100644\n--- a/t/helper/test-tool.h\n+++ b/t/helper/test-tool.h\n@@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n int cmd__path_utils(int argc, const char **argv);\n int cmd__pcre2_config(int argc, const char **argv);\n int cmd__pkt_line(int argc, const char **argv);\n-int cmd__prio_queue(int argc, const char **argv);\n int cmd__proc_receive(int argc, const char **argv);\n int cmd__progress(int argc, const char **argv);\n int cmd__reach(int argc, const char **argv);\ndiff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\ndeleted file mode 100755\nindex eea99107a48..00000000000\n--- a/t/t0009-prio-queue.sh\n+++ /dev/null\n@@ -1,66 +0,0 @@\n-#!/bin/sh\n-\n-test_description='basic tests for priority queue implementation'\n-\n-TEST_PASSES_SANITIZE_LEAK=true\n-. ./test-lib.sh\n-\n-cat >expect <<'EOF'\n-1\n-2\n-3\n-4\n-5\n-5\n-6\n-7\n-8\n-9\n-10\n-EOF\n-test_expect_success 'basic ordering' '\n-\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-2\n-3\n-4\n-1\n-5\n-6\n-EOF\n-test_expect_success 'mixed put and get' '\n-\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-1\n-2\n-NULL\n-1\n-2\n-NULL\n-EOF\n-test_expect_success 'notice empty queue' '\n-\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-3\n-2\n-6\n-4\n-5\n-1\n-8\n-EOF\n-test_expect_success 'stack order' '\n-\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-test_done\ndiff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\nnew file mode 100644\nindex 00000000000..07b112f5894\n--- /dev/null\n+++ b/t/unit-tests/t-prio-queue.c\n@@ -0,0 +1,99 @@\n+#include \"test-lib.h\"\n+#include \"prio-queue.h\"\n+\n+static int intcmp(const void *va, const void *vb, void *data UNUSED)\n+{\n+\tconst int *a = va, *b = vb;\n+\treturn *a - *b;\n+}\n+\n+static int show(int *v)\n+{\n+\tint ret = -1;\n+\tif (v)\n+\t\tret = *v;\n+\tfree(v);\n+\treturn ret;\n+}\n+\n+static int test_prio_queue(const char **input, int *result)\n+{\n+\tstruct prio_queue pq = { intcmp };\n+\tint i = 0;\n+\n+\twhile (*input) {\n+\t\tif (!strcmp(*input, \"get\")) {\n+\t\t\tvoid *peek = prio_queue_peek(&pq);\n+\t\t\tvoid *get = prio_queue_get(&pq);\n+\t\t\tif (peek != get)\n+\t\t\t\tBUG(\"peek and get results do not match\");\n+\t\t\tresult[i++] = show(get);\n+\t\t} else if (!strcmp(*input, \"dump\")) {\n+\t\t\tvoid *peek;\n+\t\t\tvoid *get;\n+\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n+\t\t\t\tget = prio_queue_get(&pq);\n+\t\t\t\tif (peek != get)\n+\t\t\t\t\tBUG(\"peek and get results do not match\");\n+\t\t\t\tresult[i++] = show(get);\n+\t\t\t}\n+\t\t} else if (!strcmp(*input, \"stack\")) {\n+\t\t\tpq.compare = NULL;\n+\t\t} else if (!strcmp(*input, \"reverse\")) {\n+\t\t\tprio_queue_reverse(&pq);\n+\t\t} else {\n+\t\t\tint *v = xmalloc(sizeof(*v));\n+\t\t\t*v = atoi(*input);\n+\t\t\tprio_queue_put(&pq, v);\n+\t\t}\n+\t\tinput++;\n+\t}\n+\n+\tclear_prio_queue(&pq);\n+\n+\treturn 0;\n+}\n+\n+#define INPUT_SIZE 6\n+\n+#define BASIC_INPUT \"1\", \"2\", \"3\", \"4\", \"5\", \"5\", \"dump\"\n+#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n+\n+#define MIXED_PUT_GET_INPUT \"6\", \"2\", \"4\", \"get\", \"5\", \"3\", \"get\", \"get\", \"1\", \"dump\"\n+#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n+\n+#define EMPTY_QUEUE_INPUT \"1\", \"2\", \"get\", \"get\", \"get\", \"1\", \"2\", \"get\", \"get\", \"get\"\n+#define EMPTY_QUEUE_EXPECTED 1, 2, -1, 1, 2, -1\n+\n+#define STACK_INPUT \"stack\", \"1\", \"5\", \"4\", \"6\", \"2\", \"3\", \"dump\"\n+#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n+\n+#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n+#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n+\n+#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n+  static void test_##name(void)\t\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\\\n+\tconst char *input[] = {INPUT};\t\t\t\t\\\n+\tint expected[] = {EXPECTED};\t\t\t\t\\\n+\tint result[INPUT_SIZE];\t\t\t\t\t\\\n+\ttest_prio_queue(input, result);\t\t\t\t\\\n+\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n+}\n+\n+TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n+TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n+TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n+TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n+TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n+\n+int cmd_main(int argc, const char **argv)\n+{\n+\tTEST(test_basic(), \"prio-queue works for basic input\");\n+\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n+\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n+\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n+\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n+\n+\treturn test_done();\n+}\n\nbase-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n-- \ngitgitgadget\n"},{"id":"486848","messageId":"xmqqzfx51bhf.fsf@gitster.g","threadId":"60741","inReplyTo":"pull.1642.v2.git.1705220304781.gitgitgadget@gmail.com","subject":"Re: [PATCH v2] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-01-16T16:36:44Z","receivedAt":"2024-01-16T16:36:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Chandra Pratap via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\n> new file mode 100644\n> index 00000000000..07b112f5894\n> --- /dev/null\n> +++ b/t/unit-tests/t-prio-queue.c\n> @@ -0,0 +1,99 @@\n> +#include \"test-lib.h\"\n> +#include \"prio-queue.h\"\n> +\n> +static int intcmp(const void *va, const void *vb, void *data UNUSED)\n> +{\n> +\tconst int *a = va, *b = vb;\n> +\treturn *a - *b;\n> +}\n\nThis came from the original and looks obviously OK.\n\n> +static int show(int *v)\n> +{\n> +\tint ret = -1;\n> +\tif (v)\n> +\t\tret = *v;\n> +\tfree(v);\n> +\treturn ret;\n> +}\n\nThe original allowed us to differentiate \"prio queue did not yield\nanything\" case and \"the integer obtained from the queue happened to\nbe negative\" cases, but with this, -1 is taken.\n\nIt is not a huge loss, as the tests can limit themselves to a subset\nof \"int\" (say, positive integers only).  But this realization can\nlead to further simplfication.\n\n> +static int test_prio_queue(const char **input, int *result)\n\nThis takes an array of strings, but it does not have to.  Make it\ntake an array of \"int\" and then with something like\n\n\t#define MISSING\t-1\n        #define GET\t-2\n        #define DUMP\t-3\n\t#define STACK\t-4\n\nyou can get rid of strcmp(), atoi(), and xmalloc(), like so:\n\n\twhile (*input) {\n\t\tint val = *input++;\n\n\t\tswitch (val) {\n\t\tcase GET:\n\t\t\tvoid *peek = prio_queue_peek(&pq);\n\t\t\t...\n\t\t\tresult[i++] = peek ? (*(int*)peek) : MISSING;\n\t\t\tbreak;\n\t\t... other \"commands\" here ...\n\t\tdefault:\n\t\t\tprio_queue_put(&pq, val);\n\t\t\tbreak;\t\t\t\n\t\t}\n\t}\n\nI inlined the show() in the above illustration, but you can keep it\nas a separate small helper function.  The point is that it makes it\nfar easier to follow by using the MISSING symbolic constant either\nway.\n\n> +{\n> +\tstruct prio_queue pq = { intcmp };\n> +\tint i = 0;\n> +\n> +\twhile (*input) {\n> +\t\tif (!strcmp(*input, \"get\")) {\n> +\t\t\tvoid *peek = prio_queue_peek(&pq);\n> +\t\t\tvoid *get = prio_queue_get(&pq);\n> +\t\t\tif (peek != get)\n> +\t\t\t\tBUG(\"peek and get results do not match\");\n> +\t\t\tresult[i++] = show(get);\n> +\t\t} else if (!strcmp(*input, \"dump\")) {\n> +\t\t\tvoid *peek;\n> +\t\t\tvoid *get;\n> +\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n> +\t\t\t\tget = prio_queue_get(&pq);\n> +\t\t\t\tif (peek != get)\n> +\t\t\t\t\tBUG(\"peek and get results do not match\");\n> +\t\t\t\tresult[i++] = show(get);\n> +\t\t\t}\n> +\t\t} else if (!strcmp(*input, \"stack\")) {\n> +\t\t\tpq.compare = NULL;\n> +\t\t} else if (!strcmp(*input, \"reverse\")) {\n> +\t\t\tprio_queue_reverse(&pq);\n> +\t\t} else {\n> +\t\t\tint *v = xmalloc(sizeof(*v));\n> +\t\t\t*v = atoi(*input);\n> +\t\t\tprio_queue_put(&pq, v);\n> +\t\t}\n> +\t\tinput++;\n> +\t}\n> +\n> +\tclear_prio_queue(&pq);\n> +\n> +\treturn 0;\n> +}\n> +\n> +#define INPUT_SIZE 6\n\nYou do not need this (see below)\n\n> +#define BASIC_INPUT \"1\", \"2\", \"3\", \"4\", \"5\", \"5\", \"dump\"\n> +#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n> +\n> +#define MIXED_PUT_GET_INPUT \"6\", \"2\", \"4\", \"get\", \"5\", \"3\", \"get\", \"get\", \"1\", \"dump\"\n> +#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n> +\n> +#define EMPTY_QUEUE_INPUT \"1\", \"2\", \"get\", \"get\", \"get\", \"1\", \"2\", \"get\", \"get\", \"get\"\n> +#define EMPTY_QUEUE_EXPECTED 1, 2, -1, 1, 2, -1\n\nAnd these input and expectation can become all integers, i.e.\n\n\t#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n\t#define EMPTY_QUEUE_EXPECTED 1, 2, MISSING, 1, 2, MISSING\n\n> +\n> +#define STACK_INPUT \"stack\", \"1\", \"5\", \"4\", \"6\", \"2\", \"3\", \"dump\"\n> +#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n> +\n> +#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n> +#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n> +\n> +#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n> +  static void test_##name(void)\t\t\t\t\t\\\n> +{\t\t\t\t\t\t\t\t\\\n> +\tconst char *input[] = {INPUT};\t\t\t\t\\\n> +\tint expected[] = {EXPECTED};\t\t\t\t\\\n> +\tint result[INPUT_SIZE];\t\t\t\t\t\\\n\nThis can be written more like\n\n\tint result[ARRAY_SIZE(expected)]\n\nso that you can freely extend each test without having to worry\nabout increasing the hardcoded limit.\n\n> +\ttest_prio_queue(input, result);\t\t\t\t\\\n> +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n> +}\n> +\n> +TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n> +TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n> +TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n> +TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n> +TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n> +\n> +int cmd_main(int argc, const char **argv)\n> +{\n> +\tTEST(test_basic(), \"prio-queue works for basic input\");\n> +\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n> +\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n> +\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n> +\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n> +\n> +\treturn test_done();\n> +}\n>\n> base-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n"},{"id":"486905","messageId":"ZadtPeTiS1HmM7aw@google.com","threadId":"60741","inReplyTo":"pull.1642.v2.git.1705220304781.gitgitgadget@gmail.com","subject":"Re: [PATCH v2] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Josh Steadmon","fromEmail":"steadmon@google.com","sentAt":"2024-01-17T06:01:33Z","receivedAt":"2024-01-17T06:01:40Z","isPatch":true,"sender":{"key":"steadmon@google.com","avatar":"https://avatars.githubusercontent.com/u/2654920?v=4"},"body":"On 2024.01.14 08:18, Chandra Pratap via GitGitGadget wrote:\n> From: Chandra Pratap <chandrapratap3519@gmail.com>\n> \n> t/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\n> tests Git's implementation of a priority queue. Migrate the\n> test over to the new unit testing framework to simplify debugging\n> and reduce test run-time. Refactor the required logic and add\n> a new test case in addition to porting over the original ones in\n> shell.\n> \n> Signed-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n> ---\n>     tests: move t0009-prio-queue.sh to the new unit testing framework\n> \n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v2\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v2\n> Pull-Request: https://github.com/gitgitgadget/git/pull/1642\n> \n> Range-diff vs v1:\n> \n>  1:  ca20abe95ea ! 1:  60ac9b3c259 tests: move t0009-prio-queue.sh to the new unit testing framework\n>      @@ t/unit-tests/t-prio-queue.c (new)\n>       +#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n>       +#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n>       +\n>      -+#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\\\n>      ++#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n>       +  static void test_##name(void)\t\t\t\t\t\\\n>      -+{\t\t\t\t\t\t\t\t\t\t\t\\\n>      -+\tconst char *input[] = {INPUT};\t\t\t\t\t\t\\\n>      -+\tint expected[] = {EXPECTED};\t\t\t\t\t\\\n>      -+\tint result[INPUT_SIZE];\t\t\t\t\t\t\t\t\\\n>      -+\ttest_prio_queue(input, result);\t\t\t\t\t\t\\\n>      ++{\t\t\t\t\t\t\t\t\\\n>      ++\tconst char *input[] = {INPUT};\t\t\t\t\\\n>      ++\tint expected[] = {EXPECTED};\t\t\t\t\\\n>      ++\tint result[INPUT_SIZE];\t\t\t\t\t\\\n>      ++\ttest_prio_queue(input, result);\t\t\t\t\\\n>       +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n>       +}\n>       +\n> \n> \n>  Makefile                    |  2 +-\n>  t/helper/test-prio-queue.c  | 51 -------------------\n>  t/helper/test-tool.c        |  1 -\n>  t/helper/test-tool.h        |  1 -\n>  t/t0009-prio-queue.sh       | 66 -------------------------\n>  t/unit-tests/t-prio-queue.c | 99 +++++++++++++++++++++++++++++++++++++\n>  6 files changed, 100 insertions(+), 120 deletions(-)\n>  delete mode 100644 t/helper/test-prio-queue.c\n>  delete mode 100755 t/t0009-prio-queue.sh\n>  create mode 100644 t/unit-tests/t-prio-queue.c\n> \n> diff --git a/Makefile b/Makefile\n> index 312d95084c1..d5e48e656b3 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n>  TEST_BUILTINS_OBJS += test-path-utils.o\n>  TEST_BUILTINS_OBJS += test-pcre2-config.o\n>  TEST_BUILTINS_OBJS += test-pkt-line.o\n> -TEST_BUILTINS_OBJS += test-prio-queue.o\n>  TEST_BUILTINS_OBJS += test-proc-receive.o\n>  TEST_BUILTINS_OBJS += test-progress.o\n>  TEST_BUILTINS_OBJS += test-reach.o\n> @@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n>  \n>  UNIT_TEST_PROGRAMS += t-basic\n>  UNIT_TEST_PROGRAMS += t-strbuf\n> +UNIT_TEST_PROGRAMS += t-prio-queue\n>  UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n>  UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n>  UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n> diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\n> deleted file mode 100644\n> index f0bf255f5f0..00000000000\n> --- a/t/helper/test-prio-queue.c\n> +++ /dev/null\n> @@ -1,51 +0,0 @@\n> -#include \"test-tool.h\"\n> -#include \"prio-queue.h\"\n> -\n> -static int intcmp(const void *va, const void *vb, void *data UNUSED)\n> -{\n> -\tconst int *a = va, *b = vb;\n> -\treturn *a - *b;\n> -}\n> -\n> -static void show(int *v)\n> -{\n> -\tif (!v)\n> -\t\tprintf(\"NULL\\n\");\n> -\telse\n> -\t\tprintf(\"%d\\n\", *v);\n> -\tfree(v);\n> -}\n> -\n> -int cmd__prio_queue(int argc UNUSED, const char **argv)\n> -{\n> -\tstruct prio_queue pq = { intcmp };\n> -\n> -\twhile (*++argv) {\n> -\t\tif (!strcmp(*argv, \"get\")) {\n> -\t\t\tvoid *peek = prio_queue_peek(&pq);\n> -\t\t\tvoid *get = prio_queue_get(&pq);\n> -\t\t\tif (peek != get)\n> -\t\t\t\tBUG(\"peek and get results do not match\");\n> -\t\t\tshow(get);\n> -\t\t} else if (!strcmp(*argv, \"dump\")) {\n> -\t\t\tvoid *peek;\n> -\t\t\tvoid *get;\n> -\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n> -\t\t\t\tget = prio_queue_get(&pq);\n> -\t\t\t\tif (peek != get)\n> -\t\t\t\t\tBUG(\"peek and get results do not match\");\n> -\t\t\t\tshow(get);\n> -\t\t\t}\n> -\t\t} else if (!strcmp(*argv, \"stack\")) {\n> -\t\t\tpq.compare = NULL;\n> -\t\t} else {\n> -\t\t\tint *v = xmalloc(sizeof(*v));\n> -\t\t\t*v = atoi(*argv);\n> -\t\t\tprio_queue_put(&pq, v);\n> -\t\t}\n> -\t}\n> -\n> -\tclear_prio_queue(&pq);\n> -\n> -\treturn 0;\n> -}\n> diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\n> index 876cd2dc313..5f591b9718f 100644\n> --- a/t/helper/test-tool.c\n> +++ b/t/helper/test-tool.c\n> @@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n>  \t{ \"path-utils\", cmd__path_utils },\n>  \t{ \"pcre2-config\", cmd__pcre2_config },\n>  \t{ \"pkt-line\", cmd__pkt_line },\n> -\t{ \"prio-queue\", cmd__prio_queue },\n>  \t{ \"proc-receive\", cmd__proc_receive },\n>  \t{ \"progress\", cmd__progress },\n>  \t{ \"reach\", cmd__reach },\n> diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\n> index 70dd4eba119..b921138d8ec 100644\n> --- a/t/helper/test-tool.h\n> +++ b/t/helper/test-tool.h\n> @@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n>  int cmd__path_utils(int argc, const char **argv);\n>  int cmd__pcre2_config(int argc, const char **argv);\n>  int cmd__pkt_line(int argc, const char **argv);\n> -int cmd__prio_queue(int argc, const char **argv);\n>  int cmd__proc_receive(int argc, const char **argv);\n>  int cmd__progress(int argc, const char **argv);\n>  int cmd__reach(int argc, const char **argv);\n> diff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\n> deleted file mode 100755\n> index eea99107a48..00000000000\n> --- a/t/t0009-prio-queue.sh\n> +++ /dev/null\n> @@ -1,66 +0,0 @@\n> -#!/bin/sh\n> -\n> -test_description='basic tests for priority queue implementation'\n> -\n> -TEST_PASSES_SANITIZE_LEAK=true\n> -. ./test-lib.sh\n> -\n> -cat >expect <<'EOF'\n> -1\n> -2\n> -3\n> -4\n> -5\n> -5\n> -6\n> -7\n> -8\n> -9\n> -10\n> -EOF\n> -test_expect_success 'basic ordering' '\n> -\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n> -\ttest_cmp expect actual\n> -'\n> -\n> -cat >expect <<'EOF'\n> -2\n> -3\n> -4\n> -1\n> -5\n> -6\n> -EOF\n> -test_expect_success 'mixed put and get' '\n> -\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n> -\ttest_cmp expect actual\n> -'\n> -\n> -cat >expect <<'EOF'\n> -1\n> -2\n> -NULL\n> -1\n> -2\n> -NULL\n> -EOF\n> -test_expect_success 'notice empty queue' '\n> -\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n> -\ttest_cmp expect actual\n> -'\n> -\n> -cat >expect <<'EOF'\n> -3\n> -2\n> -6\n> -4\n> -5\n> -1\n> -8\n> -EOF\n> -test_expect_success 'stack order' '\n> -\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n> -\ttest_cmp expect actual\n> -'\n> -\n> -test_done\n> diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\n> new file mode 100644\n> index 00000000000..07b112f5894\n> --- /dev/null\n> +++ b/t/unit-tests/t-prio-queue.c\n> @@ -0,0 +1,99 @@\n> +#include \"test-lib.h\"\n> +#include \"prio-queue.h\"\n> +\n> +static int intcmp(const void *va, const void *vb, void *data UNUSED)\n> +{\n> +\tconst int *a = va, *b = vb;\n> +\treturn *a - *b;\n> +}\n> +\n> +static int show(int *v)\n> +{\n> +\tint ret = -1;\n> +\tif (v)\n> +\t\tret = *v;\n> +\tfree(v);\n> +\treturn ret;\n> +}\n> +\n> +static int test_prio_queue(const char **input, int *result)\n> +{\n> +\tstruct prio_queue pq = { intcmp };\n> +\tint i = 0;\n> +\n> +\twhile (*input) {\n> +\t\tif (!strcmp(*input, \"get\")) {\n\nRunning the test segfaults at the above strcmp() for me, from the very\nfirst test_basic test case. I'm not sure why, there's not an obvious\nproblem that I can see. Does it run properly for you?\n\n\n> +\t\t\tvoid *peek = prio_queue_peek(&pq);\n> +\t\t\tvoid *get = prio_queue_get(&pq);\n> +\t\t\tif (peek != get)\n> +\t\t\t\tBUG(\"peek and get results do not match\");\n> +\t\t\tresult[i++] = show(get);\n> +\t\t} else if (!strcmp(*input, \"dump\")) {\n> +\t\t\tvoid *peek;\n> +\t\t\tvoid *get;\n> +\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n> +\t\t\t\tget = prio_queue_get(&pq);\n> +\t\t\t\tif (peek != get)\n> +\t\t\t\t\tBUG(\"peek and get results do not match\");\n> +\t\t\t\tresult[i++] = show(get);\n> +\t\t\t}\n> +\t\t} else if (!strcmp(*input, \"stack\")) {\n> +\t\t\tpq.compare = NULL;\n> +\t\t} else if (!strcmp(*input, \"reverse\")) {\n> +\t\t\tprio_queue_reverse(&pq);\n> +\t\t} else {\n> +\t\t\tint *v = xmalloc(sizeof(*v));\n> +\t\t\t*v = atoi(*input);\n> +\t\t\tprio_queue_put(&pq, v);\n> +\t\t}\n> +\t\tinput++;\n> +\t}\n> +\n> +\tclear_prio_queue(&pq);\n> +\n> +\treturn 0;\n> +}\n> +\n> +#define INPUT_SIZE 6\n> +\n> +#define BASIC_INPUT \"1\", \"2\", \"3\", \"4\", \"5\", \"5\", \"dump\"\n> +#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n> +\n> +#define MIXED_PUT_GET_INPUT \"6\", \"2\", \"4\", \"get\", \"5\", \"3\", \"get\", \"get\", \"1\", \"dump\"\n> +#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n> +\n> +#define EMPTY_QUEUE_INPUT \"1\", \"2\", \"get\", \"get\", \"get\", \"1\", \"2\", \"get\", \"get\", \"get\"\n> +#define EMPTY_QUEUE_EXPECTED 1, 2, -1, 1, 2, -1\n> +\n> +#define STACK_INPUT \"stack\", \"1\", \"5\", \"4\", \"6\", \"2\", \"3\", \"dump\"\n> +#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n> +\n> +#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n> +#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n> +\n> +#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n> +  static void test_##name(void)\t\t\t\t\t\\\n> +{\t\t\t\t\t\t\t\t\\\n> +\tconst char *input[] = {INPUT};\t\t\t\t\\\n> +\tint expected[] = {EXPECTED};\t\t\t\t\\\n> +\tint result[INPUT_SIZE];\t\t\t\t\t\\\n> +\ttest_prio_queue(input, result);\t\t\t\t\\\n> +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n> +}\n> +\n> +TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n> +TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n> +TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n> +TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n> +TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n> +\n> +int cmd_main(int argc, const char **argv)\n> +{\n> +\tTEST(test_basic(), \"prio-queue works for basic input\");\n> +\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n> +\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n> +\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n> +\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n> +\n> +\treturn test_done();\n> +}\n> \n> base-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n> -- \n> gitgitgadget\n"},{"id":"486916","messageId":"pull.1642.v3.git.1705502304219.gitgitgadget@gmail.com","threadId":"60741","inReplyTo":"pull.1642.v2.git.1705220304781.gitgitgadget@gmail.com","subject":"[PATCH v3] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Chandra Pratap via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-01-17T14:38:23Z","receivedAt":"2024-01-17T14:38:28Z","isPatch":true,"sender":{"key":"chandrapratap3519@gmail.com","avatar":null},"body":"From: Chandra Pratap <chandrapratap3519@gmail.com>\n\nt/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\ntests Git's implementation of a priority queue. Migrate the\ntest over to the new unit testing framework to simplify debugging\nand reduce test run-time. Refactor the required logic and add\na new test case in addition to porting over the original ones in\nshell.\n\nSigned-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n---\n    tests: move t0009-prio-queue.sh to the new unit testing framework\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/1642\n\nRange-diff vs v2:\n\n 1:  60ac9b3c259 ! 1:  6b10028177a tests: move t0009-prio-queue.sh to the new unit testing framework\n     @@ t/unit-tests/t-prio-queue.c (new)\n      +\treturn *a - *b;\n      +}\n      +\n     ++\n     ++#define MISSING  -1\n     ++#define DUMP\t -2\n     ++#define STACK\t -3\n     ++#define GET\t -4\n     ++#define REVERSE  -5\n     ++\n      +static int show(int *v)\n      +{\n     -+\tint ret = -1;\n     -+\tif (v)\n     -+\t\tret = *v;\n     -+\tfree(v);\n     -+\treturn ret;\n     ++\treturn v ? *v : MISSING;\n      +}\n      +\n     -+static int test_prio_queue(const char **input, int *result)\n     ++static int test_prio_queue(int *input, int *result)\n      +{\n      +\tstruct prio_queue pq = { intcmp };\n      +\tint i = 0;\n      +\n      +\twhile (*input) {\n     -+\t\tif (!strcmp(*input, \"get\")) {\n     -+\t\t\tvoid *peek = prio_queue_peek(&pq);\n     -+\t\t\tvoid *get = prio_queue_get(&pq);\n     -+\t\t\tif (peek != get)\n     -+\t\t\t\tBUG(\"peek and get results do not match\");\n     -+\t\t\tresult[i++] = show(get);\n     -+\t\t} else if (!strcmp(*input, \"dump\")) {\n     -+\t\t\tvoid *peek;\n     -+\t\t\tvoid *get;\n     -+\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n     ++\t\tint *val = input++;\n     ++\t\tvoid *peek, *get;\n     ++\t\tswitch(*val) {\n     ++\t\t\tcase GET:\n     ++\t\t\t\tpeek = prio_queue_peek(&pq);\n      +\t\t\t\tget = prio_queue_get(&pq);\n      +\t\t\t\tif (peek != get)\n     -+\t\t\t\t\tBUG(\"peek and get results do not match\");\n     ++\t\t\t\t\tBUG(\"peek and get results don't match\");\n      +\t\t\t\tresult[i++] = show(get);\n     -+\t\t\t}\n     -+\t\t} else if (!strcmp(*input, \"stack\")) {\n     -+\t\t\tpq.compare = NULL;\n     -+\t\t} else if (!strcmp(*input, \"reverse\")) {\n     -+\t\t\tprio_queue_reverse(&pq);\n     -+\t\t} else {\n     -+\t\t\tint *v = xmalloc(sizeof(*v));\n     -+\t\t\t*v = atoi(*input);\n     -+\t\t\tprio_queue_put(&pq, v);\n     ++\t\t\t\tbreak;\n     ++\t\t\tcase DUMP:\n     ++\t\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n     ++\t\t\t\t\tget = prio_queue_get(&pq);\n     ++\t\t\t\t\tif (peek != get)\n     ++\t\t\t\t\t\tBUG(\"peek and get results don't match\");\n     ++\t\t\t\t\tresult[i++] = show(get);\n     ++\t\t\t\t}\n     ++\t\t\t\tbreak;\n     ++\t\t\tcase STACK:\n     ++\t\t\t\tpq.compare = NULL;\n     ++\t\t\t\tbreak;\n     ++\t\t\tcase REVERSE:\n     ++\t\t\t\tprio_queue_reverse(&pq);\n     ++\t\t\t\tbreak;\n     ++\t\t\tdefault:\n     ++\t\t\t\tprio_queue_put(&pq, val);\n     ++\t\t\t\tbreak;\n      +\t\t}\n     -+\t\tinput++;\n      +\t}\n     -+\n      +\tclear_prio_queue(&pq);\n     -+\n      +\treturn 0;\n      +}\n      +\n     -+#define INPUT_SIZE 6\n     -+\n     -+#define BASIC_INPUT \"1\", \"2\", \"3\", \"4\", \"5\", \"5\", \"dump\"\n     ++#define BASIC_INPUT 1, 2, 3, 4, 5, 5, DUMP\n      +#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n      +\n     -+#define MIXED_PUT_GET_INPUT \"6\", \"2\", \"4\", \"get\", \"5\", \"3\", \"get\", \"get\", \"1\", \"dump\"\n     ++#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n      +#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n      +\n     -+#define EMPTY_QUEUE_INPUT \"1\", \"2\", \"get\", \"get\", \"get\", \"1\", \"2\", \"get\", \"get\", \"get\"\n     -+#define EMPTY_QUEUE_EXPECTED 1, 2, -1, 1, 2, -1\n     ++#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n     ++#define EMPTY_QUEUE_EXPECTED 1, 2, MISSING, 1, 2, MISSING\n      +\n     -+#define STACK_INPUT \"stack\", \"1\", \"5\", \"4\", \"6\", \"2\", \"3\", \"dump\"\n     ++#define STACK_INPUT STACK, 1, 5, 4, 6, 2, 3, DUMP\n      +#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n      +\n     -+#define REVERSE_STACK_INPUT \"stack\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"reverse\", \"dump\"\n     ++#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n      +#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n      +\n      +#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n     -+  static void test_##name(void)\t\t\t\t\t\\\n     ++  static void test_##name(void)\t\t\t\t\\\n      +{\t\t\t\t\t\t\t\t\\\n     -+\tconst char *input[] = {INPUT};\t\t\t\t\\\n     ++\tint input[] = {INPUT};\t\t\t\t\t\\\n      +\tint expected[] = {EXPECTED};\t\t\t\t\\\n     -+\tint result[INPUT_SIZE];\t\t\t\t\t\\\n     ++\tint result[ARRAY_SIZE(expected)];\t\t\t\\\n      +\ttest_prio_queue(input, result);\t\t\t\t\\\n      +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n      +}\n\n\n Makefile                    |   2 +-\n t/helper/test-prio-queue.c  |  51 ------------------\n t/helper/test-tool.c        |   1 -\n t/helper/test-tool.h        |   1 -\n t/t0009-prio-queue.sh       |  66 -----------------------\n t/unit-tests/t-prio-queue.c | 101 ++++++++++++++++++++++++++++++++++++\n 6 files changed, 102 insertions(+), 120 deletions(-)\n delete mode 100644 t/helper/test-prio-queue.c\n delete mode 100755 t/t0009-prio-queue.sh\n create mode 100644 t/unit-tests/t-prio-queue.c\n\ndiff --git a/Makefile b/Makefile\nindex 312d95084c1..d5e48e656b3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n TEST_BUILTINS_OBJS += test-path-utils.o\n TEST_BUILTINS_OBJS += test-pcre2-config.o\n TEST_BUILTINS_OBJS += test-pkt-line.o\n-TEST_BUILTINS_OBJS += test-prio-queue.o\n TEST_BUILTINS_OBJS += test-proc-receive.o\n TEST_BUILTINS_OBJS += test-progress.o\n TEST_BUILTINS_OBJS += test-reach.o\n@@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n \n UNIT_TEST_PROGRAMS += t-basic\n UNIT_TEST_PROGRAMS += t-strbuf\n+UNIT_TEST_PROGRAMS += t-prio-queue\n UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\ndiff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\ndeleted file mode 100644\nindex f0bf255f5f0..00000000000\n--- a/t/helper/test-prio-queue.c\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-#include \"test-tool.h\"\n-#include \"prio-queue.h\"\n-\n-static int intcmp(const void *va, const void *vb, void *data UNUSED)\n-{\n-\tconst int *a = va, *b = vb;\n-\treturn *a - *b;\n-}\n-\n-static void show(int *v)\n-{\n-\tif (!v)\n-\t\tprintf(\"NULL\\n\");\n-\telse\n-\t\tprintf(\"%d\\n\", *v);\n-\tfree(v);\n-}\n-\n-int cmd__prio_queue(int argc UNUSED, const char **argv)\n-{\n-\tstruct prio_queue pq = { intcmp };\n-\n-\twhile (*++argv) {\n-\t\tif (!strcmp(*argv, \"get\")) {\n-\t\t\tvoid *peek = prio_queue_peek(&pq);\n-\t\t\tvoid *get = prio_queue_get(&pq);\n-\t\t\tif (peek != get)\n-\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\tshow(get);\n-\t\t} else if (!strcmp(*argv, \"dump\")) {\n-\t\t\tvoid *peek;\n-\t\t\tvoid *get;\n-\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n-\t\t\t\tget = prio_queue_get(&pq);\n-\t\t\t\tif (peek != get)\n-\t\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\t\tshow(get);\n-\t\t\t}\n-\t\t} else if (!strcmp(*argv, \"stack\")) {\n-\t\t\tpq.compare = NULL;\n-\t\t} else {\n-\t\t\tint *v = xmalloc(sizeof(*v));\n-\t\t\t*v = atoi(*argv);\n-\t\t\tprio_queue_put(&pq, v);\n-\t\t}\n-\t}\n-\n-\tclear_prio_queue(&pq);\n-\n-\treturn 0;\n-}\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex 876cd2dc313..5f591b9718f 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n \t{ \"path-utils\", cmd__path_utils },\n \t{ \"pcre2-config\", cmd__pcre2_config },\n \t{ \"pkt-line\", cmd__pkt_line },\n-\t{ \"prio-queue\", cmd__prio_queue },\n \t{ \"proc-receive\", cmd__proc_receive },\n \t{ \"progress\", cmd__progress },\n \t{ \"reach\", cmd__reach },\ndiff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\nindex 70dd4eba119..b921138d8ec 100644\n--- a/t/helper/test-tool.h\n+++ b/t/helper/test-tool.h\n@@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n int cmd__path_utils(int argc, const char **argv);\n int cmd__pcre2_config(int argc, const char **argv);\n int cmd__pkt_line(int argc, const char **argv);\n-int cmd__prio_queue(int argc, const char **argv);\n int cmd__proc_receive(int argc, const char **argv);\n int cmd__progress(int argc, const char **argv);\n int cmd__reach(int argc, const char **argv);\ndiff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\ndeleted file mode 100755\nindex eea99107a48..00000000000\n--- a/t/t0009-prio-queue.sh\n+++ /dev/null\n@@ -1,66 +0,0 @@\n-#!/bin/sh\n-\n-test_description='basic tests for priority queue implementation'\n-\n-TEST_PASSES_SANITIZE_LEAK=true\n-. ./test-lib.sh\n-\n-cat >expect <<'EOF'\n-1\n-2\n-3\n-4\n-5\n-5\n-6\n-7\n-8\n-9\n-10\n-EOF\n-test_expect_success 'basic ordering' '\n-\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-2\n-3\n-4\n-1\n-5\n-6\n-EOF\n-test_expect_success 'mixed put and get' '\n-\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-1\n-2\n-NULL\n-1\n-2\n-NULL\n-EOF\n-test_expect_success 'notice empty queue' '\n-\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-3\n-2\n-6\n-4\n-5\n-1\n-8\n-EOF\n-test_expect_success 'stack order' '\n-\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-test_done\ndiff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\nnew file mode 100644\nindex 00000000000..0b826b463e9\n--- /dev/null\n+++ b/t/unit-tests/t-prio-queue.c\n@@ -0,0 +1,101 @@\n+#include \"test-lib.h\"\n+#include \"prio-queue.h\"\n+\n+static int intcmp(const void *va, const void *vb, void *data UNUSED)\n+{\n+\tconst int *a = va, *b = vb;\n+\treturn *a - *b;\n+}\n+\n+\n+#define MISSING  -1\n+#define DUMP\t -2\n+#define STACK\t -3\n+#define GET\t -4\n+#define REVERSE  -5\n+\n+static int show(int *v)\n+{\n+\treturn v ? *v : MISSING;\n+}\n+\n+static int test_prio_queue(int *input, int *result)\n+{\n+\tstruct prio_queue pq = { intcmp };\n+\tint i = 0;\n+\n+\twhile (*input) {\n+\t\tint *val = input++;\n+\t\tvoid *peek, *get;\n+\t\tswitch(*val) {\n+\t\t\tcase GET:\n+\t\t\t\tpeek = prio_queue_peek(&pq);\n+\t\t\t\tget = prio_queue_get(&pq);\n+\t\t\t\tif (peek != get)\n+\t\t\t\t\tBUG(\"peek and get results don't match\");\n+\t\t\t\tresult[i++] = show(get);\n+\t\t\t\tbreak;\n+\t\t\tcase DUMP:\n+\t\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n+\t\t\t\t\tget = prio_queue_get(&pq);\n+\t\t\t\t\tif (peek != get)\n+\t\t\t\t\t\tBUG(\"peek and get results don't match\");\n+\t\t\t\t\tresult[i++] = show(get);\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\tcase STACK:\n+\t\t\t\tpq.compare = NULL;\n+\t\t\t\tbreak;\n+\t\t\tcase REVERSE:\n+\t\t\t\tprio_queue_reverse(&pq);\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tprio_queue_put(&pq, val);\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\tclear_prio_queue(&pq);\n+\treturn 0;\n+}\n+\n+#define BASIC_INPUT 1, 2, 3, 4, 5, 5, DUMP\n+#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n+\n+#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n+#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n+\n+#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n+#define EMPTY_QUEUE_EXPECTED 1, 2, MISSING, 1, 2, MISSING\n+\n+#define STACK_INPUT STACK, 1, 5, 4, 6, 2, 3, DUMP\n+#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n+\n+#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n+#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n+\n+#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n+  static void test_##name(void)\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\\\n+\tint input[] = {INPUT};\t\t\t\t\t\\\n+\tint expected[] = {EXPECTED};\t\t\t\t\\\n+\tint result[ARRAY_SIZE(expected)];\t\t\t\\\n+\ttest_prio_queue(input, result);\t\t\t\t\\\n+\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n+}\n+\n+TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n+TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n+TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n+TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n+TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n+\n+int cmd_main(int argc, const char **argv)\n+{\n+\tTEST(test_basic(), \"prio-queue works for basic input\");\n+\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n+\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n+\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n+\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n+\n+\treturn test_done();\n+}\n\nbase-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n-- \ngitgitgadget\n"},{"id":"486938","messageId":"xmqqh6jbvd9u.fsf@gitster.g","threadId":"60741","inReplyTo":"pull.1642.v3.git.1705502304219.gitgitgadget@gmail.com","subject":"Re: [PATCH v3] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-01-17T21:52:13Z","receivedAt":"2024-01-17T21:52:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Chandra Pratap via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> +static int test_prio_queue(int *input, int *result)\n> +{\n> +\tstruct prio_queue pq = { intcmp };\n> +\tint i = 0;\n> +\n> +\twhile (*input) {\n> +\t\tint *val = input++;\n> +\t\tvoid *peek, *get;\n> +\t\tswitch(*val) {\n\nAh, this one is a bit tricky.  I would have expected that we can\nmake val a pure integer, but because we need to give the address of\nthe element to be placed in the queue, not the value to be placed as\nan element in the queue, to prio_queue_put(), we would need the\npointer.\n\nI wonder if writing this as a more conventional for(;;) loop would\nmake it easier to handle, i.e.\n\n\tint val, i;\n\n\tfor (i = 0; (val = *input); input++) {\n\t\tswitch (val) {\n\t\tcase ...:\n\t\t...\n\t\tdefault:\n\t\t\tprio_queue_put(&pq, input);\n\t\t\tbreak;\n\t\t}\n\t}\n\n> +...\n> +\t\t\tdefault:\n> +\t\t\t\tprio_queue_put(&pq, val);\n> +\t\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\tclear_prio_queue(&pq);\n> +\treturn 0;\n> +}\n\n> +#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n> +  static void test_##name(void)\t\t\t\t\\\n> +{\t\t\t\t\t\t\t\t\\\n> +\tint input[] = {INPUT};\t\t\t\t\t\\\n\nI think I missed this myself in my review the last round, but we\nneed the sentinel value 0 at the end, i.e.,\n\n\tint input[] = {INPUT, 0};\n\nbecause the test_prio_queue() loops \"while (*input)\".  Otherwise\nthe loop would not terminate.\n\n> +\tint expected[] = {EXPECTED};\t\t\t\t\\\n> +\tint result[ARRAY_SIZE(expected)];\t\t\t\\\n\nThese arrays are correct.\n\n> +\ttest_prio_queue(input, result);\t\t\t\t\\\n> +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n\nSo is this check.\n\n> +}\n> +\n> +TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n> +TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n> +TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n> +TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n> +TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n> +\n> +int cmd_main(int argc, const char **argv)\n> +{\n> +\tTEST(test_basic(), \"prio-queue works for basic input\");\n> +\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n> +\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n> +\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n> +\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n> +\n> +\treturn test_done();\n> +}\n\nOther than that, looking good.  Thanks.\n"},{"id":"486939","messageId":"xmqqa5p3vczi.fsf@gitster.g","threadId":"60741","inReplyTo":"pull.1642.v3.git.1705502304219.gitgitgadget@gmail.com","subject":"Re: [PATCH v3] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-01-17T21:58:25Z","receivedAt":"2024-01-17T21:58:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I forgot to examine the contents of the tests themselves.\n\n> -cat >expect <<'EOF'\n> -1\n> -2\n> -3\n> -4\n> -5\n> -5\n> -6\n> -7\n> -8\n> -9\n> -10\n> -EOF\n> -test_expect_success 'basic ordering' '\n> -\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n> -\ttest_cmp expect actual\n> -'\n\nThis seems to have been lost from the converted test.  Your basic\ninput test feeds an already sorted array of 6 items and dump to see\nthey are the same already sorted array, which is a lot less\ninteresting than the above.\n\n> -cat >expect <<'EOF'\n> -2\n> -3\n> -4\n> -1\n> -5\n> -6\n> -EOF\n> -test_expect_success 'mixed put and get' '\n> -\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n> -\ttest_cmp expect actual\n> -'\n\nThis is a faithful conversion.\n\n> -cat >expect <<'EOF'\n> -1\n> -2\n> -NULL\n> -1\n> -2\n> -NULL\n> -EOF\n> -test_expect_success 'notice empty queue' '\n> -\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n> -\ttest_cmp expect actual\n> -'\n\nThis too.\n\n> -cat >expect <<'EOF'\n> -3\n> -2\n> -6\n> -4\n> -5\n> -1\n> -8\n> -EOF\n> -test_expect_success 'stack order' '\n> -\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n> -\ttest_cmp expect actual\n> -'\n\nThis test got truncated in your version, which is not horribly\nwrong, but if we claim \"move t0009 to unit testing\", people would\nexpect to see a conversion faithful to the original.  And with the\nuse of result[ARRAY_SIZE(expected)], there is no reason to truncate\nthe original test with this version, no?\n\nThanks.\n"},{"id":"486941","messageId":"xmqq34uvvc6a.fsf@gitster.g","threadId":"60741","inReplyTo":"xmqqa5p3vczi.fsf@gitster.g","subject":"Re: [PATCH v3] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-01-17T22:15:57Z","receivedAt":"2024-01-17T22:16:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I forgot to examine the contents of the tests themselves.\n> ...\n\nFYI: taking them all together, here is what I tentatively queued on\ntop of what was posted as v3 before I start doing today's\nintegration cycle.\n\nThanks.\n\n----- >8 -----\nSubject: [PATCH] SQUASH???\n\n---\n t/unit-tests/t-prio-queue.c | 57 ++++++++++++++++++-------------------\n 1 file changed, 28 insertions(+), 29 deletions(-)\n\ndiff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\nindex 0b826b463e..3014a67ac2 100644\n--- a/t/unit-tests/t-prio-queue.c\n+++ b/t/unit-tests/t-prio-queue.c\n@@ -22,44 +22,43 @@ static int show(int *v)\n static int test_prio_queue(int *input, int *result)\n {\n \tstruct prio_queue pq = { intcmp };\n-\tint i = 0;\n+\tint i, val;\n \n-\twhile (*input) {\n-\t\tint *val = input++;\n+\tfor (i = 0; (val = *input); input++) {\n \t\tvoid *peek, *get;\n-\t\tswitch(*val) {\n-\t\t\tcase GET:\n-\t\t\t\tpeek = prio_queue_peek(&pq);\n+\t\tswitch (val) {\n+\t\tcase GET:\n+\t\t\tpeek = prio_queue_peek(&pq);\n+\t\t\tget = prio_queue_get(&pq);\n+\t\t\tif (peek != get)\n+\t\t\t\tBUG(\"peek and get results don't match\");\n+\t\t\tresult[i++] = show(get);\n+\t\t\tbreak;\n+\t\tcase DUMP:\n+\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n \t\t\t\tget = prio_queue_get(&pq);\n \t\t\t\tif (peek != get)\n \t\t\t\t\tBUG(\"peek and get results don't match\");\n \t\t\t\tresult[i++] = show(get);\n-\t\t\t\tbreak;\n-\t\t\tcase DUMP:\n-\t\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n-\t\t\t\t\tget = prio_queue_get(&pq);\n-\t\t\t\t\tif (peek != get)\n-\t\t\t\t\t\tBUG(\"peek and get results don't match\");\n-\t\t\t\t\tresult[i++] = show(get);\n-\t\t\t\t}\n-\t\t\t\tbreak;\n-\t\t\tcase STACK:\n-\t\t\t\tpq.compare = NULL;\n-\t\t\t\tbreak;\n-\t\t\tcase REVERSE:\n-\t\t\t\tprio_queue_reverse(&pq);\n-\t\t\t\tbreak;\n-\t\t\tdefault:\n-\t\t\t\tprio_queue_put(&pq, val);\n-\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase STACK:\n+\t\t\tpq.compare = NULL;\n+\t\t\tbreak;\n+\t\tcase REVERSE:\n+\t\t\tprio_queue_reverse(&pq);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprio_queue_put(&pq, input);\n+\t\t\tbreak;\n \t\t}\n \t}\n \tclear_prio_queue(&pq);\n \treturn 0;\n }\n \n-#define BASIC_INPUT 1, 2, 3, 4, 5, 5, DUMP\n-#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n+#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP\n+#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10\n \n #define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n #define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n@@ -67,8 +66,8 @@ static int test_prio_queue(int *input, int *result)\n #define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n #define EMPTY_QUEUE_EXPECTED 1, 2, MISSING, 1, 2, MISSING\n \n-#define STACK_INPUT STACK, 1, 5, 4, 6, 2, 3, DUMP\n-#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n+#define STACK_INPUT STACK, 8, 1, 5, 4, 6, 2, 3, DUMP\n+#define STACK_EXPECTED 3, 2, 6, 4, 5, 1, 8\n \n #define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n #define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n@@ -76,7 +75,7 @@ static int test_prio_queue(int *input, int *result)\n #define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n   static void test_##name(void)\t\t\t\t\\\n {\t\t\t\t\t\t\t\t\\\n-\tint input[] = {INPUT};\t\t\t\t\t\\\n+\tint input[] = {INPUT, 0};\t\t\t\t\\\n \tint expected[] = {EXPECTED};\t\t\t\t\\\n \tint result[ARRAY_SIZE(expected)];\t\t\t\\\n \ttest_prio_queue(input, result);\t\t\t\t\\\n-- \n2.43.0-367-g186b115d30\n\n\n\n"},{"id":"487130","messageId":"20240120023141.GA610247@coredump.intra.peff.net","threadId":"60741","inReplyTo":"pull.1642.v3.git.1705502304219.gitgitgadget@gmail.com","subject":"Re: [PATCH v3] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2024-01-20T02:31:41Z","receivedAt":"2024-01-20T02:31:43Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 17, 2024 at 02:38:23PM +0000, Chandra Pratap via GitGitGadget wrote:\n\n> +#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n> +  static void test_##name(void)\t\t\t\t\\\n> +{\t\t\t\t\t\t\t\t\\\n> +\tint input[] = {INPUT};\t\t\t\t\t\\\n> +\tint expected[] = {EXPECTED};\t\t\t\t\\\n> +\tint result[ARRAY_SIZE(expected)];\t\t\t\\\n> +\ttest_prio_queue(input, result);\t\t\t\t\\\n> +\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n> +}\n\nIt is somewhat unfortunate that a failing test here gives a fairly\nuninformative message like:\n\n  # check \"!memcmp(expected, result, sizeof(expected))\" failed at t/unit-tests/t-prio-queue.c:89\n  not ok 5 - prio-queue works when LIFO stack is reversed\n\nwhereas the original t0009 you get a nice diff between expected and\nactual output. I guess this is a place where the test framework could\nhelp us more with a specialized check_memequal() or something that\nshowed the differing bytes on failure (of course being C, it has no type\ninfo so it wouldn't even know these are ints!).\n\nAnother solution would be to have the test function check the result as\nit is computed rather than storing it in an array. That would also solve\nanother potential problem: undefined behavior if the result is not the\nexpected size. If there is a bug that causes too much output we'd\noverflow our buffer. If too few, we'll end up comparing uninitialized\nmemory (which could even accidentally have the correct values,\nespecially if it's recycled from a previous test!). Neither of those\nshould happen in practice, but then the whole point of this exercise is\nto test the code.\n\nI admit I find myself a little skeptical in general of this whole \"let's\ndo tests in C\" framework.\n\n-Peff\n"},{"id":"487135","messageId":"611378dc-dfe7-446b-803d-ee933b50fdbf@gmail.com","threadId":"60741","inReplyTo":"pull.1642.v3.git.1705502304219.gitgitgadget@gmail.com","subject":"Re: [PATCH v3] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2024-01-20T14:23:09Z","receivedAt":"2024-01-20T14:23:11Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 17/01/2024 14:38, Chandra Pratap via GitGitGadget wrote:\n> From: Chandra Pratap <chandrapratap3519@gmail.com>\n> \n> t/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\n> tests Git's implementation of a priority queue. Migrate the\n> test over to the new unit testing framework to simplify debugging\n> and reduce test run-time. Refactor the required logic and add\n> a new test case in addition to porting over the original ones in\n> shell.\n\nThanks for working on this, it is good to see people exploring the unit \ntest framework. I agree with the points that Junio and Peff have already \nmade, I've got a couple of additional comments below.\n\n > [...]\n> +static int test_prio_queue(int *input, int *result)\n\nThis function does not need to return a value.\n\n> +{\n> +\tstruct prio_queue pq = { intcmp };\n> +\tint i = 0;\n> +\n> +\twhile (*input) {\n\nI agree with Junio that a for() loop would be better here, but I think \nthat rather than testing for '0' we should just pass the length of the \ninput array to this function.\n\n> +\t\tint *val = input++;\n> +\t\tvoid *peek, *get;\n> +\t\tswitch(*val) {\n> +\t\t\tcase GET:\n> +\t\t\t\tpeek = prio_queue_peek(&pq);\n> +\t\t\t\tget = prio_queue_get(&pq);\n> +\t\t\t\tif (peek != get)\n> +\t\t\t\t\tBUG(\"peek and get results don't match\");\n\nIf possible avoid calling BUG() in unit test code as it aborts the whole \ntest program, not just the current test. You can use check() and return \nearly instead\n\n\tif (!check(peek, !=, get))\n\t\treturn;\n\n> +\t\t\t\tresult[i++] = show(get);\n\nI agree with Peff that it would be safer just to use check_int() here. \nIf you switch to a for loop with an index you can also print the current \nindex with\n\n\ttest_msg(\"index %d\", i);\n\nWhich will help diagnose which item in the queue is failing.\n\nAlternatively we could grow result dynamically using ALLOC_GROW() and \nadd a function to compare two arrays of integers. Such a function should \ntake the two lengths, one for each array.\n\nBest Wishes\n\nPhillip\n\n"},{"id":"487184","messageId":"pull.1642.v4.git.1705865326185.gitgitgadget@gmail.com","threadId":"60741","inReplyTo":"pull.1642.v3.git.1705502304219.gitgitgadget@gmail.com","subject":"[PATCH v4] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Chandra Pratap via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-01-21T19:28:45Z","receivedAt":"2024-01-21T19:28:49Z","isPatch":true,"sender":{"key":"chandrapratap3519@gmail.com","avatar":null},"body":"From: Chandra Pratap <chandrapratap3519@gmail.com>\n\nt/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\ntests Git's implementation of a priority queue. Migrate the\ntest over to the new unit testing framework to simplify debugging\nand reduce test run-time. Refactor the required logic and add\na new test case in addition to porting over the original ones in\nshell.\n\nSigned-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n---\n    tests: move t0009-prio-queue.sh to the new unit testing framework\n    \n    Thanks to Jeff, Philip and Junio for your valuable feedbacks! I have\n    updated the patch so that the resulting tests are more verbose when they\n    fail and lesser prone to memory related errors.\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v4\nPull-Request: https://github.com/gitgitgadget/git/pull/1642\n\nRange-diff vs v3:\n\n 1:  6b10028177a ! 1:  e9a0dba6f47 tests: move t0009-prio-queue.sh to the new unit testing framework\n     @@ t/unit-tests/t-prio-queue.c (new)\n      +\treturn v ? *v : MISSING;\n      +}\n      +\n     -+static int test_prio_queue(int *input, int *result)\n     ++static void test_prio_queue(int *input, int *result, size_t input_size)\n      +{\n      +\tstruct prio_queue pq = { intcmp };\n     -+\tint i = 0;\n      +\n     -+\twhile (*input) {\n     -+\t\tint *val = input++;\n     ++\tfor (int i = 0, j = 0; i < input_size; i++) {\n      +\t\tvoid *peek, *get;\n     -+\t\tswitch(*val) {\n     -+\t\t\tcase GET:\n     -+\t\t\t\tpeek = prio_queue_peek(&pq);\n     ++\t\tswitch(input[i]) {\n     ++\t\tcase GET:\n     ++\t\t\tpeek = prio_queue_peek(&pq);\n     ++\t\t\tget = prio_queue_get(&pq);\n     ++\t\t\tif (!check(peek == get))\n     ++\t\t\t\treturn;\n     ++\t\t\tif(!check_int(result[j++], ==, show(get)))\n     ++\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n     ++\t\t\tbreak;\n     ++\t\tcase DUMP:\n     ++\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n      +\t\t\t\tget = prio_queue_get(&pq);\n     -+\t\t\t\tif (peek != get)\n     -+\t\t\t\t\tBUG(\"peek and get results don't match\");\n     -+\t\t\t\tresult[i++] = show(get);\n     -+\t\t\t\tbreak;\n     -+\t\t\tcase DUMP:\n     -+\t\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n     -+\t\t\t\t\tget = prio_queue_get(&pq);\n     -+\t\t\t\t\tif (peek != get)\n     -+\t\t\t\t\t\tBUG(\"peek and get results don't match\");\n     -+\t\t\t\t\tresult[i++] = show(get);\n     -+\t\t\t\t}\n     -+\t\t\t\tbreak;\n     -+\t\t\tcase STACK:\n     -+\t\t\t\tpq.compare = NULL;\n     -+\t\t\t\tbreak;\n     -+\t\t\tcase REVERSE:\n     -+\t\t\t\tprio_queue_reverse(&pq);\n     -+\t\t\t\tbreak;\n     -+\t\t\tdefault:\n     -+\t\t\t\tprio_queue_put(&pq, val);\n     -+\t\t\t\tbreak;\n     ++\t\t\t\tif (!check(peek == get))\n     ++\t\t\t\t\treturn;\n     ++\t\t\t\tif(!check_int(result[j++], ==, show(get)))\n     ++\t\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n     ++\t\t\t}\n     ++\t\t\tbreak;\n     ++\t\tcase STACK:\n     ++\t\t\tpq.compare = NULL;\n     ++\t\t\tbreak;\n     ++\t\tcase REVERSE:\n     ++\t\t\tprio_queue_reverse(&pq);\n     ++\t\t\tbreak;\n     ++\t\tdefault:\n     ++\t\t\tprio_queue_put(&pq, &input[i]);\n     ++\t\t\tbreak;\n      +\t\t}\n      +\t}\n      +\tclear_prio_queue(&pq);\n     -+\treturn 0;\n      +}\n      +\n     -+#define BASIC_INPUT 1, 2, 3, 4, 5, 5, DUMP\n     -+#define BASIC_EXPECTED 1, 2, 3, 4, 5, 5\n     ++#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP\n     ++#define BASIC_RESULT 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10\n      +\n      +#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n     -+#define MIXED_PUT_GET_EXPECTED 2, 3, 4, 1, 5, 6\n     ++#define MIXED_PUT_GET_RESULT 2, 3, 4, 1, 5, 6\n      +\n      +#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n     -+#define EMPTY_QUEUE_EXPECTED 1, 2, MISSING, 1, 2, MISSING\n     ++#define EMPTY_QUEUE_RESULT 1, 2, MISSING, 1, 2, MISSING\n      +\n     -+#define STACK_INPUT STACK, 1, 5, 4, 6, 2, 3, DUMP\n     -+#define STACK_EXPECTED 3, 2, 6, 4, 5, 1\n     ++#define STACK_INPUT STACK, 8, 1, 5, 4, 6, 2, 3, DUMP\n     ++#define STACK_RESULT 3, 2, 6, 4, 5, 1, 8\n      +\n      +#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n     -+#define REVERSE_STACK_EXPECTED 1, 2, 3, 4, 5, 6\n     ++#define REVERSE_STACK_RESULT 1, 2, 3, 4, 5, 6\n      +\n     -+#define TEST_INPUT(INPUT, EXPECTED, name)\t\t\t\\\n     ++#define TEST_INPUT(INPUT, RESULT, name)\t\t\t\\\n      +  static void test_##name(void)\t\t\t\t\\\n      +{\t\t\t\t\t\t\t\t\\\n      +\tint input[] = {INPUT};\t\t\t\t\t\\\n     -+\tint expected[] = {EXPECTED};\t\t\t\t\\\n     -+\tint result[ARRAY_SIZE(expected)];\t\t\t\\\n     -+\ttest_prio_queue(input, result);\t\t\t\t\\\n     -+\tcheck(!memcmp(expected, result, sizeof(expected)));\t\\\n     ++\tint result[] = {RESULT};\t\t\t\t\\\n     ++\ttest_prio_queue(input, result, ARRAY_SIZE(input));\t\\\n      +}\n      +\n     -+TEST_INPUT(BASIC_INPUT, BASIC_EXPECTED, basic)\n     -+TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_EXPECTED, mixed)\n     -+TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_EXPECTED, empty)\n     -+TEST_INPUT(STACK_INPUT, STACK_EXPECTED, stack)\n     -+TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_EXPECTED, reverse)\n     ++TEST_INPUT(BASIC_INPUT, BASIC_RESULT, basic)\n     ++TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_RESULT, mixed)\n     ++TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_RESULT, empty)\n     ++TEST_INPUT(STACK_INPUT, STACK_RESULT, stack)\n     ++TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_RESULT, reverse)\n      +\n      +int cmd_main(int argc, const char **argv)\n      +{\n\n\n Makefile                    |  2 +-\n t/helper/test-prio-queue.c  | 51 -------------------\n t/helper/test-tool.c        |  1 -\n t/helper/test-tool.h        |  1 -\n t/t0009-prio-queue.sh       | 66 -------------------------\n t/unit-tests/t-prio-queue.c | 98 +++++++++++++++++++++++++++++++++++++\n 6 files changed, 99 insertions(+), 120 deletions(-)\n delete mode 100644 t/helper/test-prio-queue.c\n delete mode 100755 t/t0009-prio-queue.sh\n create mode 100644 t/unit-tests/t-prio-queue.c\n\ndiff --git a/Makefile b/Makefile\nindex 312d95084c1..d5e48e656b3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n TEST_BUILTINS_OBJS += test-path-utils.o\n TEST_BUILTINS_OBJS += test-pcre2-config.o\n TEST_BUILTINS_OBJS += test-pkt-line.o\n-TEST_BUILTINS_OBJS += test-prio-queue.o\n TEST_BUILTINS_OBJS += test-proc-receive.o\n TEST_BUILTINS_OBJS += test-progress.o\n TEST_BUILTINS_OBJS += test-reach.o\n@@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n \n UNIT_TEST_PROGRAMS += t-basic\n UNIT_TEST_PROGRAMS += t-strbuf\n+UNIT_TEST_PROGRAMS += t-prio-queue\n UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\ndiff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\ndeleted file mode 100644\nindex f0bf255f5f0..00000000000\n--- a/t/helper/test-prio-queue.c\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-#include \"test-tool.h\"\n-#include \"prio-queue.h\"\n-\n-static int intcmp(const void *va, const void *vb, void *data UNUSED)\n-{\n-\tconst int *a = va, *b = vb;\n-\treturn *a - *b;\n-}\n-\n-static void show(int *v)\n-{\n-\tif (!v)\n-\t\tprintf(\"NULL\\n\");\n-\telse\n-\t\tprintf(\"%d\\n\", *v);\n-\tfree(v);\n-}\n-\n-int cmd__prio_queue(int argc UNUSED, const char **argv)\n-{\n-\tstruct prio_queue pq = { intcmp };\n-\n-\twhile (*++argv) {\n-\t\tif (!strcmp(*argv, \"get\")) {\n-\t\t\tvoid *peek = prio_queue_peek(&pq);\n-\t\t\tvoid *get = prio_queue_get(&pq);\n-\t\t\tif (peek != get)\n-\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\tshow(get);\n-\t\t} else if (!strcmp(*argv, \"dump\")) {\n-\t\t\tvoid *peek;\n-\t\t\tvoid *get;\n-\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n-\t\t\t\tget = prio_queue_get(&pq);\n-\t\t\t\tif (peek != get)\n-\t\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\t\tshow(get);\n-\t\t\t}\n-\t\t} else if (!strcmp(*argv, \"stack\")) {\n-\t\t\tpq.compare = NULL;\n-\t\t} else {\n-\t\t\tint *v = xmalloc(sizeof(*v));\n-\t\t\t*v = atoi(*argv);\n-\t\t\tprio_queue_put(&pq, v);\n-\t\t}\n-\t}\n-\n-\tclear_prio_queue(&pq);\n-\n-\treturn 0;\n-}\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex 876cd2dc313..5f591b9718f 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n \t{ \"path-utils\", cmd__path_utils },\n \t{ \"pcre2-config\", cmd__pcre2_config },\n \t{ \"pkt-line\", cmd__pkt_line },\n-\t{ \"prio-queue\", cmd__prio_queue },\n \t{ \"proc-receive\", cmd__proc_receive },\n \t{ \"progress\", cmd__progress },\n \t{ \"reach\", cmd__reach },\ndiff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\nindex 70dd4eba119..b921138d8ec 100644\n--- a/t/helper/test-tool.h\n+++ b/t/helper/test-tool.h\n@@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n int cmd__path_utils(int argc, const char **argv);\n int cmd__pcre2_config(int argc, const char **argv);\n int cmd__pkt_line(int argc, const char **argv);\n-int cmd__prio_queue(int argc, const char **argv);\n int cmd__proc_receive(int argc, const char **argv);\n int cmd__progress(int argc, const char **argv);\n int cmd__reach(int argc, const char **argv);\ndiff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\ndeleted file mode 100755\nindex eea99107a48..00000000000\n--- a/t/t0009-prio-queue.sh\n+++ /dev/null\n@@ -1,66 +0,0 @@\n-#!/bin/sh\n-\n-test_description='basic tests for priority queue implementation'\n-\n-TEST_PASSES_SANITIZE_LEAK=true\n-. ./test-lib.sh\n-\n-cat >expect <<'EOF'\n-1\n-2\n-3\n-4\n-5\n-5\n-6\n-7\n-8\n-9\n-10\n-EOF\n-test_expect_success 'basic ordering' '\n-\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-2\n-3\n-4\n-1\n-5\n-6\n-EOF\n-test_expect_success 'mixed put and get' '\n-\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-1\n-2\n-NULL\n-1\n-2\n-NULL\n-EOF\n-test_expect_success 'notice empty queue' '\n-\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-3\n-2\n-6\n-4\n-5\n-1\n-8\n-EOF\n-test_expect_success 'stack order' '\n-\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-test_done\ndiff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\nnew file mode 100644\nindex 00000000000..d78b002f9ea\n--- /dev/null\n+++ b/t/unit-tests/t-prio-queue.c\n@@ -0,0 +1,98 @@\n+#include \"test-lib.h\"\n+#include \"prio-queue.h\"\n+\n+static int intcmp(const void *va, const void *vb, void *data UNUSED)\n+{\n+\tconst int *a = va, *b = vb;\n+\treturn *a - *b;\n+}\n+\n+\n+#define MISSING  -1\n+#define DUMP\t -2\n+#define STACK\t -3\n+#define GET\t -4\n+#define REVERSE  -5\n+\n+static int show(int *v)\n+{\n+\treturn v ? *v : MISSING;\n+}\n+\n+static void test_prio_queue(int *input, int *result, size_t input_size)\n+{\n+\tstruct prio_queue pq = { intcmp };\n+\n+\tfor (int i = 0, j = 0; i < input_size; i++) {\n+\t\tvoid *peek, *get;\n+\t\tswitch(input[i]) {\n+\t\tcase GET:\n+\t\t\tpeek = prio_queue_peek(&pq);\n+\t\t\tget = prio_queue_get(&pq);\n+\t\t\tif (!check(peek == get))\n+\t\t\t\treturn;\n+\t\t\tif(!check_int(result[j++], ==, show(get)))\n+\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n+\t\t\tbreak;\n+\t\tcase DUMP:\n+\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n+\t\t\t\tget = prio_queue_get(&pq);\n+\t\t\t\tif (!check(peek == get))\n+\t\t\t\t\treturn;\n+\t\t\t\tif(!check_int(result[j++], ==, show(get)))\n+\t\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase STACK:\n+\t\t\tpq.compare = NULL;\n+\t\t\tbreak;\n+\t\tcase REVERSE:\n+\t\t\tprio_queue_reverse(&pq);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprio_queue_put(&pq, &input[i]);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tclear_prio_queue(&pq);\n+}\n+\n+#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP\n+#define BASIC_RESULT 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10\n+\n+#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n+#define MIXED_PUT_GET_RESULT 2, 3, 4, 1, 5, 6\n+\n+#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n+#define EMPTY_QUEUE_RESULT 1, 2, MISSING, 1, 2, MISSING\n+\n+#define STACK_INPUT STACK, 8, 1, 5, 4, 6, 2, 3, DUMP\n+#define STACK_RESULT 3, 2, 6, 4, 5, 1, 8\n+\n+#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n+#define REVERSE_STACK_RESULT 1, 2, 3, 4, 5, 6\n+\n+#define TEST_INPUT(INPUT, RESULT, name)\t\t\t\\\n+  static void test_##name(void)\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\\\n+\tint input[] = {INPUT};\t\t\t\t\t\\\n+\tint result[] = {RESULT};\t\t\t\t\\\n+\ttest_prio_queue(input, result, ARRAY_SIZE(input));\t\\\n+}\n+\n+TEST_INPUT(BASIC_INPUT, BASIC_RESULT, basic)\n+TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_RESULT, mixed)\n+TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_RESULT, empty)\n+TEST_INPUT(STACK_INPUT, STACK_RESULT, stack)\n+TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_RESULT, reverse)\n+\n+int cmd_main(int argc, const char **argv)\n+{\n+\tTEST(test_basic(), \"prio-queue works for basic input\");\n+\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n+\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n+\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n+\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n+\n+\treturn test_done();\n+}\n\nbase-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n-- \ngitgitgadget\n"},{"id":"487212","messageId":"xmqqwms1tcb0.fsf@gitster.g","threadId":"60741","inReplyTo":"pull.1642.v4.git.1705865326185.gitgitgadget@gmail.com","subject":"Re: [PATCH v4] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-01-22T19:09:39Z","receivedAt":"2024-01-22T19:09:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"> diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\n> new file mode 100644\n> index 00000000000..d78b002f9ea\n> --- /dev/null\n> +++ b/t/unit-tests/t-prio-queue.c\n> @@ -0,0 +1,98 @@\n> +#include \"test-lib.h\"\n> +#include \"prio-queue.h\"\n> +\n> +static int intcmp(const void *va, const void *vb, void *data UNUSED)\n> +{\n> +\tconst int *a = va, *b = vb;\n> +\treturn *a - *b;\n> +}\n> +\n> +\n> +#define MISSING  -1\n> +#define DUMP\t -2\n> +#define STACK\t -3\n> +#define GET\t -4\n> +#define REVERSE  -5\n> +\n> +static int show(int *v)\n> +{\n> +\treturn v ? *v : MISSING;\n> +}\n> +\n> +static void test_prio_queue(int *input, int *result, size_t input_size)\n> +{\n> +\tstruct prio_queue pq = { intcmp };\n> +\n> +\tfor (int i = 0, j = 0; i < input_size; i++) {\n> +\t\tvoid *peek, *get;\n> +\t\tswitch(input[i]) {\n\nStyle: in this codebase, a flow control keyword followed by a\nparenthesized stuff always get a single SP before the parenthesis.\n\n\t\tswitch (input[i]) {\n\nThere are similar style violations in this patch with if().\n\n> +\t\tcase GET:\n> +\t\t\tpeek = prio_queue_peek(&pq);\n> +\t\t\tget = prio_queue_get(&pq);\n> +\t\t\tif (!check(peek == get))\n> +\t\t\t\treturn;\n> +\t\t\tif(!check_int(result[j++], ==, show(get)))\n> +\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n> +\t\t\tbreak;\n> +\t\tcase DUMP:\n> +\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n> +\t\t\t\tget = prio_queue_get(&pq);\n> +\t\t\t\tif (!check(peek == get))\n> +\t\t\t\t\treturn;\n> +\t\t\t\tif(!check_int(result[j++], ==, show(get)))\n> +\t\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n> +\t\t\t}\n> +\t\t\tbreak;\n\nOK.  So this one checks as we go.  I am not sure how easy to grok a\nbreakage diagnosis with these giving the same message, without\ngiving any context of the failure (e.g. when we are fed\n\n\tINPUT  = 6 2 4 GET 5 3 GET GET 1 DUMP\n\tEXPECT = 2 3 4 1 5 6\n\nand for some reason if the first GET did not yield expected 2 but\ngave us, say, 6, we only see \"left: 2, right: 6\" followed by \"failed\nat result[] index 0\", and nothing else.  \n\nIf it said something like \"We pushed 6, 2, 4 and then did GET\" to\ngive the reader a bit more context, it would make it easier to see\nwhy we were complaining, i.e. expecting to see 2, instead getting 6.\nBut perhaps that is too much to ask to this code?\n\nI dunno.  Those who wanted to see an easier-to-diagnose output may\nhave better ideas.\n\nThanks.\n\n> +\t\tcase STACK:\n> +\t\t\tpq.compare = NULL;\n> +\t\t\tbreak;\n> +\t\tcase REVERSE:\n> +\t\t\tprio_queue_reverse(&pq);\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\tprio_queue_put(&pq, &input[i]);\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +\tclear_prio_queue(&pq);\n> +}\n> +\n> +#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP\n> +#define BASIC_RESULT 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10\n> +\n> +#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n> +#define MIXED_PUT_GET_RESULT 2, 3, 4, 1, 5, 6\n> +\n> +#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n> +#define EMPTY_QUEUE_RESULT 1, 2, MISSING, 1, 2, MISSING\n> +\n> +#define STACK_INPUT STACK, 8, 1, 5, 4, 6, 2, 3, DUMP\n> +#define STACK_RESULT 3, 2, 6, 4, 5, 1, 8\n> +\n> +#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n> +#define REVERSE_STACK_RESULT 1, 2, 3, 4, 5, 6\n> +\n> +#define TEST_INPUT(INPUT, RESULT, name)\t\t\t\\\n> +  static void test_##name(void)\t\t\t\t\\\n> +{\t\t\t\t\t\t\t\t\\\n> +\tint input[] = {INPUT};\t\t\t\t\t\\\n> +\tint result[] = {RESULT};\t\t\t\t\\\n> +\ttest_prio_queue(input, result, ARRAY_SIZE(input));\t\\\n> +}\n> +\n> +TEST_INPUT(BASIC_INPUT, BASIC_RESULT, basic)\n> +TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_RESULT, mixed)\n> +TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_RESULT, empty)\n> +TEST_INPUT(STACK_INPUT, STACK_RESULT, stack)\n> +TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_RESULT, reverse)\n> +\n> +int cmd_main(int argc, const char **argv)\n> +{\n> +\tTEST(test_basic(), \"prio-queue works for basic input\");\n> +\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n> +\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n> +\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n> +\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n> +\n> +\treturn test_done();\n> +}\n>\n> base-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n"},{"id":"487232","messageId":"20240122224223.GA814674@coredump.intra.peff.net","threadId":"60741","inReplyTo":"xmqqwms1tcb0.fsf@gitster.g","subject":"Re: [PATCH v4] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2024-01-22T22:42:23Z","receivedAt":"2024-01-22T22:42:27Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Jan 22, 2024 at 11:09:39AM -0800, Junio C Hamano wrote:\n\n> > +\t\tcase DUMP:\n> > +\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n> > +\t\t\t\tget = prio_queue_get(&pq);\n> > +\t\t\t\tif (!check(peek == get))\n> > +\t\t\t\t\treturn;\n> > +\t\t\t\tif(!check_int(result[j++], ==, show(get)))\n> > +\t\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n> > +\t\t\t}\n> > +\t\t\tbreak;\n> \n> OK.  So this one checks as we go.  I am not sure how easy to grok a\n> breakage diagnosis with these giving the same message, without\n> giving any context of the failure (e.g. when we are fed\n> \n> \tINPUT  = 6 2 4 GET 5 3 GET GET 1 DUMP\n> \tEXPECT = 2 3 4 1 5 6\n> \n> and for some reason if the first GET did not yield expected 2 but\n> gave us, say, 6, we only see \"left: 2, right: 6\" followed by \"failed\n> at result[] index 0\", and nothing else.  \n> \n> If it said something like \"We pushed 6, 2, 4 and then did GET\" to\n> give the reader a bit more context, it would make it easier to see\n> why we were complaining, i.e. expecting to see 2, instead getting 6.\n> But perhaps that is too much to ask to this code?\n> \n> I dunno.  Those who wanted to see an easier-to-diagnose output may\n> have better ideas.\n\nI don't have any bright ideas, but here are some dumb ones.\n\nThe big issue is that storing and manipulating data in C is tricky and\nrequires code to do correctly. And the whole idea of these tests is to\navoid having a ton of special code. That's why I actually think that the\nexisting strategy used in t0009 and elsewhere is pretty good. It pawns\noff output handling and such to existing programs.\n\nBut if we really want to keep it all in C, some options are:\n\n  1. We could log what is happening verbosely to stderr (or maybe stdout\n     with a TAP \"#\" prefix?). That lets it go nowhere most of the time,\n     but you can see it if you are investigating a failure (like the way\n     our current \"-v\" works).\n\n     Obviously by that same argument you can fire up a debugger to look\n     at the problem more closely when you have a failure. But failures\n     aren't always easy to reproduce. Sometimes they're racy, sometimes\n     CI fails but local runs don't (I've found CI's use of \"-v -x\"\n     especially helpful there), etc.\n\n  2. We can rely on a dynamic-growth array of ints to store the result,\n     and then a check_int_array() to compare/output them. That's custom\n     code for the test harness, but in theory it's reusable across many\n     tests.\n\n  3. In the same direction, we could simply output to a strbuf or\n     similar, and then compare the strbufs. We could even show a diff\n     when they are not the same. ;) That is reimplementing what scripts\n     like t0009 are doing already, but maybe people think there is other\n     value in shoving it all into a single C program (as I've said, I\n     remain a bit skeptical).\n\n-Peff\n"},{"id":"487380","messageId":"pull.1642.v5.git.1706212955415.gitgitgadget@gmail.com","threadId":"60741","inReplyTo":"pull.1642.v4.git.1705865326185.gitgitgadget@gmail.com","subject":"[PATCH v5] tests: move t0009-prio-queue.sh to the new unit testing framework","fromName":"Chandra Pratap via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-01-25T20:02:35Z","receivedAt":"2024-01-25T20:02:38Z","isPatch":true,"sender":{"key":"chandrapratap3519@gmail.com","avatar":null},"body":"From: Chandra Pratap <chandrapratap3519@gmail.com>\n\nt/t0009-prio-queue.sh along with t/helper/test-prio-queue.c unit\ntests Git's implementation of a priority queue. Migrate the\ntest over to the new unit testing framework to simplify debugging\nand reduce test run-time. Refactor the required logic and add\na new test case in addition to porting over the original ones in\nshell.\n\nSigned-off-by: Chandra Pratap <chandrapratap3519@gmail.com>\n---\n    tests: move t0009-prio-queue.sh to the new unit testing framework\n    \n    Thanks for the feedbacks! I have updated the patch so that the resulting\n    tests show something like:\n    \n    > check \"result[j++] == show(get)\" failed at\n    > unit-tests/t-prio-queue.c:60\n    \n    > left: 20 right: 2\n    \n    > input: push 1, push 2, get, get, get, push 1, push 2, get, get, get,\n    \n    > failed at input index 8\n    \n    in the case of a failing test.\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1642%2FChand-ra%2Fprio-queue-v5\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1642/Chand-ra/prio-queue-v5\nPull-Request: https://github.com/gitgitgadget/git/pull/1642\n\nRange-diff vs v4:\n\n 1:  e9a0dba6f47 ! 1:  88e70127ad3 tests: move t0009-prio-queue.sh to the new unit testing framework\n     @@ t/unit-tests/t-prio-queue.c (new)\n      +\treturn v ? *v : MISSING;\n      +}\n      +\n     ++static void print_input(int *input, size_t input_size)\n     ++{\n     ++\tchar buf[128];\n     ++\tint len = 0;\n     ++\tfor(size_t i = 0; i < input_size; i++) {\n     ++\t\tswitch (input[i]) {\n     ++\t\tcase GET:\n     ++\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"get, \");\n     ++\t\t\tbreak;\n     ++\t\tcase DUMP:\n     ++\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"dump\");\n     ++\t\t\tbreak;\n     ++\t\tcase STACK:\n     ++\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"stack, \");\n     ++\t\t\tbreak;\n     ++\t\tcase REVERSE:\n     ++\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"reverse, \");\n     ++\t\t\tbreak;\n     ++\t\tdefault:\n     ++\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"push %d, \", input[i]);\n     ++\t\t\tbreak;\n     ++\t\t}\n     ++\t}\n     ++\ttest_msg(\"input: %s\", buf);\n     ++}\n     ++\n      +static void test_prio_queue(int *input, int *result, size_t input_size)\n      +{\n      +\tstruct prio_queue pq = { intcmp };\n      +\n      +\tfor (int i = 0, j = 0; i < input_size; i++) {\n      +\t\tvoid *peek, *get;\n     -+\t\tswitch(input[i]) {\n     ++\t\tswitch (input[i]) {\n      +\t\tcase GET:\n      +\t\t\tpeek = prio_queue_peek(&pq);\n      +\t\t\tget = prio_queue_get(&pq);\n      +\t\t\tif (!check(peek == get))\n      +\t\t\t\treturn;\n     -+\t\t\tif(!check_int(result[j++], ==, show(get)))\n     -+\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n     ++\t\t\tif (!check_int(result[j++], ==, show(get))) {\n     ++\t\t\t\tprint_input(input, input_size);\n     ++\t\t\t\ttest_msg(\"failed at input index %d\", i);\n     ++\t\t\t}\n      +\t\t\tbreak;\n      +\t\tcase DUMP:\n      +\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n      +\t\t\t\tget = prio_queue_get(&pq);\n      +\t\t\t\tif (!check(peek == get))\n      +\t\t\t\t\treturn;\n     -+\t\t\t\tif(!check_int(result[j++], ==, show(get)))\n     -+\t\t\t\t\ttest_msg(\"failed at result[] index %d\", j-1);\n     ++\t\t\t\tif (!check_int(result[j++], ==, show(get))) {\n     ++\t\t\t\t\tprint_input(input, input_size);\n     ++\t\t\t\t\ttest_msg(\"failed at input index %d\", i);\n     ++\t\t\t\t}\n      +\t\t\t}\n      +\t\t\tbreak;\n      +\t\tcase STACK:\n     @@ t/unit-tests/t-prio-queue.c (new)\n      +\tclear_prio_queue(&pq);\n      +}\n      +\n     ++\n      +#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP\n      +#define BASIC_RESULT 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10\n      +\n\n\n Makefile                    |   2 +-\n t/helper/test-prio-queue.c  |  51 --------------\n t/helper/test-tool.c        |   1 -\n t/helper/test-tool.h        |   1 -\n t/t0009-prio-queue.sh       |  66 ------------------\n t/unit-tests/t-prio-queue.c | 129 ++++++++++++++++++++++++++++++++++++\n 6 files changed, 130 insertions(+), 120 deletions(-)\n delete mode 100644 t/helper/test-prio-queue.c\n delete mode 100755 t/t0009-prio-queue.sh\n create mode 100644 t/unit-tests/t-prio-queue.c\n\ndiff --git a/Makefile b/Makefile\nindex 312d95084c1..d5e48e656b3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -828,7 +828,6 @@ TEST_BUILTINS_OBJS += test-partial-clone.o\n TEST_BUILTINS_OBJS += test-path-utils.o\n TEST_BUILTINS_OBJS += test-pcre2-config.o\n TEST_BUILTINS_OBJS += test-pkt-line.o\n-TEST_BUILTINS_OBJS += test-prio-queue.o\n TEST_BUILTINS_OBJS += test-proc-receive.o\n TEST_BUILTINS_OBJS += test-progress.o\n TEST_BUILTINS_OBJS += test-reach.o\n@@ -1340,6 +1339,7 @@ THIRD_PARTY_SOURCES += sha1dc/%\n \n UNIT_TEST_PROGRAMS += t-basic\n UNIT_TEST_PROGRAMS += t-strbuf\n+UNIT_TEST_PROGRAMS += t-prio-queue\n UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\ndiff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c\ndeleted file mode 100644\nindex f0bf255f5f0..00000000000\n--- a/t/helper/test-prio-queue.c\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-#include \"test-tool.h\"\n-#include \"prio-queue.h\"\n-\n-static int intcmp(const void *va, const void *vb, void *data UNUSED)\n-{\n-\tconst int *a = va, *b = vb;\n-\treturn *a - *b;\n-}\n-\n-static void show(int *v)\n-{\n-\tif (!v)\n-\t\tprintf(\"NULL\\n\");\n-\telse\n-\t\tprintf(\"%d\\n\", *v);\n-\tfree(v);\n-}\n-\n-int cmd__prio_queue(int argc UNUSED, const char **argv)\n-{\n-\tstruct prio_queue pq = { intcmp };\n-\n-\twhile (*++argv) {\n-\t\tif (!strcmp(*argv, \"get\")) {\n-\t\t\tvoid *peek = prio_queue_peek(&pq);\n-\t\t\tvoid *get = prio_queue_get(&pq);\n-\t\t\tif (peek != get)\n-\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\tshow(get);\n-\t\t} else if (!strcmp(*argv, \"dump\")) {\n-\t\t\tvoid *peek;\n-\t\t\tvoid *get;\n-\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n-\t\t\t\tget = prio_queue_get(&pq);\n-\t\t\t\tif (peek != get)\n-\t\t\t\t\tBUG(\"peek and get results do not match\");\n-\t\t\t\tshow(get);\n-\t\t\t}\n-\t\t} else if (!strcmp(*argv, \"stack\")) {\n-\t\t\tpq.compare = NULL;\n-\t\t} else {\n-\t\t\tint *v = xmalloc(sizeof(*v));\n-\t\t\t*v = atoi(*argv);\n-\t\t\tprio_queue_put(&pq, v);\n-\t\t}\n-\t}\n-\n-\tclear_prio_queue(&pq);\n-\n-\treturn 0;\n-}\ndiff --git a/t/helper/test-tool.c b/t/helper/test-tool.c\nindex 876cd2dc313..5f591b9718f 100644\n--- a/t/helper/test-tool.c\n+++ b/t/helper/test-tool.c\n@@ -57,7 +57,6 @@ static struct test_cmd cmds[] = {\n \t{ \"path-utils\", cmd__path_utils },\n \t{ \"pcre2-config\", cmd__pcre2_config },\n \t{ \"pkt-line\", cmd__pkt_line },\n-\t{ \"prio-queue\", cmd__prio_queue },\n \t{ \"proc-receive\", cmd__proc_receive },\n \t{ \"progress\", cmd__progress },\n \t{ \"reach\", cmd__reach },\ndiff --git a/t/helper/test-tool.h b/t/helper/test-tool.h\nindex 70dd4eba119..b921138d8ec 100644\n--- a/t/helper/test-tool.h\n+++ b/t/helper/test-tool.h\n@@ -50,7 +50,6 @@ int cmd__partial_clone(int argc, const char **argv);\n int cmd__path_utils(int argc, const char **argv);\n int cmd__pcre2_config(int argc, const char **argv);\n int cmd__pkt_line(int argc, const char **argv);\n-int cmd__prio_queue(int argc, const char **argv);\n int cmd__proc_receive(int argc, const char **argv);\n int cmd__progress(int argc, const char **argv);\n int cmd__reach(int argc, const char **argv);\ndiff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh\ndeleted file mode 100755\nindex eea99107a48..00000000000\n--- a/t/t0009-prio-queue.sh\n+++ /dev/null\n@@ -1,66 +0,0 @@\n-#!/bin/sh\n-\n-test_description='basic tests for priority queue implementation'\n-\n-TEST_PASSES_SANITIZE_LEAK=true\n-. ./test-lib.sh\n-\n-cat >expect <<'EOF'\n-1\n-2\n-3\n-4\n-5\n-5\n-6\n-7\n-8\n-9\n-10\n-EOF\n-test_expect_success 'basic ordering' '\n-\ttest-tool prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-2\n-3\n-4\n-1\n-5\n-6\n-EOF\n-test_expect_success 'mixed put and get' '\n-\ttest-tool prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-1\n-2\n-NULL\n-1\n-2\n-NULL\n-EOF\n-test_expect_success 'notice empty queue' '\n-\ttest-tool prio-queue 1 2 get get get 1 2 get get get >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-cat >expect <<'EOF'\n-3\n-2\n-6\n-4\n-5\n-1\n-8\n-EOF\n-test_expect_success 'stack order' '\n-\ttest-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual &&\n-\ttest_cmp expect actual\n-'\n-\n-test_done\ndiff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c\nnew file mode 100644\nindex 00000000000..8456b23255c\n--- /dev/null\n+++ b/t/unit-tests/t-prio-queue.c\n@@ -0,0 +1,129 @@\n+#include \"test-lib.h\"\n+#include \"prio-queue.h\"\n+\n+static int intcmp(const void *va, const void *vb, void *data UNUSED)\n+{\n+\tconst int *a = va, *b = vb;\n+\treturn *a - *b;\n+}\n+\n+\n+#define MISSING  -1\n+#define DUMP\t -2\n+#define STACK\t -3\n+#define GET\t -4\n+#define REVERSE  -5\n+\n+static int show(int *v)\n+{\n+\treturn v ? *v : MISSING;\n+}\n+\n+static void print_input(int *input, size_t input_size)\n+{\n+\tchar buf[128];\n+\tint len = 0;\n+\tfor(size_t i = 0; i < input_size; i++) {\n+\t\tswitch (input[i]) {\n+\t\tcase GET:\n+\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"get, \");\n+\t\t\tbreak;\n+\t\tcase DUMP:\n+\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"dump\");\n+\t\t\tbreak;\n+\t\tcase STACK:\n+\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"stack, \");\n+\t\t\tbreak;\n+\t\tcase REVERSE:\n+\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"reverse, \");\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tlen += xsnprintf(buf+len, sizeof(buf), \"push %d, \", input[i]);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\ttest_msg(\"input: %s\", buf);\n+}\n+\n+static void test_prio_queue(int *input, int *result, size_t input_size)\n+{\n+\tstruct prio_queue pq = { intcmp };\n+\n+\tfor (int i = 0, j = 0; i < input_size; i++) {\n+\t\tvoid *peek, *get;\n+\t\tswitch (input[i]) {\n+\t\tcase GET:\n+\t\t\tpeek = prio_queue_peek(&pq);\n+\t\t\tget = prio_queue_get(&pq);\n+\t\t\tif (!check(peek == get))\n+\t\t\t\treturn;\n+\t\t\tif (!check_int(result[j++], ==, show(get))) {\n+\t\t\t\tprint_input(input, input_size);\n+\t\t\t\ttest_msg(\"failed at input index %d\", i);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase DUMP:\n+\t\t\twhile ((peek = prio_queue_peek(&pq))) {\n+\t\t\t\tget = prio_queue_get(&pq);\n+\t\t\t\tif (!check(peek == get))\n+\t\t\t\t\treturn;\n+\t\t\t\tif (!check_int(result[j++], ==, show(get))) {\n+\t\t\t\t\tprint_input(input, input_size);\n+\t\t\t\t\ttest_msg(\"failed at input index %d\", i);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase STACK:\n+\t\t\tpq.compare = NULL;\n+\t\t\tbreak;\n+\t\tcase REVERSE:\n+\t\t\tprio_queue_reverse(&pq);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tprio_queue_put(&pq, &input[i]);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tclear_prio_queue(&pq);\n+}\n+\n+\n+#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP\n+#define BASIC_RESULT 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10\n+\n+#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP\n+#define MIXED_PUT_GET_RESULT 2, 3, 4, 1, 5, 6\n+\n+#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET\n+#define EMPTY_QUEUE_RESULT 1, 2, MISSING, 1, 2, MISSING\n+\n+#define STACK_INPUT STACK, 8, 1, 5, 4, 6, 2, 3, DUMP\n+#define STACK_RESULT 3, 2, 6, 4, 5, 1, 8\n+\n+#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP\n+#define REVERSE_STACK_RESULT 1, 2, 3, 4, 5, 6\n+\n+#define TEST_INPUT(INPUT, RESULT, name)\t\t\t\\\n+  static void test_##name(void)\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\\\n+\tint input[] = {INPUT};\t\t\t\t\t\\\n+\tint result[] = {RESULT};\t\t\t\t\\\n+\ttest_prio_queue(input, result, ARRAY_SIZE(input));\t\\\n+}\n+\n+TEST_INPUT(BASIC_INPUT, BASIC_RESULT, basic)\n+TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_RESULT, mixed)\n+TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_RESULT, empty)\n+TEST_INPUT(STACK_INPUT, STACK_RESULT, stack)\n+TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_RESULT, reverse)\n+\n+int cmd_main(int argc, const char **argv)\n+{\n+\tTEST(test_basic(), \"prio-queue works for basic input\");\n+\tTEST(test_mixed(), \"prio-queue works for mixed put & get commands\");\n+\tTEST(test_empty(), \"prio-queue works when queue is empty\");\n+\tTEST(test_stack(), \"prio-queue works when used as a LIFO stack\");\n+\tTEST(test_reverse(), \"prio-queue works when LIFO stack is reversed\");\n+\n+\treturn test_done();\n+}\n\nbase-commit: 1a87c842ece327d03d08096395969aca5e0a6996\n-- \ngitgitgadget\n"}]}