- #include <stdio.h>
- #include <string.h>
-
- #include <kc.h>
- #include <kc_assert.h>
- #include <kc_ut.h>
- #include <kc_memory.h>
-
- #include "ut.h"
-
- // プロトタイプ宣言
- static void test_memory_start(void);
- static void test_memory_dump(void);
- static void test_memory_set_listener(void);
- static void test_memory_entries(void);
- static void test_memory_freeif(void);
- static void test_memory_aligned(void);
- static void test_memory_calloc(void);
- static void test_memory_realloc(void);
- static void test_memory_raw_xxxxx(void);
-
- /**
- * memory_mark 単体テストスイート
- */
- void suite_memory(void)
- {
- KcUt *ut = KcUt_get_instance();
- ut->add(ut, UT_TESTCASE, "memory start", test_memory_start);
- ut->add(ut, UT_TESTCASE, "memory dump", test_memory_dump);
- ut->add(ut, UT_TESTCASE, "memory set_listener", test_memory_set_listener);
- ut->add(ut, UT_TESTCASE, "memory entries", test_memory_entries);
- ut->add(ut, UT_TESTCASE, "memory freeif", test_memory_freeif);
- ut->add(ut, UT_TESTCASE, "memory aligned", test_memory_aligned);
- ut->add(ut, UT_TESTCASE, "memory calloc", test_memory_calloc);
- ut->add(ut, UT_TESTCASE, "memory realloc", test_memory_realloc);
- ut->add(ut, UT_TESTCASE, "memory raw_xxxxx", test_memory_raw_xxxxx);
- }
-
- /**
- * メモリ管理開始。
- *
- * @process メモリ管理開始(情報詳細出力あり)
- * @process メモリ管理開始(情報詳細出力無し)
- */
- static void test_memory_start(void)
- {
- // NOP
- // ut.c にて、下記実施
- // KcMemory_start(false);
- // KcMemory_start(true);
- }
-
- extern void KcMemory_dump_leak(void);
- static bool test_memory_dump_handler(const char *data)
- {
- printf("%s", data);
- return true;
- }
-
- /**
- * 確保中のメモリ情報出力。
- *
- * @process dump を実行する。
- * @result 確保中のメモリ情報が出力されること。
- *
- * @param dump_leak を実行する。
- * @result メモリリーク情報が出力されること。
- *
- * @process 確保しているメモリがない状態で dump を実行する。
- * @result メモリ情報が出力されないこと。
- *
- * @process 出力用ハンドラを指定してメモリをダンプする。
- * @result ハンドラに対してメモリ情報が渡されること。
- */
- static void test_memory_dump(void)
- {
- int *val = (int *)malloc(sizeof(int));
- *val = 10;
-
- printf("---DUMP---\n");
- KcMemory_dump();
-
- printf("---DUMP LEAK---\n");
- KcMemory_dump_leak();
-
- free(val);
- printf("---DUMP---\n");
- KcMemory_dump();
-
- val = (int *)malloc(sizeof(int));
- *val = 20;
- kc_memory_manager->dump(
- test_memory_dump_handler, 16, true, true, 8192);
- free(val);
- }
-
- /**
- * リスナ設定(NULL指定)。
- *
- * @process リスナを登録する。(NULL指定)
- * @result リスナが設定されないこと。
- */
- static void test_memory_set_listener(void)
- {
- KcMemoryListener listener;
- listener.allocate = NULL;
- listener.free = NULL;
- listener.error = NULL;
- kc_memory_manager->set_listener(&listener);
- }
-
- // ハンドラ実行用
- static int test_memory_entries_handler_counter = 0;
- static int test_memory_entries_handler_values[10];
- static int test_memory_entries_handler_can_loop = 0;
- static bool test_memory_entries_handler(const KcMemoryEntry *entry, void *info)
- {
- assert_equals(
- test_memory_entries_handler_values[test_memory_entries_handler_counter],
- *((int *)entry->data));
- test_memory_entries_handler_counter++;
- test_memory_entries_handler_can_loop--;
- assert_equals("X", (const char *)info);
- if (test_memory_entries_handler_can_loop <= 0)
- {
- return false;
- }
- return true;
- }
- /**
- * メモリエントリハンドラ実行
- */
- static void test_memory_entries(void)
- {
- int *val1 = (int *)malloc(sizeof(int));
- int *val2 = (int *)malloc(sizeof(int));
- int *val3 = (int *)malloc(sizeof(int));
- *val1 = 123;
- *val2 = 456;
- *val3 = 789;
- test_memory_entries_handler_values[0] = 123;
- test_memory_entries_handler_values[1] = 456;
- test_memory_entries_handler_values[2] = 789;
-
- // 途中中断パターン
- test_memory_entries_handler_counter = 0;
- test_memory_entries_handler_can_loop = 2;
- kc_memory_manager->entries(test_memory_entries_handler, "X");
- assert_equals(2, test_memory_entries_handler_counter);
-
- // 全てダンプパターン
- test_memory_entries_handler_counter = 0;
- test_memory_entries_handler_can_loop = 999;
- kc_memory_manager->entries(test_memory_entries_handler, "X");
- assert_equals(3, test_memory_entries_handler_counter);
-
- free(val1);
- free(val2);
- free(val3);
- }
-
- bool test_memory_freeif_handler(const KcMemoryEntry *entry, void *info)
- {
- assert_equals("FREEIF", (const char *)info);
- if (strcmp("test_memory_freeif", entry->func) == 0)
- {
- int *data = (int *)entry->data;
- if (*data == 456)
- {
- return true;
- }
- }
- return false;
- }
-
- /**
- * 強制メモリ破棄
- */
- static void test_memory_freeif(void)
- {
- int *val1 = (int *)malloc(sizeof(int));
- int *val2 = (int *)malloc(sizeof(int));
- int *val3 = (int *)malloc(sizeof(int));
- *val1 = 123;
- *val2 = 456;
- *val3 = 789;
- test_memory_entries_handler_values[0] = 123;
- test_memory_entries_handler_values[1] = 456;
- test_memory_entries_handler_values[2] = 789;
-
- kc_memory_manager->freeif(test_memory_freeif_handler, "FREEIF");
- free(val1);
- // free(val2);
- free(val3);
- }
-
- // メモリ確保失敗動作確認用
- static int UT_Memory_can_alloc_counter = 0;
- static bool UT_Memory_can_alloc(
- KcMemoryEntry *entry, size_t alignment, size_t size,
- KcMemoryMark mark, const char *file, const char *func, int line)
- {
- UNUSED_VARIABLE(entry);
- UNUSED_VARIABLE(alignment);
- UNUSED_VARIABLE(size);
- UNUSED_VARIABLE(mark);
- UNUSED_VARIABLE(file);
- UNUSED_VARIABLE(func);
- UNUSED_VARIABLE(line);
-
- UT_Memory_can_alloc_counter--;
- if (UT_Memory_can_alloc_counter < 0)
- {
- return false;
- }
- return true;
- }
- /**
- * アライメント指定メモリ確保
- *
- * @process aligned_alloc によりメモリを確保する。
- * @result メモリが確保されること。
- *
- * @process メモリ確保が失敗する状態で、aligned_alloc を実行する。
- * @result メモリ確保に失敗し、NULL が返されること。
- */
- static void test_memory_aligned(void)
- {
- int *val = (int *)aligned_alloc(sizeof(long long), sizeof(int));
- assert_not_null(val);
- *val = 123;
- free(val);
-
- UT_Memory_can_alloc_counter = 0;
- _UT_KcMemory_can_alloc = UT_Memory_can_alloc;
- val = (int *)aligned_alloc(sizeof(long long), sizeof(int));
- assert_null(val);
- _UT_KcMemory_can_alloc = NULL;
- }
-
- /**
- * calloc によるメモリ確保
- *
- * @process calloc によりメモリを確保する。
- * @result メモリが確保されること。内容がすべて 0 のこと。
- *
- * @process メモリ確保が失敗する状態で、calloc を実行する。
- * @result メモリ確保に失敗し、NULL が返されること。
- */
- static void test_memory_calloc(void)
- {
- int *val = (int *)calloc(10, sizeof(int));
- for (int i = 0; i < 10; i++)
- {
- assert_equals(0, val[i]);
- }
- free(val);
-
- UT_Memory_can_alloc_counter = 0;
- _UT_KcMemory_can_alloc = UT_Memory_can_alloc;
- val = (int *)calloc(10, sizeof(int));
- assert_null(val);
- _UT_KcMemory_can_alloc = NULL;
- }
-
- /**
- * realloc によるメモリ確保
- *
- * @process NULL を指定して、realloc によりメモリを確保する。
- * @result メモリが確保されること。
- *
- * @process メモリ確保が失敗する状態で、calloc を実行する。
- * @result メモリ確保に失敗し、NULL が返されること。
- */
- static void test_memory_realloc(void)
- {
- // NULL 指定
- int *val = realloc(NULL, sizeof(int));
- assert_not_null(val);
- *val = 123;
- free(val);
-
- // 管理外メモリによる realloc
- int *unmng_ptr = raw_malloc(sizeof(int) * 2);
- unmng_ptr[0] = 123;
- unmng_ptr[1] = 456;
- assert_equals(123, unmng_ptr[0]);
- assert_equals(456, unmng_ptr[1]);
-
- int *mng_ptr = (int *)realloc(unmng_ptr, sizeof(int) * 3);
- assert_null(mng_ptr);
- free(unmng_ptr);
- }
-
- /**
- * raw_xxxxx 関数動作確認。
- */
- static void test_memory_raw_xxxxx(void)
- {
- int *ptr = (int *)raw_malloc(sizeof(int));
- assert_not_null(ptr);
- raw_free(ptr);
-
- ptr = raw_aligned_alloc(sizeof(int), sizeof(int));
- assert_not_null(ptr);
- raw_free(ptr);
-
- ptr = raw_calloc(10, sizeof(int));
- assert_not_null(ptr);
-
- ptr = raw_realloc(ptr, 20);
- assert_not_null(ptr);
- raw_free(ptr);
- }