Blame tests/core/vector.c

Packit ae9e2a
#include "clar_libgit2.h"
Packit ae9e2a
#include "vector.h"
Packit ae9e2a
Packit ae9e2a
/* initial size of 1 would cause writing past array bounds */
Packit ae9e2a
void test_core_vector__0(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	int i;
Packit ae9e2a
	git_vector_init(&x, 1, NULL);
Packit ae9e2a
	for (i = 0; i < 10; ++i) {
Packit ae9e2a
		git_vector_insert(&x, (void*) 0xabc);
Packit ae9e2a
	}
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
Packit ae9e2a
/* don't read past array bounds on remove() */
Packit ae9e2a
void test_core_vector__1(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	// make initial capacity exact for our insertions.
Packit ae9e2a
	git_vector_init(&x, 3, NULL);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0xabc);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0xdef);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x123);
Packit ae9e2a
Packit ae9e2a
	git_vector_remove(&x, 0); // used to read past array bounds.
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
Packit ae9e2a
static int test_cmp(const void *a, const void *b)
Packit ae9e2a
{
Packit ae9e2a
	return *(const int *)a - *(const int *)b;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
/* remove duplicates */
Packit ae9e2a
void test_core_vector__2(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	int *ptrs[2];
Packit ae9e2a
Packit ae9e2a
	ptrs[0] = git__malloc(sizeof(int));
Packit ae9e2a
	ptrs[1] = git__malloc(sizeof(int));
Packit ae9e2a
Packit ae9e2a
	*ptrs[0] = 2;
Packit ae9e2a
	*ptrs[1] = 1;
Packit ae9e2a
Packit ae9e2a
	cl_git_pass(git_vector_init(&x, 5, test_cmp));
Packit ae9e2a
	cl_git_pass(git_vector_insert(&x, ptrs[0]));
Packit ae9e2a
	cl_git_pass(git_vector_insert(&x, ptrs[1]));
Packit ae9e2a
	cl_git_pass(git_vector_insert(&x, ptrs[1]));
Packit ae9e2a
	cl_git_pass(git_vector_insert(&x, ptrs[0]));
Packit ae9e2a
	cl_git_pass(git_vector_insert(&x, ptrs[1]));
Packit ae9e2a
	cl_assert(x.length == 5);
Packit ae9e2a
Packit ae9e2a
	git_vector_uniq(&x, NULL);
Packit ae9e2a
	cl_assert(x.length == 2);
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
Packit ae9e2a
	git__free(ptrs[0]);
Packit ae9e2a
	git__free(ptrs[1]);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
Packit ae9e2a
static int compare_them(const void *a, const void *b)
Packit ae9e2a
{
Packit ae9e2a
	return (int)((long)a - (long)b);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
/* insert_sorted */
Packit ae9e2a
void test_core_vector__3(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	long i;
Packit ae9e2a
	git_vector_init(&x, 1, &compare_them);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 10; i += 2) {
Packit ae9e2a
		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	for (i = 9; i > 0; i -= 2) {
Packit ae9e2a
		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 10);
Packit ae9e2a
	for (i = 0; i < 10; ++i) {
Packit ae9e2a
		cl_assert(git_vector_get(&x, i) == (void*)(i + 1));
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
/* insert_sorted with duplicates */
Packit ae9e2a
void test_core_vector__4(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	long i;
Packit ae9e2a
	git_vector_init(&x, 1, &compare_them);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 10; i += 2) {
Packit ae9e2a
		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	for (i = 9; i > 0; i -= 2) {
Packit ae9e2a
		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 10; i += 2) {
Packit ae9e2a
		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	for (i = 9; i > 0; i -= 2) {
Packit ae9e2a
		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 20);
Packit ae9e2a
	for (i = 0; i < 20; ++i) {
Packit ae9e2a
		cl_assert(git_vector_get(&x, i) == (void*)(i / 2 + 1));
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
typedef struct {
Packit ae9e2a
	int content;
Packit ae9e2a
	int count;
Packit ae9e2a
} my_struct;
Packit ae9e2a
Packit ae9e2a
static int _struct_count = 0;
Packit ae9e2a
Packit ae9e2a
static int compare_structs(const void *a, const void *b)
Packit ae9e2a
{
Packit ae9e2a
	return ((const my_struct *)a)->content -
Packit ae9e2a
		((const my_struct *)b)->content;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int merge_structs(void **old_raw, void *new)
Packit ae9e2a
{
Packit ae9e2a
	my_struct *old = *(my_struct **)old_raw;
Packit ae9e2a
	cl_assert(((my_struct *)old)->content == ((my_struct *)new)->content);
Packit ae9e2a
	((my_struct *)old)->count += 1;
Packit ae9e2a
	git__free(new);
Packit ae9e2a
	_struct_count--;
Packit ae9e2a
	return GIT_EEXISTS;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static my_struct *alloc_struct(int value)
Packit ae9e2a
{
Packit ae9e2a
	my_struct *st = git__malloc(sizeof(my_struct));
Packit ae9e2a
	st->content = value;
Packit ae9e2a
	st->count = 0;
Packit ae9e2a
	_struct_count++;
Packit ae9e2a
	return st;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
/* insert_sorted with duplicates and special handling */
Packit ae9e2a
void test_core_vector__5(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	int i;
Packit ae9e2a
Packit ae9e2a
	git_vector_init(&x, 1, &compare_structs);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 10; i += 2)
Packit ae9e2a
		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
Packit ae9e2a
Packit ae9e2a
	for (i = 9; i > 0; i -= 2)
Packit ae9e2a
		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 10);
Packit ae9e2a
	cl_assert(_struct_count == 10);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 10; i += 2)
Packit ae9e2a
		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
Packit ae9e2a
Packit ae9e2a
	for (i = 9; i > 0; i -= 2)
Packit ae9e2a
		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 10);
Packit ae9e2a
	cl_assert(_struct_count == 10);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 10; ++i) {
Packit ae9e2a
		cl_assert(((my_struct *)git_vector_get(&x, i))->content == i);
Packit ae9e2a
		git__free(git_vector_get(&x, i));
Packit ae9e2a
		_struct_count--;
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int remove_ones(const git_vector *v, size_t idx, void *p)
Packit ae9e2a
{
Packit ae9e2a
	GIT_UNUSED(p);
Packit ae9e2a
	return (git_vector_get(v, idx) == (void *)0x001);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
/* Test removal based on callback */
Packit ae9e2a
void test_core_vector__remove_matching(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x;
Packit ae9e2a
	size_t i;
Packit ae9e2a
	void *compare;
Packit ae9e2a
Packit ae9e2a
	git_vector_init(&x, 1, NULL);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 1);
Packit ae9e2a
	git_vector_remove_matching(&x, remove_ones, NULL);
Packit ae9e2a
	cl_assert(x.length == 0);
Packit ae9e2a
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 3);
Packit ae9e2a
	git_vector_remove_matching(&x, remove_ones, NULL);
Packit ae9e2a
	cl_assert(x.length == 0);
Packit ae9e2a
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 4);
Packit ae9e2a
	git_vector_remove_matching(&x, remove_ones, NULL);
Packit ae9e2a
	cl_assert(x.length == 2);
Packit ae9e2a
Packit ae9e2a
	git_vector_foreach(&x, i, compare) {
Packit ae9e2a
		cl_assert(compare != (void *)0x001);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	git_vector_clear(&x);
Packit ae9e2a
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 4);
Packit ae9e2a
	git_vector_remove_matching(&x, remove_ones, NULL);
Packit ae9e2a
	cl_assert(x.length == 2);
Packit ae9e2a
Packit ae9e2a
	git_vector_foreach(&x, i, compare) {
Packit ae9e2a
		cl_assert(compare != (void *)0x001);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	git_vector_clear(&x);
Packit ae9e2a
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x001);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 4);
Packit ae9e2a
	git_vector_remove_matching(&x, remove_ones, NULL);
Packit ae9e2a
	cl_assert(x.length == 2);
Packit ae9e2a
Packit ae9e2a
	git_vector_foreach(&x, i, compare) {
Packit ae9e2a
		cl_assert(compare != (void *)0x001);
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	git_vector_clear(&x);
Packit ae9e2a
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x003);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x002);
Packit ae9e2a
	git_vector_insert(&x, (void*) 0x003);
Packit ae9e2a
Packit ae9e2a
	cl_assert(x.length == 4);
Packit ae9e2a
	git_vector_remove_matching(&x, remove_ones, NULL);
Packit ae9e2a
	cl_assert(x.length == 4);
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static void assert_vector(git_vector *x, void *expected[], size_t len)
Packit ae9e2a
{
Packit ae9e2a
	size_t i;
Packit ae9e2a
Packit ae9e2a
	cl_assert_equal_i(len, x->length);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < len; i++)
Packit ae9e2a
		cl_assert(expected[i] == x->contents[i]);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void test_core_vector__grow_and_shrink(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector x = GIT_VECTOR_INIT;
Packit ae9e2a
	void *expected1[] = {
Packit ae9e2a
		(void *)0x02, (void *)0x03, (void *)0x04, (void *)0x05,
Packit ae9e2a
		(void *)0x06, (void *)0x07, (void *)0x08, (void *)0x09,
Packit ae9e2a
		(void *)0x0a
Packit ae9e2a
	};
Packit ae9e2a
	void *expected2[] = {
Packit ae9e2a
		(void *)0x02, (void *)0x04, (void *)0x05, (void *)0x06,
Packit ae9e2a
		(void *)0x07, (void *)0x08, (void *)0x09, (void *)0x0a
Packit ae9e2a
	};
Packit ae9e2a
	void *expected3[] = {
Packit ae9e2a
		(void *)0x02, (void *)0x04, (void *)0x05, (void *)0x06,
Packit ae9e2a
		(void *)0x0a
Packit ae9e2a
	};
Packit ae9e2a
	void *expected4[] = {
Packit ae9e2a
		(void *)0x02, (void *)0x04, (void *)0x05
Packit ae9e2a
	};
Packit ae9e2a
	void *expected5[] = {
Packit ae9e2a
		(void *)0x00, (void *)0x00, (void *)0x02, (void *)0x04,
Packit ae9e2a
		(void *)0x05
Packit ae9e2a
	};
Packit ae9e2a
	void *expected6[] = {
Packit ae9e2a
		(void *)0x00, (void *)0x00, (void *)0x02, (void *)0x04,
Packit ae9e2a
		(void *)0x05, (void *)0x00
Packit ae9e2a
	};
Packit ae9e2a
	void *expected7[] = {
Packit ae9e2a
		(void *)0x00, (void *)0x00, (void *)0x02, (void *)0x04,
Packit ae9e2a
		(void *)0x00, (void *)0x00, (void *)0x00, (void *)0x05,
Packit ae9e2a
		(void *)0x00
Packit ae9e2a
	};
Packit ae9e2a
	void *expected8[] = {
Packit ae9e2a
		(void *)0x04, (void *)0x00, (void *)0x00, (void *)0x00,
Packit ae9e2a
		(void *)0x05, (void *)0x00
Packit ae9e2a
	};
Packit ae9e2a
	void *expected9[] = {
Packit ae9e2a
		(void *)0x04, (void *)0x00, (void *)0x05, (void *)0x00
Packit ae9e2a
	};
Packit ae9e2a
	void *expectedA[] = { (void *)0x04, (void *)0x00 };
Packit ae9e2a
	void *expectedB[] = { (void *)0x04 };
Packit ae9e2a
Packit ae9e2a
	git_vector_insert(&x, (void *)0x01);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x02);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x03);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x04);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x05);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x06);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x07);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x08);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x09);
