log_test_helpers.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* Copyright (c) 2015-2017, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define LOG_PRIVATE
  4. #include "torlog.h"
  5. #include "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. /** Return true iff the saved logs have any messages with <b>severity</b> */
  143. int
  144. mock_saved_log_has_severity(int severity)
  145. {
  146. int has_sev = 0;
  147. if (saved_logs) {
  148. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  149. {
  150. if (m->severity == severity) {
  151. has_sev = 1;
  152. }
  153. });
  154. }
  155. return has_sev;
  156. }
  157. /** Return true iff the the saved logs have at lease one message */
  158. int
  159. mock_saved_log_has_entry(void)
  160. {
  161. if (saved_logs) {
  162. return smartlist_len(saved_logs) > 0;
  163. }
  164. return 0;
  165. }
  166. /* Replacement for logv: record the log message, and (maybe) send it
  167. * into the logging system again.
  168. */
  169. static void
  170. mock_saving_logv(int severity, log_domain_mask_t domain,
  171. const char *funcname, const char *suffix,
  172. const char *format, va_list ap)
  173. {
  174. char *buf = tor_malloc_zero(10240);
  175. int n;
  176. n = tor_vsnprintf(buf,10240,format,ap);
  177. tor_assert(n < 10240-1);
  178. buf[n]='\n';
  179. buf[n+1]='\0';
  180. if (echo_to_real_logs) {
  181. tor_log(severity, domain|LD_NO_MOCK, "%s", buf);
  182. }
  183. if (severity > record_logs_at_level) {
  184. tor_free(buf);
  185. return;
  186. }
  187. if (!saved_logs)
  188. saved_logs = smartlist_new();
  189. mock_saved_log_entry_t *e = tor_malloc_zero(sizeof(mock_saved_log_entry_t));
  190. e->severity = severity;
  191. e->funcname = funcname;
  192. e->suffix = suffix;
  193. e->format = format;
  194. e->generated_msg = tor_strdup(buf);
  195. tor_free(buf);
  196. smartlist_add(saved_logs, e);
  197. }
  198. void
  199. mock_dump_saved_logs(void)
  200. {
  201. if (saved_logs == NULL) {
  202. puts(" Captured logs: NULL");
  203. return;
  204. }
  205. puts(" Captured logs:");
  206. SMARTLIST_FOREACH_BEGIN(saved_logs, const mock_saved_log_entry_t *, m) {
  207. printf("% 5d. %s: %s\n", m_sl_idx + 1,
  208. log_level_to_string(m->severity),
  209. escaped(m->generated_msg));
  210. } SMARTLIST_FOREACH_END(m);
  211. }