log_test_helpers.c 4.8 KB

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