log_test_helpers.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* Copyright (c) 2015-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define LOG_PRIVATE
  4. #include "lib/log/log.h"
  5. #include "test/log_test_helpers.h"
  6. /**
  7. * \file log_test_helpers.c
  8. * \brief Code to check for expected log messages during testing.
  9. */
  10. static void mock_saving_logv(int severity, log_domain_mask_t domain,
  11. const char *funcname, const char *suffix,
  12. const char *format, va_list ap)
  13. CHECK_PRINTF(5, 0);
  14. /**
  15. * Smartlist of all the logs we've received since we last set up
  16. * log capture.
  17. */
  18. static smartlist_t *saved_logs = NULL;
  19. /** Boolean: should we also send messages to the test-runner? */
  20. static int echo_to_real_logs = 1;
  21. /** Record logs at this level or more severe */
  22. static int record_logs_at_level = LOG_ERR;
  23. static int saved_log_level = 0;
  24. /**
  25. * As setup_capture_of_logs, but do not relay log messages into the main
  26. * logging system.
  27. *
  28. * Avoid using this function; use setup_capture_of_logs() instead if you
  29. * can. If you must use this function, then make sure you detect any
  30. * unexpected log messages, and treat them as test failures. */
  31. void
  32. setup_full_capture_of_logs(int new_level)
  33. {
  34. setup_capture_of_logs(new_level);
  35. echo_to_real_logs = 0;
  36. }
  37. /**
  38. * Temporarily capture all the messages logged at severity <b>new_level</b> or
  39. * higher.
  40. *
  41. * This function does not prevent messages from being sent to the main
  42. * logging system.
  43. */
  44. void
  45. setup_capture_of_logs(int new_level)
  46. {
  47. if (saved_log_level == 0) {
  48. saved_log_level = log_global_min_severity_;
  49. } else {
  50. tor_assert(0);
  51. }
  52. /* Only change the log_global_min_severity_ if we're making things _more_
  53. * verbose. Otherwise we could prevent real log messages that the test-
  54. * runner wanted.
  55. */
  56. if (log_global_min_severity_ < new_level)
  57. log_global_min_severity_ = new_level;
  58. record_logs_at_level = new_level;
  59. mock_clean_saved_logs();
  60. saved_logs = smartlist_new();
  61. MOCK(logv, mock_saving_logv);
  62. echo_to_real_logs = 1;
  63. }
  64. /**
  65. * Undo setup_capture_of_logs().
  66. *
  67. * This function is safe to call more than once.
  68. */
  69. void
  70. teardown_capture_of_logs(void)
  71. {
  72. UNMOCK(logv);
  73. if (saved_log_level)
  74. log_global_min_severity_ = saved_log_level;
  75. saved_log_level = 0;
  76. mock_clean_saved_logs();
  77. }
  78. /**
  79. * Clear all messages in mock_saved_logs()
  80. */
  81. void
  82. mock_clean_saved_logs(void)
  83. {
  84. if (!saved_logs)
  85. return;
  86. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  87. { tor_free(m->generated_msg); tor_free(m); });
  88. smartlist_free(saved_logs);
  89. saved_logs = NULL;
  90. }
  91. /**
  92. * Return a list of all the messages captured since the last
  93. * setup_[full_]capture_of_logs() call. Each log call is recorded as a
  94. * mock_saved_log_entry_t.
  95. */
  96. const smartlist_t *
  97. mock_saved_logs(void)
  98. {
  99. return saved_logs;
  100. }
  101. int
  102. mock_saved_log_n_entries(void)
  103. {
  104. return saved_logs ? smartlist_len(saved_logs) : 0;
  105. }
  106. /**
  107. * Return true iff there is a message recorded by log capture
  108. * that is exactly equal to <b>msg</b>
  109. */
  110. int
  111. mock_saved_log_has_message(const char *msg)
  112. {
  113. if (saved_logs) {
  114. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  115. {
  116. if (msg && m->generated_msg &&
  117. !strcmp(msg, m->generated_msg)) {
  118. return 1;
  119. }
  120. });
  121. }
  122. return 0;
  123. }
  124. /**
  125. * Return true iff there is a message recorded by log capture
  126. * that contains <b>msg</b> as a substring.
  127. */
  128. int
  129. mock_saved_log_has_message_containing(const char *msg)
  130. {
  131. if (saved_logs) {
  132. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  133. {
  134. if (msg && m->generated_msg &&
  135. strstr(m->generated_msg, msg)) {
  136. return 1;
  137. }
  138. });
  139. }
  140. return 0;
  141. }
  142. /**
  143. * Return true iff there is not a message recorded by log capture
  144. * that contains <b>msg</b> as a substring.
  145. */
  146. int
  147. mock_saved_log_has_message_not_containing(const char *msg)
  148. {
  149. if (saved_logs) {
  150. SMARTLIST_FOREACH(
  151. saved_logs, mock_saved_log_entry_t *, m,
  152. {
  153. if (msg && m->generated_msg && strstr(m->generated_msg, msg))
  154. return 0;
  155. }
  156. );
  157. }
  158. return 1;
  159. }
  160. /** Return true iff the saved logs have any messages with <b>severity</b> */
  161. int
  162. mock_saved_log_has_severity(int severity)
  163. {
  164. int has_sev = 0;
  165. if (saved_logs) {
  166. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  167. {
  168. if (m->severity == severity) {
  169. has_sev = 1;
  170. }
  171. });
  172. }
  173. return has_sev;
  174. }
  175. /** Return true iff the the saved logs have at lease one message */
  176. int
  177. mock_saved_log_has_entry(void)
  178. {
  179. if (saved_logs) {
  180. return smartlist_len(saved_logs) > 0;
  181. }
  182. return 0;
  183. }
  184. /* Replacement for logv: record the log message, and (maybe) send it
  185. * into the logging system again.
  186. */
  187. static void
  188. mock_saving_logv(int severity, log_domain_mask_t domain,
  189. const char *funcname, const char *suffix,
  190. const char *format, va_list ap)
  191. {
  192. char *buf = tor_malloc_zero(10240);
  193. int n;
  194. n = tor_vsnprintf(buf,10240,format,ap);
  195. tor_assert(n < 10240-1);
  196. buf[n]='\n';
  197. buf[n+1]='\0';
  198. if (echo_to_real_logs) {
  199. tor_log(severity, domain|LD_NO_MOCK, "%s", buf);
  200. }
  201. if (severity > record_logs_at_level) {
  202. tor_free(buf);
  203. return;
  204. }
  205. if (!saved_logs)
  206. saved_logs = smartlist_new();
  207. mock_saved_log_entry_t *e = tor_malloc_zero(sizeof(mock_saved_log_entry_t));
  208. e->severity = severity;
  209. e->funcname = funcname;
  210. e->suffix = suffix;
  211. e->format = format;
  212. e->generated_msg = tor_strdup(buf);
  213. tor_free(buf);
  214. smartlist_add(saved_logs, e);
  215. }
  216. void
  217. mock_dump_saved_logs(void)
  218. {
  219. if (saved_logs == NULL) {
  220. puts(" Captured logs: NULL");
  221. return;
  222. }
  223. puts(" Captured logs:");
  224. SMARTLIST_FOREACH_BEGIN(saved_logs, const mock_saved_log_entry_t *, m) {
  225. printf("% 5d. %s: %s\n", m_sl_idx + 1,
  226. log_level_to_string(m->severity),
  227. escaped(m->generated_msg));
  228. } SMARTLIST_FOREACH_END(m);
  229. }