Newer
Older
libkc / modules / src / kc_assert.c
  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 <threads.h>
  10. #include <math.h>
  11. #include <kc_assert.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. assert_handler(assert_message);
  91. }
  92. }
  93.  
  94. /**
  95. * 指定されたバイナリが一致するか否か検査します。
  96. *
  97. * @param expected 期待する値
  98. * @param actual 実際の値
  99. * @param file ファイル
  100. * @param func 関数
  101. * @param line 行番号
  102. */
  103. void assert_equals_binary_(
  104. const void *expected, const void *actual, size_t size, const char *file, const char *func, int line)
  105. {
  106. bool is_success = (memcmp(expected, actual, size) == 0);
  107. if (!is_success)
  108. {
  109. char expected_buf[64];
  110. char actual_buf[64];
  111. const char *expected_dump = assert_hexdump(expected_buf, expected, size);
  112. const char *actual_dump = assert_hexdump(actual_buf, actual, size);
  113. snprintf(assert_message, sizeof(assert_message),
  114. "%s:%d: %s: Assertion expected <%s> but was <%s>",
  115. file, line, func, expected_dump, actual_dump);
  116. assert_handler(assert_message);
  117. }
  118. }
  119.  
  120. /**
  121. * 指定された値がNULLであることを検査します。
  122. *
  123. * @param condition 検査する値
  124. * @param file ファイル
  125. * @param func 関数
  126. * @param line 行番号
  127. */
  128. void assert_null_(const void *condition, const char *file, const char *func, int line)
  129. {
  130. bool is_success = (condition == NULL);
  131. if (!is_success)
  132. {
  133. snprintf(assert_message, sizeof(assert_message),
  134. "%s:%d: %s: Assertion condition is not null", file, line, func);
  135. assert_handler(assert_message);
  136. }
  137. }
  138.  
  139. /**
  140. * 指定された値がNULLでないことを検査します。
  141. *
  142. * @param condition 検査する値
  143. * @param file ファイル
  144. * @param func 関数
  145. * @param line 行番号
  146. */
  147. void assert_not_null_(const void *condition, const char *file, const char *func, int line)
  148. {
  149. bool is_success = (condition != NULL);
  150. if (!is_success)
  151. {
  152. snprintf(assert_message, sizeof(assert_message),
  153. "%s:%d: %s: Assertion condition is null", file, line, func);
  154. assert_handler(assert_message);
  155. }
  156. }
  157.  
  158. /**
  159. * 指定された値が false であることを検査します。
  160. *
  161. * @param condition 検査する値
  162. * @param file ファイル
  163. * @param func 関数
  164. * @param line 行番号
  165. */
  166. void assert_false_(bool condition, const char *file, const char *func, int line)
  167. {
  168. bool is_success = (!condition);
  169. if (!is_success)
  170. {
  171. snprintf(assert_message, sizeof(assert_message),
  172. "%s:%d: %s: Assertion condition is not false", file, line, func);
  173. assert_handler(assert_message);
  174. }
  175. }
  176.  
  177. /**
  178. * 指定された値が true であることを検査します。
  179. *
  180. * @param condition 検査する値
  181. * @param file ファイル
  182. * @param func 関数
  183. * @param line 行番号
  184. */
  185. void assert_true_(bool condition, const char *file, const char *func, int line)
  186. {
  187. bool is_success = (condition);
  188. if (!is_success)
  189. {
  190. snprintf(assert_message, sizeof(assert_message),
  191. "%s:%d: %s: Assertion condition is not true", file, line, func);
  192. assert_handler(assert_message);
  193. }
  194. }
  195.  
  196. /**
  197. * 常に失敗であることを示します。
  198. *
  199. * @param file ファイル
  200. * @param func 関数
  201. * @param line 行番号
  202. */
  203. void assert_fail_(const char *file, const char *func, int line)
  204. {
  205. snprintf(assert_message, sizeof(assert_message),
  206. "%s:%d: %s: Assertion fail()", file, line, func);
  207. assert_handler(assert_message);
  208. }
  209.  
  210. /**
  211. * デフォルトアサーションハンドラ。
  212. *
  213. * @param is_success 成功か否か
  214. * @param msg メッセージ
  215. */
  216. static void assert_default_handler(const char *msg)
  217. {
  218. fprintf(stderr, "%s\n", msg);
  219. abort();
  220. }
  221.  
  222. /**
  223. * 最大 16 バイトの16進数ダンプ文字列をバッファに格納します。
  224. *
  225. * @param buff 結果を格納するためのバッファ [48 以上のこと]
  226. * @param data データ
  227. * @param size データのサイズ
  228. */
  229. static const char *assert_hexdump(char *buf, const void *data, size_t size)
  230. {
  231. int dump_size = (size < 16) ? size : 16;
  232. const char *ptr = (const char *)data;
  233. char *write_ptr = buf;
  234. int write_size = 0;
  235. for (int i = 0; i < dump_size; i++)
  236. {
  237. write_size += sprintf(write_ptr, "%02X ", *ptr);
  238. write_ptr += write_size;
  239. ptr++;
  240. }
  241. return buf;
  242. }