LCOV - code coverage report
Current view: top level - test - log_test_helpers.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 70 81 86.4 %
Date: 2021-11-24 03:28:48 Functions: 12 13 92.3 %

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

Generated by: LCOV version 1.14