Newer
Older
libkc / modules / test / src / test_memory.c
Nomura Kei on 22 May 2024 8 KB update
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. #include <kc.h>
  5. #include <kc_assert.h>
  6. #include <kc_ut.h>
  7. #include <kc_memory.h>
  8.  
  9. #include "ut.h"
  10.  
  11. // プロトタイプ宣言
  12. static void test_memory_start(void);
  13. static void test_memory_dump(void);
  14. static void test_memory_set_listener(void);
  15. static void test_memory_entries(void);
  16. static void test_memory_freeif(void);
  17. static void test_memory_aligned(void);
  18. static void test_memory_calloc(void);
  19. static void test_memory_realloc(void);
  20. static void test_memory_raw_xxxxx(void);
  21.  
  22. /**
  23. * memory_mark 単体テストスイート
  24. */
  25. void suite_memory(void)
  26. {
  27. KcUt *ut = KcUt_get_instance();
  28. ut->add(ut, UT_TESTCASE, "memory start", test_memory_start);
  29. ut->add(ut, UT_TESTCASE, "memory dump", test_memory_dump);
  30. ut->add(ut, UT_TESTCASE, "memory set_listener", test_memory_set_listener);
  31. ut->add(ut, UT_TESTCASE, "memory entries", test_memory_entries);
  32. ut->add(ut, UT_TESTCASE, "memory freeif", test_memory_freeif);
  33. ut->add(ut, UT_TESTCASE, "memory aligned", test_memory_aligned);
  34. ut->add(ut, UT_TESTCASE, "memory calloc", test_memory_calloc);
  35. ut->add(ut, UT_TESTCASE, "memory realloc", test_memory_realloc);
  36. ut->add(ut, UT_TESTCASE, "memory raw_xxxxx", test_memory_raw_xxxxx);
  37. }
  38.  
  39. /**
  40. * メモリ管理開始。
  41. *
  42. * @process メモリ管理開始(情報詳細出力あり)
  43. * @process メモリ管理開始(情報詳細出力無し)
  44. */
  45. static void test_memory_start(void)
  46. {
  47. // NOP
  48. // ut.c にて、下記実施
  49. // KcMemory_start(false);
  50. // KcMemory_start(true);
  51. }
  52.  
  53. extern void KcMemory_dump_leak(void);
  54. static bool test_memory_dump_handler(const char *data)
  55. {
  56. printf("%s", data);
  57. return true;
  58. }
  59.  
  60. /**
  61. * 確保中のメモリ情報出力。
  62. *
  63. * @process dump を実行する。
  64. * @result 確保中のメモリ情報が出力されること。
  65. *
  66. * @param dump_leak を実行する。
  67. * @result メモリリーク情報が出力されること。
  68. *
  69. * @process 確保しているメモリがない状態で dump を実行する。
  70. * @result メモリ情報が出力されないこと。
  71. *
  72. * @process 出力用ハンドラを指定してメモリをダンプする。
  73. * @result ハンドラに対してメモリ情報が渡されること。
  74. */
  75. static void test_memory_dump(void)
  76. {
  77. int *val = (int *)malloc(sizeof(int));
  78. *val = 10;
  79.  
  80. printf("---DUMP---\n");
  81. KcMemory_dump();
  82.  
  83. printf("---DUMP LEAK---\n");
  84. KcMemory_dump_leak();
  85.  
  86. free(val);
  87. printf("---DUMP---\n");
  88. KcMemory_dump();
  89.  
  90. val = (int *)malloc(sizeof(int));
  91. *val = 20;
  92. kc_memory_manager->dump(
  93. test_memory_dump_handler, 16, true, true, 8192);
  94. free(val);
  95. }
  96.  
  97. /**
  98. * リスナ設定(NULL指定)。
  99. *
  100. * @process リスナを登録する。(NULL指定)
  101. * @result リスナが設定されないこと。
  102. */
  103. static void test_memory_set_listener(void)
  104. {
  105. KcMemoryListener listener;
  106. listener.allocate = NULL;
  107. listener.free = NULL;
  108. listener.error = NULL;
  109. kc_memory_manager->set_listener(&listener);
  110. }
  111.  
  112. // ハンドラ実行用
  113. static int test_memory_entries_handler_counter = 0;
  114. static int test_memory_entries_handler_values[10];
  115. static int test_memory_entries_handler_can_loop = 0;
  116. static bool test_memory_entries_handler(const KcMemoryEntry *entry, void *info)
  117. {
  118. assert_equals(
  119. test_memory_entries_handler_values[test_memory_entries_handler_counter],
  120. *((int *)entry->data));
  121. test_memory_entries_handler_counter++;
  122. test_memory_entries_handler_can_loop--;
  123. assert_equals("X", (const char *)info);
  124. if (test_memory_entries_handler_can_loop <= 0)
  125. {
  126. return false;
  127. }
  128. return true;
  129. }
  130. /**
  131. * メモリエントリハンドラ実行
  132. */
  133. static void test_memory_entries(void)
  134. {
  135. int *val1 = (int *)malloc(sizeof(int));
  136. int *val2 = (int *)malloc(sizeof(int));
  137. int *val3 = (int *)malloc(sizeof(int));
  138. *val1 = 123;
  139. *val2 = 456;
  140. *val3 = 789;
  141. test_memory_entries_handler_values[0] = 123;
  142. test_memory_entries_handler_values[1] = 456;
  143. test_memory_entries_handler_values[2] = 789;
  144.  
  145. // 途中中断パターン
  146. test_memory_entries_handler_counter = 0;
  147. test_memory_entries_handler_can_loop = 2;
  148. kc_memory_manager->entries(test_memory_entries_handler, "X");
  149. assert_equals(2, test_memory_entries_handler_counter);
  150.  
  151. // 全てダンプパターン
  152. test_memory_entries_handler_counter = 0;
  153. test_memory_entries_handler_can_loop = 999;
  154. kc_memory_manager->entries(test_memory_entries_handler, "X");
  155. assert_equals(3, test_memory_entries_handler_counter);
  156.  
  157. free(val1);
  158. free(val2);
  159. free(val3);
  160. }
  161.  
  162. bool test_memory_freeif_handler(const KcMemoryEntry *entry, void *info)
  163. {
  164. assert_equals("FREEIF", (const char *)info);
  165. if (strcmp("test_memory_freeif", entry->func) == 0)
  166. {
  167. int *data = (int *)entry->data;
  168. if (*data == 456)
  169. {
  170. return true;
  171. }
  172. }
  173. return false;
  174. }
  175.  
  176. /**
  177. * 強制メモリ破棄
  178. */
  179. static void test_memory_freeif(void)
  180. {
  181. int *val1 = (int *)malloc(sizeof(int));
  182. int *val2 = (int *)malloc(sizeof(int));
  183. int *val3 = (int *)malloc(sizeof(int));
  184. *val1 = 123;
  185. *val2 = 456;
  186. *val3 = 789;
  187. test_memory_entries_handler_values[0] = 123;
  188. test_memory_entries_handler_values[1] = 456;
  189. test_memory_entries_handler_values[2] = 789;
  190.  
  191. kc_memory_manager->freeif(test_memory_freeif_handler, "FREEIF");
  192. free(val1);
  193. // free(val2);
  194. free(val3);
  195. }
  196.  
  197. // メモリ確保失敗動作確認用
  198. static int UT_Memory_can_alloc_counter = 0;
  199. static bool UT_Memory_can_alloc(
  200. KcMemoryEntry *entry, size_t alignment, size_t size,
  201. KcMemoryMark mark, const char *file, const char *func, int line)
  202. {
  203. UNUSED_VARIABLE(entry);
  204. UNUSED_VARIABLE(alignment);
  205. UNUSED_VARIABLE(size);
  206. UNUSED_VARIABLE(mark);
  207. UNUSED_VARIABLE(file);
  208. UNUSED_VARIABLE(func);
  209. UNUSED_VARIABLE(line);
  210.  
  211. UT_Memory_can_alloc_counter--;
  212. if (UT_Memory_can_alloc_counter < 0)
  213. {
  214. return false;
  215. }
  216. return true;
  217. }
  218. /**
  219. * アライメント指定メモリ確保
  220. *
  221. * @process aligned_alloc によりメモリを確保する。
  222. * @result メモリが確保されること。
  223. *
  224. * @process メモリ確保が失敗する状態で、aligned_alloc を実行する。
  225. * @result メモリ確保に失敗し、NULL が返されること。
  226. */
  227. static void test_memory_aligned(void)
  228. {
  229. int *val = (int *)aligned_alloc(sizeof(long long), sizeof(int));
  230. assert_not_null(val);
  231. *val = 123;
  232. free(val);
  233.  
  234. UT_Memory_can_alloc_counter = 0;
  235. _UT_KcMemory_can_alloc = UT_Memory_can_alloc;
  236. val = (int *)aligned_alloc(sizeof(long long), sizeof(int));
  237. assert_null(val);
  238. _UT_KcMemory_can_alloc = NULL;
  239. }
  240.  
  241. /**
  242. * calloc によるメモリ確保
  243. *
  244. * @process calloc によりメモリを確保する。
  245. * @result メモリが確保されること。内容がすべて 0 のこと。
  246. *
  247. * @process メモリ確保が失敗する状態で、calloc を実行する。
  248. * @result メモリ確保に失敗し、NULL が返されること。
  249. */
  250. static void test_memory_calloc(void)
  251. {
  252. int *val = (int *)calloc(10, sizeof(int));
  253. for (int i = 0; i < 10; i++)
  254. {
  255. assert_equals(0, val[i]);
  256. }
  257. free(val);
  258.  
  259. UT_Memory_can_alloc_counter = 0;
  260. _UT_KcMemory_can_alloc = UT_Memory_can_alloc;
  261. val = (int *)calloc(10, sizeof(int));
  262. assert_null(val);
  263. _UT_KcMemory_can_alloc = NULL;
  264. }
  265.  
  266. /**
  267. * realloc によるメモリ確保
  268. *
  269. * @process NULL を指定して、realloc によりメモリを確保する。
  270. * @result メモリが確保されること。
  271. *
  272. * @process メモリ確保が失敗する状態で、calloc を実行する。
  273. * @result メモリ確保に失敗し、NULL が返されること。
  274. */
  275. static void test_memory_realloc(void)
  276. {
  277. // NULL 指定
  278. int *val = realloc(NULL, sizeof(int));
  279. assert_not_null(val);
  280. *val = 123;
  281. free(val);
  282.  
  283. // 管理外メモリによる realloc
  284. int *unmng_ptr = raw_malloc(sizeof(int) * 2);
  285. unmng_ptr[0] = 123;
  286. unmng_ptr[1] = 456;
  287. assert_equals(123, unmng_ptr[0]);
  288. assert_equals(456, unmng_ptr[1]);
  289.  
  290. int *mng_ptr = (int *)realloc(unmng_ptr, sizeof(int) * 3);
  291. assert_null(mng_ptr);
  292. free(unmng_ptr);
  293. }
  294.  
  295. /**
  296. * raw_xxxxx 関数動作確認。
  297. */
  298. static void test_memory_raw_xxxxx(void)
  299. {
  300. int *ptr = (int *)raw_malloc(sizeof(int));
  301. assert_not_null(ptr);
  302. raw_free(ptr);
  303.  
  304. ptr = raw_aligned_alloc(sizeof(int), sizeof(int));
  305. assert_not_null(ptr);
  306. raw_free(ptr);
  307.  
  308. ptr = raw_calloc(10, sizeof(int));
  309. assert_not_null(ptr);
  310.  
  311. ptr = raw_realloc(ptr, 20);
  312. assert_not_null(ptr);
  313. raw_free(ptr);
  314. }