log_test_helpers.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Copyright (c) 2015-2016, 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. /**
  24. * As setup_capture_of_logs, but do not relay log messages into the main
  25. * logging system.
  26. *
  27. * Avoid using this function; use setup_capture_of_logs() instead if you
  28. * can. If you must use this function, then make sure you detect any
  29. * unexpected log messages, and treat them as test failures. */
  30. int
  31. setup_full_capture_of_logs(int new_level)
  32. {
  33. int result = setup_capture_of_logs(new_level);
  34. echo_to_real_logs = 0;
  35. return result;
  36. }
  37. /**
  38. * Temporarily capture all the messages logged at severity <b>new_level</b> or
  39. * higher. Return the previous log level; you'll need to pass it into
  40. * teardown_capture_of_logs().
  41. *
  42. * This function does not prevent messages from being sent to the main
  43. * logging system.
  44. */
  45. int
  46. setup_capture_of_logs(int new_level)
  47. {
  48. int previous_log = log_global_min_severity_;
  49. /* Only change the log_global_min_severity_ if we're making things _more_
  50. * verbose. Otherwise we could prevent real log messages that the test-
  51. * runner wanted.
  52. */
  53. if (log_global_min_severity_ < new_level)
  54. log_global_min_severity_ = new_level;
  55. record_logs_at_level = new_level;
  56. mock_clean_saved_logs();
  57. saved_logs = smartlist_new();
  58. MOCK(logv, mock_saving_logv);
  59. echo_to_real_logs = 1;
  60. return previous_log;
  61. }
  62. /**
  63. * Undo setup_capture_of_logs().
  64. */
  65. void
  66. teardown_capture_of_logs(int prev)
  67. {
  68. UNMOCK(logv);
  69. log_global_min_severity_ = prev;
  70. mock_clean_saved_logs();
  71. }
  72. /**
  73. * Clear all messages in mock_saved_logs()
  74. */
  75. void
  76. mock_clean_saved_logs(void)
  77. {
  78. if (!saved_logs)
  79. return;
  80. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  81. { tor_free(m->generated_msg); tor_free(m); });
  82. smartlist_free(saved_logs);
  83. saved_logs = NULL;
  84. }
  85. /**
  86. * Return a list of all the messages captured since the last
  87. * setup_[full_]capture_of_logs() call. Each log call is recorded as a
  88. * mock_saved_log_entry_t.
  89. */
  90. const smartlist_t *
  91. mock_saved_logs(void)
  92. {
  93. return saved_logs;
  94. }
  95. /**
  96. * Return true iff there is a message recorded by log capture
  97. * that is exactly equal to <b>msg</b>
  98. */
  99. int
  100. mock_saved_log_has_message(const char *msg)
  101. {
  102. if (saved_logs) {
  103. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  104. {
  105. if (msg && m->generated_msg &&
  106. !strcmp(msg, m->generated_msg)) {
  107. return 1;
  108. }
  109. });
  110. }
  111. return 0;
  112. }
  113. /**
  114. * Return true iff there is a message recorded by log capture
  115. * that contains <b>msg</b> as a substring.
  116. */
  117. int
  118. mock_saved_log_has_message_containing(const char *msg)
  119. {
  120. if (saved_logs) {
  121. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  122. {
  123. if (msg && m->generated_msg &&
  124. strstr(m->generated_msg, msg)) {
  125. return 1;
  126. }
  127. });
  128. }
  129. return 0;
  130. }
  131. /** Return true iff the saved logs have any messages with <b>severity</b> */
  132. int
  133. mock_saved_log_has_severity(int severity)
  134. {
  135. int has_sev = 0;
  136. if (saved_logs) {
  137. SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
  138. {
  139. if (m->severity == severity) {
  140. has_sev = 1;
  141. }
  142. });
  143. }
  144. return has_sev;
  145. }
  146. /** Return true iff the the saved logs have at lease one message */
  147. int
  148. mock_saved_log_has_entry(void)
  149. {
  150. if (saved_logs) {
  151. return smartlist_len(saved_logs) > 0;
  152. }
  153. return 0;
  154. }
  155. /* Replacement for logv: record the log message, and (maybe) send it
  156. * into the logging system again.
  157. */
  158. static void
  159. mock_saving_logv(int severity, log_domain_mask_t domain,
  160. const char *funcname, const char *suffix,
  161. const char *format, va_list ap)
  162. {
  163. char *buf = tor_malloc_zero(10240);
  164. int n;
  165. n = tor_vsnprintf(buf,10240,format,ap);
  166. tor_assert(n < 10240-1);
  167. buf[n]='\n';
  168. buf[n+1]='\0';
  169. if (echo_to_real_logs) {
  170. tor_log(severity, domain|LD_NO_MOCK, "%s", buf);
  171. }
  172. if (severity > record_logs_at_level) {
  173. tor_free(buf);
  174. return;
  175. }
  176. if (!saved_logs)
  177. saved_logs = smartlist_new();
  178. mock_saved_log_entry_t *e = tor_malloc_zero(sizeof(mock_saved_log_entry_t));
  179. e->severity = severity;
  180. e->funcname = funcname;
  181. e->suffix = suffix;
  182. e->format = format;
  183. e->generated_msg = tor_strdup(buf);
  184. tor_free(buf);
  185. smartlist_add(saved_logs, e);
  186. }
  187. void
  188. mock_dump_saved_logs(void)
  189. {
  190. if (saved_logs == NULL) {
  191. puts(" Captured logs: NULL");
  192. return;
  193. }
  194. puts(" Captured logs:");
  195. SMARTLIST_FOREACH_BEGIN(saved_logs, const mock_saved_log_entry_t *, m) {
  196. printf("% 5d. %s: %s\n", m_sl_idx + 1,
  197. log_level_to_string(m->severity),
  198. escaped(m->generated_msg));
  199. } SMARTLIST_FOREACH_END(m);
  200. }