text: #include "clar_libgit2.h"
  #include "vector.h"
  
  /* initial size of 1 would cause writing past array bounds */
  void test_core_vector__0(void)
  {
  	git_vector x;
  	int i;
  	git_vector_init(&x, 1, NULL);
  	for (i = 0; i < 10; ++i) {
  		git_vector_insert(&x, (void*) 0xabc);
  	}
  	git_vector_free(&x);
  }
  
  
  /* don't read past array bounds on remove() */
  void test_core_vector__1(void)
  {
  	git_vector x;
  	// make initial capacity exact for our insertions.
  	git_vector_init(&x, 3, NULL);
  	git_vector_insert(&x, (void*) 0xabc);
  	git_vector_insert(&x, (void*) 0xdef);
  	git_vector_insert(&x, (void*) 0x123);
  
  	git_vector_remove(&x, 0); // used to read past array bounds.
  	git_vector_free(&x);
  }
  
  
  static int test_cmp(const void *a, const void *b)
  {
  	return *(const int *)a - *(const int *)b;
  }
  
  /* remove duplicates */
  void test_core_vector__2(void)
  {
  	git_vector x;
  	int *ptrs[2];
  
  	ptrs[0] = git__malloc(sizeof(int));
  	ptrs[1] = git__malloc(sizeof(int));
  
  	*ptrs[0] = 2;
  	*ptrs[1] = 1;
  
  	cl_git_pass(git_vector_init(&x, 5, test_cmp));
  	cl_git_pass(git_vector_insert(&x, ptrs[0]));
  	cl_git_pass(git_vector_insert(&x, ptrs[1]));
  	cl_git_pass(git_vector_insert(&x, ptrs[1]));
  	cl_git_pass(git_vector_insert(&x, ptrs[0]));
  	cl_git_pass(git_vector_insert(&x, ptrs[1]));
  	cl_assert(x.length == 5);
  
  	git_vector_uniq(&x, NULL);
  	cl_assert(x.length == 2);
  
  	git_vector_free(&x);
  
  	git__free(ptrs[0]);
  	git__free(ptrs[1]);
  }
  
  
  static int compare_them(const void *a, const void *b)
  {
  	return (int)((long)a - (long)b);
  }
  
  /* insert_sorted */
  void test_core_vector__3(void)
  {
  	git_vector x;
  	long i;
  	git_vector_init(&x, 1, &compare_them);
  
  	for (i = 0; i < 10; i += 2) {
  		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
  	}
  
  	for (i = 9; i > 0; i -= 2) {
  		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
  	}
  
  	cl_assert(x.length == 10);
  	for (i = 0; i < 10; ++i) {
  		cl_assert(git_vector_get(&x, i) == (void*)(i + 1));
  	}
  
  	git_vector_free(&x);
  }
  
  /* insert_sorted with duplicates */
  void test_core_vector__4(void)
  {
  	git_vector x;
  	long i;
  	git_vector_init(&x, 1, &compare_them);
  
  	for (i = 0; i < 10; i += 2) {
  		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
  	}
  
  	for (i = 9; i > 0; i -= 2) {
  		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
  	}
  
  	for (i = 0; i < 10; i += 2) {
  		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
  	}
  
  	for (i = 9; i > 0; i -= 2) {
  		git_vector_insert_sorted(&x, (void*)(i + 1), NULL);
  	}
  
  	cl_assert(x.length == 20);
  	for (i = 0; i < 20; ++i) {
  		cl_assert(git_vector_get(&x, i) == (void*)(i / 2 + 1));
  	}
  
  	git_vector_free(&x);
  }
  
  typedef struct {
  	int content;
  	int count;
  } my_struct;
  
  static int _struct_count = 0;
  
  static int compare_structs(const void *a, const void *b)
  {
  	return ((const my_struct *)a)->content -
  		((const my_struct *)b)->content;
  }
  
  static int merge_structs(void **old_raw, void *new)
  {
  	my_struct *old = *(my_struct **)old_raw;
  	cl_assert(((my_struct *)old)->content == ((my_struct *)new)->content);
  	((my_struct *)old)->count += 1;
  	git__free(new);
  	_struct_count--;
  	return GIT_EEXISTS;
  }
  
  static my_struct *alloc_struct(int value)
  {
  	my_struct *st = git__malloc(sizeof(my_struct));
  	st->content = value;
  	st->count = 0;
  	_struct_count++;
  	return st;
  }
  
  /* insert_sorted with duplicates and special handling */
  void test_core_vector__5(void)
  {
  	git_vector x;
  	int i;
  
  	git_vector_init(&x, 1, &compare_structs);
  
  	for (i = 0; i < 10; i += 2)
  		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
  
  	for (i = 9; i > 0; i -= 2)
  		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
  
  	cl_assert(x.length == 10);
  	cl_assert(_struct_count == 10);
  
  	for (i = 0; i < 10; i += 2)
  		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
  
  	for (i = 9; i > 0; i -= 2)
  		git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs);
  
  	cl_assert(x.length == 10);
  	cl_assert(_struct_count == 10);
  
  	for (i = 0; i < 10; ++i) {
  		cl_assert(((my_struct *)git_vector_get(&x, i))->content == i);
  		git__free(git_vector_get(&x, i));
  		_struct_count--;
  	}
  
  	git_vector_free(&x);
  }
  
  static int remove_ones(const git_vector *v, size_t idx, void *p)
  {
  	GIT_UNUSED(p);
  	return (git_vector_get(v, idx) == (void *)0x001);
  }
  
  /* Test removal based on callback */
  void test_core_vector__remove_matching(void)
  {
  	git_vector x;
  	size_t i;
  	void *compare;
  
  	git_vector_init(&x, 1, NULL);
  	git_vector_insert(&x, (void*) 0x001);
  
  	cl_assert(x.length == 1);
  	git_vector_remove_matching(&x, remove_ones, NULL);
  	cl_assert(x.length == 0);
  
  	git_vector_insert(&x, (void*) 0x001);
  	git_vector_insert(&x, (void*) 0x001);
  	git_vector_insert(&x, (void*) 0x001);
  
  	cl_assert(x.length == 3);
  	git_vector_remove_matching(&x, remove_ones, NULL);
  	cl_assert(x.length == 0);
  
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x001);
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x001);
  
  	cl_assert(x.length == 4);
  	git_vector_remove_matching(&x, remove_ones, NULL);
  	cl_assert(x.length == 2);
  
  	git_vector_foreach(&x, i, compare) {
  		cl_assert(compare != (void *)0x001);
  	}
  
  	git_vector_clear(&x);
  
  	git_vector_insert(&x, (void*) 0x001);
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x001);
  
  	cl_assert(x.length == 4);
  	git_vector_remove_matching(&x, remove_ones, NULL);
  	cl_assert(x.length == 2);
  
  	git_vector_foreach(&x, i, compare) {
  		cl_assert(compare != (void *)0x001);
  	}
  
  	git_vector_clear(&x);
  
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x001);
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x001);
  
  	cl_assert(x.length == 4);
  	git_vector_remove_matching(&x, remove_ones, NULL);
  	cl_assert(x.length == 2);
  
  	git_vector_foreach(&x, i, compare) {
  		cl_assert(compare != (void *)0x001);
  	}
  
  	git_vector_clear(&x);
  
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x003);
  	git_vector_insert(&x, (void*) 0x002);
  	git_vector_insert(&x, (void*) 0x003);
  
  	cl_assert(x.length == 4);
  	git_vector_remove_matching(&x, remove_ones, NULL);
  	cl_assert(x.length == 4);
  
  	git_vector_free(&x);
  }
  