Packit ae9e2a
	git_vector_insert(&x, (void *)0x0a);
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 0, 1);
Packit ae9e2a
	assert_vector(&x, expected1, ARRAY_SIZE(expected1));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 1, 1);
Packit ae9e2a
	assert_vector(&x, expected2, ARRAY_SIZE(expected2));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 4, 3);
Packit ae9e2a
	assert_vector(&x, expected3, ARRAY_SIZE(expected3));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 3, 2);
Packit ae9e2a
	assert_vector(&x, expected4, ARRAY_SIZE(expected4));
Packit ae9e2a
Packit ae9e2a
	git_vector_insert_null(&x, 0, 2);
Packit ae9e2a
	assert_vector(&x, expected5, ARRAY_SIZE(expected5));
Packit ae9e2a
Packit ae9e2a
	git_vector_insert_null(&x, 5, 1);
Packit ae9e2a
	assert_vector(&x, expected6, ARRAY_SIZE(expected6));
Packit ae9e2a
Packit ae9e2a
	git_vector_insert_null(&x, 4, 3);
Packit ae9e2a
	assert_vector(&x, expected7, ARRAY_SIZE(expected7));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 0, 3);
Packit ae9e2a
	assert_vector(&x, expected8, ARRAY_SIZE(expected8));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 1, 2);
