- #include <errno.h>
-
- #include <kc.h>
- #include <kc_ut.h>
- #include <kc_assert.h>
- #include <kc_list.h>
- #include <kc_memory.h>
-
- #include "ut.h"
-
- // プロトタイプ宣言
- static void test_list_linked_new(void);
- static void test_list_linked_add(void);
- static void test_list_linked_remove(void);
- static void test_list_linked_set(void);
- static void test_list_linked_search(void);
- static void test_list_linked_sort(void);
- static void test_list_linked_malloc_error(void);
-
- /**
- * LinkedList 単体テストスイート
- */
- void suite_list_linked(void)
- {
- KcUt *ut = KcUt_get_instance();
- ut->add(ut, UT_TESTCASE, "list_linked new LinkedList", test_list_linked_new);
- ut->add(ut, UT_TESTCASE, "list_linked add/get", test_list_linked_add);
- ut->add(ut, UT_TESTCASE, "list_linked remove", test_list_linked_remove);
- ut->add(ut, UT_TESTCASE, "list_linked set", test_list_linked_set);
- ut->add(ut, UT_TESTCASE, "list_linked search", test_list_linked_search);
- ut->add(ut, UT_TESTCASE, "list_linked sort", test_list_linked_sort);
- ut->add(ut, UT_TESTCASE, "list_linked malloc error", test_list_linked_malloc_error);
- }
-
- /**
- * LinkedList 生成/破棄。
- *
- * @process KcList_new_LinkedList を実行する。。
- * @result LinkedList が生成されること。
- *
- * @process KcList_delete にて LinkedList を破棄する。
- * @result LinkedList が破棄されること。
- */
- static void test_list_linked_new(void)
- {
- KcList *list = KcList_new_LinkedList();
- assert_not_null(list);
- KcList_delete(list);
- }
-
- /**
- * LinkedList データ追加/取得。
- *
- * @process 初回追加 (index = 0)
- * @process 2つめ追加 (index = 1)
- * @process 先頭に追加 (index = 0)
- * @process 末尾に追加 (index = 負値(-1))
- * @process 追加(index 不正)
- * @process 値取得(サイズ取得あり)
- * @process 値取得(サイズ取得なし)
- * @process 値取得 (index 不正[負の値を指定])
- * @process 値取得 (index 不正[サイズ以上を指定])
- */
- static void test_list_linked_add(void)
- {
- KcList *list = KcList_new_LinkedList();
- assert_not_null(list);
-
- // 空
- bool is_empty = list->is_empty(list);
- assert_true(is_empty);
-
- // 1つめ追加
- int val = 10;
- bool res = list->add(list, 0, &val, sizeof(int));
- assert_true(res);
- is_empty = list->is_empty(list);
- assert_false(is_empty);
-
- // 2つめ追加
- val = 20;
- res = list->add(list, 1, &val, sizeof(int));
- assert_true(res);
-
- // 先頭に追加
- val = 30;
- res = list->add(list, 0, &val, sizeof(int));
- assert_true(res);
-
- // 末尾に追加
- val = 40;
- res = list->add(list, -1, &val, sizeof(int));
- assert_true(res);
-
- // 追加不可位置への追加
- val = 50;
- res = list->add(list, 10, &val, sizeof(int));
- assert_false(res);
-
- // 1つめ取得
- size_t size;
- int *res_val = list->get(list, 0, &size);
- assert_equals((int)sizeof(int), (int)size);
- assert_equals(30, *res_val);
-
- // 2つめ取得
- res_val = list->get(list, 1, &size);
- assert_equals((int)sizeof(int), (int)size);
- assert_equals(10, *res_val);
-
- // 3つめ取得(サイズ取得なし)
- res_val = list->get(list, 2, NULL);
- assert_equals(20, *res_val);
-
- // 4つめ取得(サイズ取得なし)
- res_val = list->get(list, 3, NULL);
- assert_equals(40, *res_val);
-
- // 値取得 (index 不正[負の値を指定])
- res_val = list->get(list, -1, NULL);
- assert_null(res_val);
-
- // 値取得 (index 不正[サイズを指定])
- res_val = list->get(list, 4, NULL);
- assert_null(res_val);
-
- // 値取得 (index 不正[サイズ以上を指定])
- res_val = list->get(list, 5, NULL);
- assert_null(res_val);
-
- KcList_delete(list);
- }
-
- /**
- * LinkedList データ削除。
- *
- * @process 末尾削除
- * @process 中間削除
- * @process 先頭削除
- * @process 削除(index 不正[負の値を指定])
- * @process 削除(index 不正[サイズ以上を指定])
- * @process 残っているデータを確認
- * @process 容量調整(初期容量→1/4以下)
- */
- static void test_list_linked_remove(void)
- {
- KcList *list = KcList_new_LinkedList();
- assert_not_null(list);
-
- // 値設定
- int vals[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160};
- int default_size = 16;
- for (int i = 0; i < (int)(sizeof(vals) / sizeof(int)); i++)
- {
- int val = vals[i];
- bool res = list->add(list, -1, &val, sizeof(int));
- assert_true(res);
- }
-
- // 末尾削除 (値、サイズ取得あり)
- int rval;
- size_t rsize = sizeof(int);
- bool ret = list->remove(list, (default_size - 1), &rval, &rsize);
- assert_true(ret);
- assert_equals(vals[(default_size - 1)], rval);
- assert_equals((int)sizeof(int), (int)rsize);
- int now_size = list->size(list);
- assert_equals((default_size - 1), now_size);
-
- // 値を追加して戻しておく
- list->add(list, (default_size - 1), &vals[(default_size - 1)], sizeof(int));
- now_size = list->size(list);
- assert_equals(default_size, now_size);
-
- // 中間削除 (値取得設定あり、サイズ指定なし [=値取得できない])
- // 10, 20, <30>, 40, 50, ...
- rval = 9999;
- ret = list->remove(list, 2, &rval, NULL);
- assert_true(ret);
- assert_equals(9999, rval); // size 指定なしのため、値は取得できない。
- now_size = list->size(list);
- assert_equals((default_size - 1), now_size);
-
- // 先頭削除 (値取得なし)
- // <10>, 20, 40, 50, ...
- ret = list->remove(list, 0, NULL, NULL);
- assert_true(ret);
- now_size = list->size(list);
- assert_equals((default_size - 2), now_size);
-
- // 削除(index 不正[負の値指定])
- ret = list->remove(list, -1, NULL, NULL);
- assert_false(ret);
-
- // 削除(index 不正[サイズ以上を指定])
- ret = list->remove(list, default_size, NULL, NULL);
- assert_false(ret);
-
- // 残り3つになるまで削除 (3つめを削除)
- int rest_size = list->size(list);
- while (rest_size > 3)
- {
- ret = list->remove(list, 3, NULL, NULL);
- assert_true(ret);
- rest_size = list->size(list);
- }
-
- // 残っているデータの確認
- // 20, 40, 50
- int *res_val_1 = list->get(list, 0, NULL);
- int *res_val_2 = list->get(list, 1, NULL);
- int *res_val_3 = list->get(list, 2, NULL);
- assert_equals(20, *res_val_1);
- assert_equals(40, *res_val_2);
- assert_equals(50, *res_val_3);
-
- bool is_empty = list->is_empty(list);
- assert_false(is_empty);
-
- // クリア
- list->clear(list);
- is_empty = list->is_empty(list);
- assert_true(is_empty);
-
- KcList_delete(list);
- }
-
- /**
- * LinkedList データ設定。
- *
- * @process 値設定(複数設定)
- * @process 値設定(元の値、サイズ取得)
- * @process 値設定(元の値取得)
- * @process 値設定(不正index[負の値指定])
- * @process 値設定(不正index[サイズ以上指定])
- */
- static void test_list_linked_set(void)
- {
- KcList *list = KcList_new_LinkedList();
- assert_not_null(list);
-
- // 値設定
- int vals[] = {10, 20, 30, 40, 50};
- for (int i = 0; i < (int)(sizeof(vals) / sizeof(int)); i++)
- {
- int val = vals[i];
- bool res = list->add(list, -1, &val, sizeof(int));
- assert_true(res);
- }
- int now_size = list->size(list);
- assert_equals(5, now_size);
-
- // 値設定 (元の値, サイズ取得)
- int set_value = 99;
- int orig_val = 9999;
- size_t orig_size = sizeof(int);
- bool ret = list->set(list, 1, &set_value, sizeof(int), &orig_val, &orig_size);
- assert_true(ret);
- assert_equals(20, orig_val);
- assert_equals((int)sizeof(int), (int)orig_size);
- int *res_val = list->get(list, 1, NULL);
- assert_equals(99, *res_val);
-
- // 値設定 (元の値, サイズ取得[設定値の方がサイズが大きい])
- set_value = 101;
- int orig_val_array[2];
- orig_size = sizeof(int) * 2;
- ret = list->set(list, 1, &set_value, sizeof(int), orig_val_array, &orig_size);
- assert_true(ret);
- assert_equals(99, orig_val_array[0]);
- assert_equals((int)sizeof(int), (int)orig_size);
- res_val = list->get(list, 1, NULL);
- assert_equals(101, *res_val);
-
- // 値設定 (元の値取得, サイズ指定なし[=値取得不可])
- set_value = 98;
- orig_val = 9999;
- ret = list->set(list, 0, &set_value, sizeof(int), &orig_val, NULL);
- assert_true(ret);
- assert_equals(9999, orig_val); // size 指定なしのため、値取得不可
- res_val = list->get(list, 0, NULL);
- assert_equals(98, *res_val);
-
- // 値設定 (サイズ取得 [=値指定なしのためサイズ取得不可])
- set_value = 97;
- orig_size = 0;
- ret = list->set(list, 0, &set_value, sizeof(int), NULL, &orig_size);
- assert_true(ret);
- assert_equals(0, (int)orig_size); // size 取得不可
- res_val = list->get(list, 0, NULL);
- assert_equals(97, *res_val);
-
- now_size = list->size(list);
- assert_equals(5, now_size);
-
- // 値設定(不正index[負の値指定])
- set_value = 96;
- ret = list->set(list, -1, &set_value, sizeof(int), NULL, NULL);
- assert_false(ret);
-
- // 値設定(不正index[サイズ指定])
- set_value = 95;
- ret = list->set(list, 5, &set_value, sizeof(int), NULL, NULL);
- assert_false(ret);
-
- // 値設定(不正index[サイズ以上指定])
- set_value = 95;
- ret = list->set(list, 6, &set_value, sizeof(int), NULL, NULL);
- assert_false(ret);
-
- KcList_delete(list);
- }
-
- /**
- * LinkedList 検索。
- *
- * @process リスト {10, 30, 50, 40, 20, 10, 30, 60, 20 } を構築する。
- * @result リストが構築されること
- *
- * @process is_contains でリストに含まれる値を確認する。
- * @result true が返されること。
- *
- * @process index_of で各インデックス位置を取得する。
- * @result 先頭からのインデックス位置が正しく取得されること。
- *
- * @process last_index_of で各インデックス位置を取得する。
- * @result 末尾からのインデックス位置が正しく取得されること。
- *
- * @process リストに含まれない値を指定して、is_contains を実行する。
- * @result false が返されること。
- *
- * @process リストに含まれない値を指定して、index_of を実行する。
- * @result -1 が返されること。
- *
- * @process リストに含まれない値を指定して、last_index_of を実行する。
- * @result -1 が返されること。
- *
- * @process 異なるサイズ指定して、is_contains を実行する。
- * @result -1 が返されること。
- *
- */
- static void test_list_linked_search(void)
- {
- KcList *list = KcList_new_LinkedList();
- assert_not_null(list);
-
- // 値設定
- int vals[] = {10, 30, 50, 40, 20, 10, 30, 60, 20};
- for (int i = 0; i < (int)(sizeof(vals) / sizeof(int)); i++)
- {
- int val = vals[i];
- bool res = list->add(list, -1, &val, sizeof(int));
- assert_true(res);
- }
- int now_size = list->size(list);
- assert_equals(9, now_size);
-
- // 値が含まれることの確認
- // index_of, last_index_of の確認
- int c_vals[] = {10, 20, 30, 40, 50, 60};
- int c_vals_index[] = {0, 4, 1, 3, 2, 7};
- int c_vals_lindex[] = {5, 8, 6, 3, 2, 7};
- bool is_contains;
- int res_index;
- int res_lindex;
- for (int i = 0; i < (int)(sizeof(c_vals) / sizeof(int)); i++)
- {
- is_contains = list->contains(list, &c_vals[i], sizeof(int));
- assert_true(is_contains);
-
- res_index = list->index_of(list, &c_vals[i], sizeof(int));
- assert_equals(c_vals_index[i], res_index);
-
- res_lindex = list->last_index_of(list, &c_vals[i], sizeof(int));
- assert_equals(c_vals_lindex[i], res_lindex);
- }
-
- // 値が含まれないことの確認
- int c_val = 99;
- is_contains = list->contains(list, &c_val, sizeof(int));
- assert_false(is_contains);
-
- res_index = list->index_of(list, &c_val, sizeof(int));
- assert_equals(-1, res_index);
-
- res_lindex = list->last_index_of(list, &c_val, sizeof(int));
- assert_equals(-1, res_lindex);
-
- // 値が含まれないことの確認(異なるサイズ指定)
- c_val = 10;
- is_contains = list->contains(list, &c_val, sizeof(int) * 2);
- assert_false(is_contains);
-
- res_index = list->index_of(list, &c_val, sizeof(int) * 2);
- assert_equals(-1, res_index);
-
- res_lindex = list->last_index_of(list, &c_val, sizeof(int) * 2);
- assert_equals(-1, res_lindex);
-
- KcList_delete(list);
- }
-
- // ソート用コンパレータ
- static int test_list_linked_sort_comparator(
- const void *element1, size_t size1,
- const void *element2, size_t size2,
- void *args)
- {
- int val1 = *((int *)element1);
- int val2 = *((int *)element2);
- assert_equals((int)sizeof(int), (int)size1);
- assert_equals((int)sizeof(int), (int)size2);
- assert_equals("ABCDEFG", (const char *)args);
- return (val1 - val2);
- }
-
- /**
- * LinkedList ソート。
- *
- * @process リスト {10, 30, 50, 40, 20, 10, 30, 60, 20} を構築する。
- * @result リストが構築されること。
- *
- * @process 昇順用コンパレータを渡し、ソートする。
- * @result リストがソートされること。
- *
- * @process Iterator を取得する。
- * @result Iterator にて順次値が取得できること。
- */
- static void test_list_linked_sort(void)
- {
- KcList *list = KcList_new_LinkedList();
- assert_not_null(list);
-
- // 値設定
- int vals[] = {10, 30, 50, 40, 20, 10, 30, 60, 20};
- for (int i = 0; i < (int)(sizeof(vals) / sizeof(int)); i++)
- {
- int val = vals[i];
- bool res = list->add(list, -1, &val, sizeof(int));
- assert_true(res);
- }
- int now_size = list->size(list);
- assert_equals(9, now_size);
-
- // ソート実施
- list->sort(list, test_list_linked_sort_comparator, "ABCDEFG");
- int sorted_vals[] = {10, 10, 20, 20, 30, 30, 40, 50, 60};
-
- // Iterator にて値を取得&確認
- KcIterator *ite = list->iterator(list, 0);
- int sorted_index = 0;
- while (ite->hasNext(ite))
- {
- size_t res_size;
- int *res_val = (int *)ite->next(ite, &res_size);
- assert_equals((int)sizeof(int), (int)res_size);
- assert_equals(sorted_vals[sorted_index], *res_val);
- sorted_index++;
- }
- KcIterator_delete(ite);
-
- // index = 5 より取得
- ite = list->iterator(list, 5);
- sorted_index = 5;
- while (ite->hasNext(ite))
- {
- int *res_val = (int *)ite->next(ite, NULL);
- assert_equals(sorted_vals[sorted_index], *res_val);
- sorted_index++;
- }
- KcIterator_delete(ite);
-
- KcList_delete(list);
- }
-
- /**
- * LinkedList メモリ確保失敗。
- */
- static void test_list_linked_malloc_error(void)
- {
- // LinkedList のメモリ確保失敗
- ut_alloc_control(0)
- {
- KcList *list = KcList_new_LinkedList();
- assert_null(list);
- }
-
- // LinkedList の add 時のメモリ確保失敗
- KcList *list = KcList_new_LinkedList();
- ut_alloc_control(0)
- {
- bool ret = list->add(list, 0, "ABC", 4);
- assert_false(ret);
- assert_equals(0, list->size(list));
- }
-
- // Iterator 生成時のメモリ確保失敗
- ut_alloc_control(0)
- {
- KcIterator *ite = list->iterator(list, 0);
- assert_null(ite);
- }
-
- // set 時のメモリ確保失敗
- list->add(list, 0, "ABC", 4);
- ut_alloc_control(0)
- {
- list->set(list, 0, "XYZXYZ", 7, NULL, NULL);
- assert_equals("ABC", (const char *)list->get(list, 0, NULL));
- }
-
- KcList_delete(list);
- }