467 lines
9.3 KiB
C
467 lines
9.3 KiB
C
/*
|
|
* Copyright (C) 2014 Tobias Brunner
|
|
* Hochschule fuer Technik Rapperswil
|
|
*
|
|
* Copyright (C) 2013 Martin Willi
|
|
* Copyright (C) 2013 revosec AG
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*/
|
|
|
|
#include "test_suite.h"
|
|
|
|
#include <collections/array.h>
|
|
|
|
START_TEST(test_append_ptr)
|
|
{
|
|
array_t *array;
|
|
uintptr_t x;
|
|
int i;
|
|
|
|
array = array_create(0, 0);
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
ck_assert_int_eq(array_count(array), 0);
|
|
|
|
array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)3);
|
|
array_insert(array, ARRAY_TAIL, (void*)(uintptr_t)4);
|
|
ck_assert_int_eq(array_count(array), 2);
|
|
|
|
/* 3, 4 */
|
|
|
|
ck_assert(array_get(array, ARRAY_HEAD, &x));
|
|
ck_assert_int_eq(x, 3);
|
|
ck_assert(array_get(array, 1, &x));
|
|
ck_assert_int_eq(x, 4);
|
|
ck_assert(array_get(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 4);
|
|
ck_assert(!array_get(array, 3, &x));
|
|
|
|
array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)1);
|
|
array_insert(array, 1, (void*)(uintptr_t)2);
|
|
ck_assert_int_eq(array_count(array), 4);
|
|
|
|
/* 1, 2, 3, 4 */
|
|
|
|
array_insert(array, ARRAY_TAIL, (void*)(uintptr_t)5);
|
|
array_insert(array, ARRAY_HEAD, (void*)(uintptr_t)0);
|
|
ck_assert_int_eq(array_count(array), 6);
|
|
|
|
/* 0, 1, 2, 3, 4, 5 */
|
|
|
|
ck_assert(array_remove(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 5);
|
|
ck_assert(array_remove(array, 4, &x));
|
|
ck_assert_int_eq(x, 4);
|
|
|
|
if (i < 3)
|
|
{
|
|
array_compress(array);
|
|
}
|
|
|
|
/* 0, 1, 2, 3 */
|
|
|
|
ck_assert(array_remove(array, 1, &x));
|
|
ck_assert_int_eq(x, 1);
|
|
ck_assert(array_remove(array, ARRAY_HEAD, &x));
|
|
ck_assert_int_eq(x, 0);
|
|
|
|
if (i < 2)
|
|
{
|
|
array_compress(array);
|
|
}
|
|
|
|
/* 2, 3 */
|
|
|
|
ck_assert(array_remove(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 3);
|
|
ck_assert(array_remove(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 2);
|
|
|
|
if (i < 1)
|
|
{
|
|
array_compress(array);
|
|
}
|
|
|
|
ck_assert_int_eq(array_count(array), 0);
|
|
|
|
ck_assert(array_remove(array, ARRAY_HEAD, NULL) == FALSE);
|
|
ck_assert(array_remove(array, ARRAY_TAIL, NULL) == FALSE);
|
|
}
|
|
|
|
array_destroy(array);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_append_obj)
|
|
{
|
|
array_t *array;
|
|
int i, x, y[6] = {0, 1, 2, 3, 4, 5};
|
|
|
|
array = array_create(sizeof(y[0]), 0);
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
ck_assert_int_eq(array_count(array), 0);
|
|
|
|
array_insert(array, ARRAY_HEAD, &y[3]);
|
|
array_insert(array, ARRAY_TAIL, &y[4]);
|
|
ck_assert_int_eq(array_count(array), 2);;
|
|
|
|
/* 3, 4 */
|
|
|
|
ck_assert(array_get(array, ARRAY_HEAD, &x));
|
|
ck_assert_int_eq(x, 3);
|
|
ck_assert(array_get(array, 1, &x));
|
|
ck_assert_int_eq(x, 4);
|
|
ck_assert(array_get(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 4);
|
|
ck_assert(!array_get(array, 3, &x));
|
|
|
|
array_insert(array, ARRAY_HEAD, &y[1]);
|
|
array_insert(array, 1, &y[2]);
|
|
ck_assert_int_eq(array_count(array), 4);
|
|
|
|
/* 1, 2, 3, 4 */
|
|
|
|
array_insert(array, ARRAY_TAIL, &y[5]);
|
|
array_insert(array, ARRAY_HEAD, &y[0]);
|
|
ck_assert_int_eq(array_count(array), 6);
|
|
|
|
/* 0, 1, 2, 3, 4, 5 */
|
|
|
|
ck_assert(array_remove(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 5);
|
|
ck_assert(array_remove(array, 4, &x));
|
|
ck_assert_int_eq(x, 4);
|
|
|
|
if (i < 3)
|
|
{
|
|
array_compress(array);
|
|
}
|
|
|
|
/* 0, 1, 2, 3 */
|
|
|
|
ck_assert(array_remove(array, ARRAY_HEAD, &x));
|
|
ck_assert_int_eq(x, 0);
|
|
ck_assert(array_remove(array, ARRAY_HEAD, &x));
|
|
ck_assert_int_eq(x, 1);
|
|
|
|
if (i < 2)
|
|
{
|
|
array_compress(array);
|
|
}
|
|
|
|
/* 2, 3 */
|
|
|
|
ck_assert(array_remove(array, ARRAY_TAIL, &x));
|
|
ck_assert_int_eq(x, 3);
|
|
ck_assert(array_remove(array, ARRAY_HEAD, &x));
|
|
ck_assert_int_eq(x, 2);
|
|
|
|
if (i < 1)
|
|
{
|
|
array_compress(array);
|
|
}
|
|
|
|
ck_assert_int_eq(array_count(array), 0);
|
|
|
|
ck_assert(array_remove(array, ARRAY_HEAD, NULL) == FALSE);
|
|
ck_assert(array_remove(array, ARRAY_TAIL, NULL) == FALSE);
|
|
}
|
|
|
|
array_destroy(array);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_enumerate)
|
|
{
|
|
array_t *array;
|
|
int i, *x, y[6] = {0, 1, 2, 3, 4, 5};
|
|
enumerator_t *enumerator;
|
|
|
|
array = array_create(sizeof(y[0]), 0);
|
|
|
|
array_insert(array, ARRAY_TAIL, &y[0]);
|
|
array_insert(array, ARRAY_TAIL, &y[1]);
|
|
array_insert(array, ARRAY_TAIL, &y[2]);
|
|
array_insert(array, ARRAY_TAIL, &y[3]);
|
|
array_insert(array, ARRAY_TAIL, &y[4]);
|
|
array_insert(array, ARRAY_TAIL, &y[5]);
|
|
|
|
ck_assert_int_eq(array_count(array), 6);
|
|
|
|
/* 0, 1, 2, 3, 4, 5 */
|
|
|
|
i = 0;
|
|
enumerator = array_create_enumerator(array);
|
|
while (enumerator->enumerate(enumerator, &x))
|
|
{
|
|
ck_assert_int_eq(*x, y[i]);
|
|
i++;
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
ck_assert_int_eq(i, 6);
|
|
|
|
i = 0;
|
|
enumerator = array_create_enumerator(array);
|
|
while (enumerator->enumerate(enumerator, &x))
|
|
{
|
|
ck_assert_int_eq(*x, y[i]);
|
|
if (i == 0 || i == 3 || i == 5)
|
|
{
|
|
array_remove_at(array, enumerator);
|
|
}
|
|
i++;
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
ck_assert_int_eq(i, 6);
|
|
ck_assert_int_eq(array_count(array), 3);
|
|
|
|
/* 1, 2, 4 */
|
|
|
|
i = 0;
|
|
enumerator = array_create_enumerator(array);
|
|
while (enumerator->enumerate(enumerator, &x))
|
|
{
|
|
switch (i++)
|
|
{
|
|
case 0:
|
|
ck_assert_int_eq(*x, y[1]);
|
|
break;
|
|
case 1:
|
|
ck_assert_int_eq(*x, y[2]);
|
|
break;
|
|
case 2:
|
|
ck_assert_int_eq(*x, y[4]);
|
|
break;
|
|
default:
|
|
ck_assert(0);
|
|
}
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
|
|
array_compress(array);
|
|
|
|
i = 0;
|
|
enumerator = array_create_enumerator(array);
|
|
while (enumerator->enumerate(enumerator, &x))
|
|
{
|
|
switch (i++)
|
|
{
|
|
case 0:
|
|
ck_assert_int_eq(*x, y[1]);
|
|
break;
|
|
case 1:
|
|
ck_assert_int_eq(*x, y[2]);
|
|
break;
|
|
case 2:
|
|
ck_assert_int_eq(*x, y[4]);
|
|
break;
|
|
default:
|
|
ck_assert(0);
|
|
}
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
|
|
array_destroy(array);
|
|
}
|
|
END_TEST
|
|
|
|
static int comp_obj(const void *a, const void *b, void *arg)
|
|
{
|
|
ck_assert_str_eq(arg, "arg");
|
|
return *(int*)a - *(int*)b;
|
|
}
|
|
|
|
START_TEST(test_sort_obj)
|
|
{
|
|
array_t *array;
|
|
int x[][3] = {
|
|
{1, 2, 3},
|
|
{1, 3, 2},
|
|
{2, 1, 3},
|
|
{2, 3, 1},
|
|
{3, 1, 2},
|
|
{3, 2, 1},
|
|
};
|
|
char *arg = "arg";
|
|
int i, v;
|
|
|
|
for (i = 0; i < countof(x); i++)
|
|
{
|
|
array = array_create(sizeof(x[i][0]), 0);
|
|
array_insert(array, ARRAY_TAIL, &x[i][0]);
|
|
array_insert(array, ARRAY_TAIL, &x[i][1]);
|
|
array_insert(array, ARRAY_TAIL, &x[i][2]);
|
|
|
|
array_sort(array, comp_obj, arg);
|
|
|
|
ck_assert(array_get(array, 0, &v));
|
|
ck_assert_int_eq(v, 1);
|
|
ck_assert(array_get(array, 1, &v));
|
|
ck_assert_int_eq(v, 2);
|
|
ck_assert(array_get(array, 2, &v));
|
|
ck_assert_int_eq(v, 3);
|
|
|
|
array_destroy(array);
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
static int comp_ptr(const void *a, const void *b, void *arg)
|
|
{
|
|
ck_assert_str_eq(arg, "arg");
|
|
return strcmp(a, b);
|
|
}
|
|
|
|
START_TEST(test_sort_ptr)
|
|
{
|
|
array_t *array;
|
|
char *x[][3] = {
|
|
{"a", "b", "c"},
|
|
{"a", "c", "b"},
|
|
{"b", "a", "c"},
|
|
{"b", "c", "a"},
|
|
{"c", "a", "b"},
|
|
{"c", "b", "a"},
|
|
};
|
|
char *v, *arg = "arg";
|
|
int i;
|
|
|
|
for (i = 0; i < countof(x); i++)
|
|
{
|
|
array = array_create(0, 0);
|
|
array_insert(array, ARRAY_TAIL, x[i][0]);
|
|
array_insert(array, ARRAY_TAIL, x[i][1]);
|
|
array_insert(array, ARRAY_TAIL, x[i][2]);
|
|
|
|
array_sort(array, comp_ptr, arg);
|
|
|
|
ck_assert(array_get(array, 0, &v));
|
|
ck_assert_str_eq(v, "a");
|
|
ck_assert(array_get(array, 1, &v));
|
|
ck_assert_str_eq(v, "b");
|
|
ck_assert(array_get(array, 2, &v));
|
|
ck_assert_str_eq(v, "c");
|
|
|
|
array_destroy(array);
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
static void invoke(void *data, int idx, void *user)
|
|
{
|
|
int *y = user, *x = data;
|
|
|
|
ck_assert(idx < 3);
|
|
|
|
ck_assert_int_eq(y[idx], *x);
|
|
y[idx] = 0;
|
|
}
|
|
|
|
START_TEST(test_invoke)
|
|
{
|
|
array_t *array;
|
|
int y[] = {1, 2, 3};
|
|
|
|
array = array_create(sizeof(y[0]), 0);
|
|
|
|
array_insert(array, ARRAY_TAIL, &y[0]);
|
|
array_insert(array, ARRAY_TAIL, &y[1]);
|
|
array_insert(array, ARRAY_TAIL, &y[2]);
|
|
|
|
array_invoke(array, invoke, y);
|
|
|
|
ck_assert_int_eq(y[0], 0);
|
|
ck_assert_int_eq(y[0], 0);
|
|
ck_assert_int_eq(y[0], 0);
|
|
|
|
array_destroy(array);
|
|
}
|
|
END_TEST
|
|
|
|
typedef struct obj_t obj_t;
|
|
|
|
struct obj_t {
|
|
void (*fun)(obj_t *obj);
|
|
int x;
|
|
int *counter;
|
|
};
|
|
|
|
static void fun(obj_t *obj)
|
|
{
|
|
ck_assert(obj->x == (*obj->counter)++);
|
|
}
|
|
|
|
START_TEST(test_invoke_offset)
|
|
{
|
|
array_t *array;
|
|
obj_t objs[5];
|
|
int i, counter = 0;
|
|
|
|
array = array_create(0, 0);
|
|
|
|
for (i = 0; i < countof(objs); i++)
|
|
{
|
|
objs[i].x = i;
|
|
objs[i].counter = &counter;
|
|
objs[i].fun = fun;
|
|
|
|
array_insert(array, ARRAY_TAIL, &objs[i]);
|
|
}
|
|
|
|
ck_assert_int_eq(countof(objs), array_count(array));
|
|
|
|
array_invoke_offset(array, offsetof(obj_t, fun));
|
|
|
|
ck_assert_int_eq(counter, countof(objs));
|
|
|
|
array_destroy(array);
|
|
}
|
|
END_TEST
|
|
|
|
Suite *array_suite_create()
|
|
{
|
|
Suite *s;
|
|
TCase *tc;
|
|
|
|
s = suite_create("array");
|
|
|
|
tc = tcase_create("add/get/remove ptr");
|
|
tcase_add_test(tc, test_append_ptr);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("add/get/remove obj");
|
|
tcase_add_test(tc, test_append_obj);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("enumerate");
|
|
tcase_add_test(tc, test_enumerate);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("sort");
|
|
tcase_add_test(tc, test_sort_obj);
|
|
tcase_add_test(tc, test_sort_ptr);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("invoke");
|
|
tcase_add_test(tc, test_invoke);
|
|
suite_add_tcase(s, tc);
|
|
|
|
tc = tcase_create("invoke offset");
|
|
tcase_add_test(tc, test_invoke_offset);
|
|
suite_add_tcase(s, tc);
|
|
|
|
return s;
|
|
}
|