#include <stdio.h> #include <errno.h> #include <kc.h> #include <kc_ut.h> #include <kc_assert.h> #include <kc_queue.h> #include <kc_memory.h> #include <kc_threads.h> #include "ut.h" // プロトタイプ宣言 static void test_queue_new(void); static void test_queue_offer(void); static void test_queue_put(void); static void test_queue_size(void); static void test_queue_offer_ng(void); static void test_queue_malloc_error(void); /** * KcQueue 単体テストスイート */ void suite_queue(void) { KcUt *ut = KcUt_get_instance(); ut->add(ut, UT_TESTCASE, "queue new/delete", test_queue_new); ut->add(ut, UT_TESTCASE, "queue offer/peek/poll", test_queue_offer); ut->add(ut, UT_TESTCASE, "queue put/take", test_queue_put); ut->add(ut, UT_TESTCASE, "queue size", test_queue_size); ut->add(ut, UT_TESTCASE, "queue offer ng", test_queue_offer_ng); ut->add(ut, UT_TESTCASE, "queue malloc error", test_queue_malloc_error); } /** * Queue 生成/破棄。 * * @process KcQueue_new を実行する。。 * @result KcQueue が生成されること。 * * @process KcQueue_delete にて Queue を破棄する。 * @result Queue が破棄されること。 */ static void test_queue_new(void) { KcQueue *queue = KcQueue_new(0); assert_not_null(queue); KcQueue_delete(queue); // リストが残った状態での削除 queue = KcQueue_new(0); queue->offer(queue, "ABC", 4); assert_not_null(queue); KcQueue_delete(queue); } // for offer thread static int test_queue_offer_thread(void *arg) { KcQueue *queue = (KcQueue *)arg; for (int i = 0; i < 100; i++) { printf("offer: %d\n", i); queue->offer(queue, &i, sizeof(int)); KcThread_sleep(0, 1, false); } return 0; } // for poll thread static int test_queue_poll_thread(void *arg) { KcQueue *queue = (KcQueue *)arg; for (int i = 0; i < 100; i++) { int *val = queue->peek(queue, NULL); if (val == NULL) { printf("peek: (null)\n"); } else { printf("peek: %d\n", *val); } int element; size_t size = sizeof(int); bool is_success = queue->poll(queue, &element, &size); if (is_success) { printf("poll: %d\n", element); } else { printf("poll: (null)\n"); } KcThread_sleep(0, 1, false); } return 0; } /** * キューへの値追加/取得。 */ static void test_queue_offer(void) { KcQueue *queue = KcQueue_new(10); KcThread *offer_thread = KcThread_new(test_queue_offer_thread); KcThread *poll_thread = KcThread_new(test_queue_poll_thread); offer_thread->start(offer_thread, queue); poll_thread->start(poll_thread, queue); offer_thread->join(offer_thread); poll_thread->join(poll_thread); KcQueue_delete(queue); KcThread_delete(offer_thread); KcThread_delete(poll_thread); } // for put thread static int test_queue_put_thread(void *arg) { KcQueue *queue = (KcQueue *)arg; for (int i = 0; i < 100; i++) { queue->put(queue, &i, sizeof(int)); KcThread_sleep(0, 1000, false); } return 0; } // for take thread static int test_queue_take_thread(void *arg) { KcQueue *queue = (KcQueue *)arg; for (int i = 0; i < 100; i++) { int element; size_t size = sizeof(int); queue->take(queue, &element, &size); assert_equals(i, element); KcThread_sleep(0, 1, false); } return 0; } // for take thread static int test_queue_take2_thread(void *arg) { KcQueue *queue = (KcQueue *)arg; for (int i = 0; i < 100; i++) { int element; size_t size = sizeof(int); queue->take(queue, &element, &size); assert_equals(i, element); KcThread_sleep(0, 100 * 1000, false); } return 0; } /** * キューへの値追加/取得。 */ static void test_queue_put(void) { { KcQueue *queue = KcQueue_new(0); KcThread *put_thread = KcThread_new(test_queue_put_thread); KcThread *take_thread = KcThread_new(test_queue_take_thread); put_thread->start(put_thread, queue); take_thread->start(take_thread, queue); put_thread->join(put_thread); take_thread->join(take_thread); KcThread_delete(put_thread); KcThread_delete(take_thread); KcQueue_delete(queue); } // PUT ブロックパターン { KcQueue *queue = KcQueue_new(5); KcThread *put_thread = KcThread_new(test_queue_put_thread); KcThread *take_thread = KcThread_new(test_queue_take2_thread); put_thread->start(put_thread, queue); take_thread->start(take_thread, queue); put_thread->join(put_thread); take_thread->join(take_thread); KcThread_delete(put_thread); KcThread_delete(take_thread); KcQueue_delete(queue); } } /** * キューサイズ取得 */ static void test_queue_size(void) { KcQueue *queue = KcQueue_new(0); // キューへ追加 bool ret = queue->offer(queue, "ABC", 4); assert_true(ret); ret = queue->offer(queue, "DEFG", 5); int size = queue->size(queue); assert_equals(2, size); bool is_empty = queue->is_empty(queue); assert_false(is_empty); bool is_contains = queue->contains(queue, "ABC", 4); assert_true(is_contains); is_contains = queue->contains(queue, "DEFG", 5); assert_true(is_contains); char buffer[10]; size_t element_size; // 取り出し [peek] const char *val = (const char *)queue->peek(queue, &element_size); assert_equals(4, element_size); assert_equals("ABC", val); size = queue->size(queue); assert_equals(2, size); is_empty = queue->is_empty(queue); assert_false(is_empty); // 取り出し [poll] (サイズ不足) for (int i = 0; i < 10; i++) { buffer[i] = 'X'; } buffer[9] = '\0'; element_size = 2; queue->poll(queue, buffer, &element_size); assert_equals("ABXXXXXXX", buffer); assert_equals(4, element_size); size = queue->size(queue); assert_equals(1, size); is_empty = queue->is_empty(queue); assert_false(is_empty); is_contains = queue->contains(queue, "ABC", 4); assert_false(is_contains); is_contains = queue->contains(queue, "DEFG", 5); assert_true(is_contains); // 取り出し [poll] for (int i = 0; i < 10; i++) { buffer[i] = 'X'; } buffer[9] = '\0'; element_size = 10; queue->poll(queue, buffer, &element_size); assert_equals("DEFG", buffer); assert_equals(5, element_size); size = queue->size(queue); assert_equals(0, size); is_empty = queue->is_empty(queue); assert_true(is_empty); is_contains = queue->contains(queue, "ABC", 4); assert_false(is_contains); is_contains = queue->contains(queue, "DEFG", 5); assert_false(is_contains); KcQueue_delete(queue); } /** * offer 失敗。 */ static void test_queue_offer_ng(void) { KcQueue *queue = KcQueue_new(3); bool ret; ret = queue->offer(queue, "ABC", 4); assert_true(ret); ret = queue->offer(queue, "DEF", 4); assert_true(ret); ret = queue->offer(queue, "GHI", 4); assert_true(ret); ret = queue->offer(queue, "JKL", 4); assert_false(ret); queue->clear(queue); ret = queue->is_empty(queue); assert_true(ret); KcQueue_delete(queue); } /** * Queue メモリ確保失敗。 */ static void test_queue_malloc_error(void) { // メモリ確保失敗 KcQueue *queue; ut_alloc_control(0) { queue = KcQueue_new(0); } assert_null(queue); // 内部管理のリストメモリ確保失敗 ut_alloc_control(1) { queue = KcQueue_new(0); } assert_null(queue); // 追加時のメモリ確保失敗 queue = KcQueue_new(10); ut_alloc_control(0) { bool ret = queue->offer(queue, "XYZ", 4); assert_false(ret); } KcQueue_delete(queue); }