Newer
Older
libkc / modules / src / kc_assert.c
Nomura Kei on 2 Jun 2024 6 KB update
  1. /**
  2. * @file kc_assert.c
  3. * @brief アサーションモジュール
  4. * @copyright 2003 - 2023 Nomura Kei
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <kc_assert.h>
  11. #include <kc_threads.h>
  12.  
  13. // プロトタイプ宣言
  14. static void assert_default_handler(const char *msg);
  15. static const char *assert_hexdump(char *buf, const void *data, size_t size);
  16.  
  17. // ハンドラ
  18. /**
  19. * Assertion 発生時に実行されるハンドラ。
  20. *
  21. * @param msg エラーメッセージ
  22. */
  23. void (*assert_handler)(const char *msg) = assert_default_handler;
  24.  
  25. /** Assertion で利用するメッセージバッファ。 */
  26. static thread_local char assert_message[1024];
  27.  
  28. /**
  29. * 指定された値が一致するか否か検査します。
  30. *
  31. * @param expected 期待する値
  32. * @param actual 実際の値
  33. * @param file ファイル
  34. * @param func 関数
  35. * @param line 行番号
  36. */
  37. void assert_equals_long_(
  38. long expected, long actual, const char *file, const char *func, int line)
  39. {
  40. bool is_success = (expected == actual);
  41. if (!is_success)
  42. {
  43. snprintf(assert_message, sizeof(assert_message),
  44. "%s:%d: %s: Assertion expected <%ld> but was <%ld>",
  45. file, line, func, expected, actual);
  46. assert_handler(assert_message);
  47. }
  48. }
  49.  
  50. /**
  51. * 指定された値が一致するか否か検査します。
  52. *
  53. * @param expected 期待する値
  54. * @param actual 実際の値
  55. * @param file ファイル
  56. * @param func 関数
  57. * @param line 行番号
  58. */
  59. void assert_equals_double_(
  60. double expected, double actual, double delta, const char *file, const char *func, int line)
  61. {
  62. bool is_success = (fabs((double)expected - actual) < delta);
  63. if (!is_success)
  64. {
  65. snprintf(assert_message, sizeof(assert_message),
  66. "%s:%d: %s: Assertion expected <%f> but was <%f>",
  67. file, line, func, expected, actual);
  68. assert_handler(assert_message);
  69. }
  70. }
  71.  
  72. /**
  73. * 指定された文字列が一致するか否か検査します。
  74. *
  75. * @param expected 期待する値
  76. * @param actual 実際の値
  77. * @param file ファイル
  78. * @param func 関数
  79. * @param line 行番号
  80. */
  81. void assert_equals_string_(
  82. const char *expected, const char *actual, const char *file, const char *func, int line)
  83. {
  84. bool is_success = (strcmp(expected, actual) == 0);
  85. if (!is_success)
  86. {
  87. snprintf(assert_message, sizeof(assert_message),
  88. "%s:%d: %s: Assertion expected <%s> but was <%s>",
  89. file, line, func, expected, actual);
  90. if (strlen(actual) == 6)
  91. {
  92. printf("[%s]\n", actual);
  93. printf("[%c][%02x]\n", actual[5], actual[5]);
  94. }
  95.  
  96. assert_handler(assert_message);
  97. }
  98. }
  99.  
  100. /**
  101. * 指定されたバイナリが一致するか否か検査します。
  102. *
  103. * @param expected 期待する値
  104. * @param actual 実際の値
  105. * @param file ファイル
  106. * @param func 関数
  107. * @param line 行番号
  108. */
  109. void assert_equals_binary_(
  110. const void *expected, const void *actual, size_t size, const char *file, const char *func, int line)
  111. {
  112. bool is_success = (memcmp(expected, actual, size) == 0);
  113. if (!is_success)
  114. {
  115. char expected_buf[64];
  116. char actual_buf[64];
  117. const char *expected_dump = assert_hexdump(expected_buf, expected, size);
  118. const char *actual_dump = assert_hexdump(actual_buf, actual, size);
  119. snprintf(assert_message, sizeof(assert_message),
  120. "%s:%d: %s: Assertion expected <%s> but was <%s>",
  121. file, line, func, expected_dump, actual_dump);
  122. assert_handler(assert_message);
  123. }
  124. }
  125.  
  126. /**
  127. * 指定された値がNULLであることを検査します。
  128. *
  129. * @param condition 検査する値
  130. * @param file ファイル
  131. * @param func 関数
  132. * @param line 行番号
  133. */
  134. void assert_null_(const void *condition, const char *file, const char *func, int line)
  135. {
  136. bool is_success = (condition == NULL);
  137. if (!is_success)
  138. {
  139. snprintf(assert_message, sizeof(assert_message),
  140. "%s:%d: %s: Assertion condition is not null", file, line, func);
  141. assert_handler(assert_message);
  142. }
  143. }
  144.  
  145. /**
  146. * 指定された値がNULLでないことを検査します。
  147. *
  148. * @param condition 検査する値
  149. * @param file ファイル
  150. * @param func 関数
  151. * @param line 行番号
  152. */
  153. void assert_not_null_(const void *condition, const char *file, const char *func, int line)
  154. {
  155. bool is_success = (condition != NULL);
  156. if (!is_success)
  157. {
  158. snprintf(assert_message, sizeof(assert_message),
  159. "%s:%d: %s: Assertion condition is null", file, line, func);
  160. assert_handler(assert_message);
  161. }
  162. }
  163.  
  164. /**
  165. * 指定された値が false であることを検査します。
  166. *
  167. * @param condition 検査する値
  168. * @param file ファイル
  169. * @param func 関数
  170. * @param line 行番号
  171. */
  172. void assert_false_(bool condition, const char *file, const char *func, int line)
  173. {
  174. bool is_success = (!condition);
  175. if (!is_success)
  176. {
  177. snprintf(assert_message, sizeof(assert_message),
  178. "%s:%d: %s: Assertion condition is not false", file, line, func);
  179. assert_handler(assert_message);
  180. }
  181. }
  182.  
  183. /**
  184. * 指定された値が true であることを検査します。
  185. *
  186. * @param condition 検査する値
  187. * @param file ファイル
  188. * @param func 関数
  189. * @param line 行番号
  190. */
  191. void assert_true_(bool condition, const char *file, const char *func, int line)
  192. {
  193. bool is_success = (condition);
  194. if (!is_success)
  195. {
  196. snprintf(assert_message, sizeof(assert_message),
  197. "%s:%d: %s: Assertion condition is not true", file, line, func);
  198. assert_handler(assert_message);
  199. }
  200. }
  201.  
  202. /**
  203. * 常に失敗であることを示します。
  204. *
  205. * @param file ファイル
  206. * @param func 関数
  207. * @param line 行番号
  208. */
  209. void assert_fail_(const char *file, const char *func, int line)
  210. {
  211. snprintf(assert_message, sizeof(assert_message),
  212. "%s:%d: %s: Assertion fail()", file, line, func);
  213. assert_handler(assert_message);
  214. }
  215.  
  216. /**
  217. * デフォルトアサーションハンドラ。
  218. *
  219. * @param is_success 成功か否か
  220. * @param msg メッセージ
  221. */
  222. static void assert_default_handler(const char *msg)
  223. {
  224. fprintf(stderr, "%s\n", msg);
  225. abort();
  226. }
  227.  
  228. /**
  229. * 最大 16 バイトの16進数ダンプ文字列をバッファに格納します。
  230. *
  231. * @param buff 結果を格納するためのバッファ [48 以上のこと]
  232. * @param data データ
  233. * @param size データのサイズ
  234. */
  235. static const char *assert_hexdump(char *buf, const void *data, size_t size)
  236. {
  237. int dump_size = (size < 16) ? size : 16;
  238. const char *ptr = (const char *)data;
  239. char *write_ptr = buf;
  240. int write_size = 0;
  241. for (int i = 0; i < dump_size; i++)
  242. {
  243. write_size += sprintf(write_ptr, "%02X ", *ptr);
  244. write_ptr += write_size;
  245. ptr++;
  246. }
  247. return buf;
  248. }