Packit ae9e2a
	assert_vector(&x, expected9, ARRAY_SIZE(expected9));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 2, 2);
Packit ae9e2a
	assert_vector(&x, expectedA, ARRAY_SIZE(expectedA));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 1, 1);
Packit ae9e2a
	assert_vector(&x, expectedB, ARRAY_SIZE(expectedB));
Packit ae9e2a
Packit ae9e2a
	git_vector_remove_range(&x, 0, 1);
Packit ae9e2a
	assert_vector(&x, NULL, 0);
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&x);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
void test_core_vector__reverse(void)
Packit ae9e2a
{
Packit ae9e2a
	git_vector v = GIT_VECTOR_INIT;
Packit ae9e2a
	size_t i;
Packit ae9e2a
Packit ae9e2a
	void *in1[] = {(void *) 0x0, (void *) 0x1, (void *) 0x2, (void *) 0x3};
Packit ae9e2a
	void *out1[] = {(void *) 0x3, (void *) 0x2, (void *) 0x1, (void *) 0x0};
Packit ae9e2a
Packit ae9e2a
	void *in2[] = {(void *) 0x0, (void *) 0x1, (void *) 0x2, (void *) 0x3, (void *) 0x4};
Packit ae9e2a
	void *out2[] = {(void *) 0x4, (void *) 0x3, (void *) 0x2, (void *) 0x1, (void *) 0x0};
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 4; i++)
Packit ae9e2a
		cl_git_pass(git_vector_insert(&v, in1[i]));
Packit ae9e2a
Packit ae9e2a
	git_vector_reverse(&v);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 4; i++)
Packit ae9e2a
		cl_assert_equal_p(out1[i], git_vector_get(&v, i));
Packit ae9e2a
Packit ae9e2a
	git_vector_clear(&v);
Packit ae9e2a
	for (i = 0; i < 5; i++)
Packit ae9e2a
		cl_git_pass(git_vector_insert(&v, in2[i]));
Packit ae9e2a
Packit ae9e2a
	git_vector_reverse(&v);
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < 5; i++)
Packit ae9e2a
		cl_assert_equal_p(out2[i], git_vector_get(&v, i));
Packit ae9e2a
Packit ae9e2a
	git_vector_free(&v);
Packit ae9e2a
}