Files
git/t/unit-tests/u-prio-queue.c
René Scharfe 3d5091d232 prio-queue: add prio_queue_replace()
Add a function to replace the top element of the queue that basically
does the same as prio_queue_get() followed by prio_queue_put(), but
without the work by prio_queue_get() to rebalance the heap.  It can be
used to optimize loops that get one element and then immediately add
another one.  That's common e.g., with commit history traversal, where
we get out a commit and then put in its parents.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-07-22 07:28:35 -07:00

118 lines
2.6 KiB
C

#include "unit-test.h"
#include "prio-queue.h"
static int intcmp(const void *va, const void *vb, void *data UNUSED)
{
const int *a = va, *b = vb;
return *a - *b;
}
#define MISSING -1
#define DUMP -2
#define STACK -3
#define GET -4
#define REVERSE -5
#define REPLACE -6
static int show(int *v)
{
return v ? *v : MISSING;
}
static void test_prio_queue(int *input, size_t input_size,
int *result, size_t result_size)
{
struct prio_queue pq = { intcmp };
size_t j = 0;
for (size_t i = 0; i < input_size; i++) {
void *peek, *get;
switch(input[i]) {
case GET:
peek = prio_queue_peek(&pq);
get = prio_queue_get(&pq);
cl_assert(peek == get);
cl_assert(j < result_size);
cl_assert_equal_i(result[j], show(get));
j++;
break;
case DUMP:
while ((peek = prio_queue_peek(&pq))) {
get = prio_queue_get(&pq);
cl_assert(peek == get);
cl_assert(j < result_size);
cl_assert_equal_i(result[j], show(get));
j++;
}
break;
case STACK:
pq.compare = NULL;
break;
case REVERSE:
prio_queue_reverse(&pq);
break;
case REPLACE:
peek = prio_queue_peek(&pq);
cl_assert(i + 1 < input_size);
cl_assert(input[i + 1] >= 0);
cl_assert(j < result_size);
cl_assert_equal_i(result[j], show(peek));
j++;
prio_queue_replace(&pq, &input[++i]);
break;
default:
prio_queue_put(&pq, &input[i]);
break;
}
}
cl_assert_equal_i(j, result_size);
clear_prio_queue(&pq);
}
#define TEST_INPUT(input, result) \
test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result))
void test_prio_queue__basic(void)
{
TEST_INPUT(((int []){ 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP }),
((int []){ 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 }));
}
void test_prio_queue__mixed(void)
{
TEST_INPUT(((int []){ 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP }),
((int []){ 2, 3, 4, 1, 5, 6 }));
}
void test_prio_queue__empty(void)
{
TEST_INPUT(((int []){ 1, 2, GET, GET, GET, 1, 2, GET, GET, GET }),
((int []){ 1, 2, MISSING, 1, 2, MISSING }));
}
void test_prio_queue__replace(void)
{
TEST_INPUT(((int []){ REPLACE, 6, 2, 4, REPLACE, 5, 7, GET,
REPLACE, 1, DUMP }),
((int []){ MISSING, 2, 4, 5, 1, 6, 7 }));
}
void test_prio_queue__stack(void)
{
TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }),
((int []){ 3, 2, 6, 4, 5, 1, 8 }));
}
void test_prio_queue__reverse_stack(void)
{
TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }),
((int []){ 1, 2, 3, 4, 5, 6 }));
}
void test_prio_queue__replace_stack(void)
{
TEST_INPUT(((int []){ STACK, 8, 1, 5, REPLACE, 4, 6, 2, 3, DUMP }),
((int []){ 5, 3, 2, 6, 4, 1, 8 }));
}