2016-02-27 18:48:19 +01:00
|
|
|
/* Copyright (c) 2015-2016, The Tor Project, Inc. */
|
2015-10-02 13:13:58 +02:00
|
|
|
/* See LICENSE for licensing information */
|
2015-09-15 17:20:44 +02:00
|
|
|
#define LOG_PRIVATE
|
|
|
|
#include "torlog.h"
|
|
|
|
#include "log_test_helpers.h"
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* \file log_test_helpers.c
|
|
|
|
* \brief Code to check for expected log messages during testing.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void mock_saving_logv(int severity, log_domain_mask_t domain,
|
|
|
|
const char *funcname, const char *suffix,
|
|
|
|
const char *format, va_list ap)
|
|
|
|
CHECK_PRINTF(5, 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Smartlist of all the logs we've received since we last set up
|
|
|
|
* log capture.
|
|
|
|
*/
|
2015-09-15 17:20:44 +02:00
|
|
|
static smartlist_t *saved_logs = NULL;
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/** Boolean: should we also send messages to the test-runner? */
|
2016-08-31 18:51:22 +02:00
|
|
|
static int echo_to_real_logs = 1;
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* As setup_capture_of_logs, but do not relay log messages into the main
|
|
|
|
* logging system.
|
|
|
|
*
|
|
|
|
* Avoid using this function; use setup_capture_of_logs() instead if you
|
|
|
|
* can. If you must use this function, then make sure you detect any
|
|
|
|
* unexpected log messages, and treat them as test failures. */
|
2016-08-31 18:51:22 +02:00
|
|
|
int
|
|
|
|
setup_full_capture_of_logs(int new_level)
|
|
|
|
{
|
|
|
|
int result = setup_capture_of_logs(new_level);
|
|
|
|
echo_to_real_logs = 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* Temporarily capture all the messages logged at severity <b>new_level</b> or
|
|
|
|
* higher. Return the previous log level; you'll need to pass it into
|
|
|
|
* teardown_capture_of_logs().
|
|
|
|
*
|
|
|
|
* This function does not prevent messages from being sent to the main
|
|
|
|
* logging system.
|
|
|
|
*/
|
2015-09-15 17:20:44 +02:00
|
|
|
int
|
|
|
|
setup_capture_of_logs(int new_level)
|
|
|
|
{
|
|
|
|
int previous_log = log_global_min_severity_;
|
2016-08-31 19:03:59 +02:00
|
|
|
/* XXXX This can suppress, if logging is turned up high. Will fix. -NM*/
|
2015-09-15 17:20:44 +02:00
|
|
|
log_global_min_severity_ = new_level;
|
|
|
|
mock_clean_saved_logs();
|
2016-07-06 18:59:43 +02:00
|
|
|
saved_logs = smartlist_new();
|
2015-09-15 17:20:44 +02:00
|
|
|
MOCK(logv, mock_saving_logv);
|
2016-08-31 18:51:22 +02:00
|
|
|
echo_to_real_logs = 1;
|
2015-09-15 17:20:44 +02:00
|
|
|
return previous_log;
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* Undo setup_capture_of_logs().
|
|
|
|
*/
|
2015-09-15 17:20:44 +02:00
|
|
|
void
|
|
|
|
teardown_capture_of_logs(int prev)
|
|
|
|
{
|
|
|
|
UNMOCK(logv);
|
|
|
|
log_global_min_severity_ = prev;
|
|
|
|
mock_clean_saved_logs();
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* Clear all messages in mock_saved_logs()
|
|
|
|
*/
|
2015-09-15 17:20:44 +02:00
|
|
|
void
|
|
|
|
mock_clean_saved_logs(void)
|
|
|
|
{
|
|
|
|
if (!saved_logs)
|
|
|
|
return;
|
|
|
|
SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
|
|
|
|
{ tor_free(m->generated_msg); tor_free(m); });
|
|
|
|
smartlist_free(saved_logs);
|
|
|
|
saved_logs = NULL;
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* Return a list of all the messages captured since the last
|
|
|
|
* setup_[full_]capture_of_logs() call. Each log call is recorded as a
|
|
|
|
* mock_saved_log_entry_t.
|
|
|
|
*/
|
2015-09-15 17:20:44 +02:00
|
|
|
const smartlist_t *
|
|
|
|
mock_saved_logs(void)
|
|
|
|
{
|
|
|
|
return saved_logs;
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* Return true iff there is a message recorded by log capture
|
|
|
|
* that is exactly equal to <b>msg</b>
|
|
|
|
*/
|
2016-01-29 17:38:54 +01:00
|
|
|
int
|
|
|
|
mock_saved_log_has_message(const char *msg)
|
|
|
|
{
|
|
|
|
if (saved_logs) {
|
|
|
|
SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
|
|
|
|
{
|
|
|
|
if (msg && m->generated_msg &&
|
|
|
|
!strcmp(msg, m->generated_msg)) {
|
2016-08-31 19:03:59 +02:00
|
|
|
return 1;
|
2016-01-29 17:38:54 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
return 0;
|
2016-01-29 17:38:54 +01:00
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/**
|
|
|
|
* Return true iff there is a message recorded by log capture
|
|
|
|
* that contains <b>msg</b> as a substring.
|
|
|
|
*/
|
2016-08-31 17:35:12 +02:00
|
|
|
int
|
|
|
|
mock_saved_log_has_message_containing(const char *msg)
|
|
|
|
{
|
|
|
|
if (saved_logs) {
|
|
|
|
SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
|
|
|
|
{
|
|
|
|
if (msg && m->generated_msg &&
|
|
|
|
strstr(m->generated_msg, msg)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/** Return true iff the saved logs have any messages with <b>severity</b> */
|
2016-02-01 00:02:04 +01:00
|
|
|
int
|
|
|
|
mock_saved_log_has_severity(int severity)
|
|
|
|
{
|
|
|
|
int has_sev = 0;
|
|
|
|
if (saved_logs) {
|
|
|
|
SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
|
|
|
|
{
|
|
|
|
if (m->severity == severity) {
|
|
|
|
has_sev = 1;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return has_sev;
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/** Return true iff the the saved logs have at lease one message */
|
2016-02-01 00:02:04 +01:00
|
|
|
int
|
|
|
|
mock_saved_log_has_entry(void)
|
|
|
|
{
|
|
|
|
if (saved_logs) {
|
|
|
|
return smartlist_len(saved_logs) > 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-08-31 19:03:59 +02:00
|
|
|
/* Replacement for logv: record the log message, and (maybe) send it
|
|
|
|
* into the logging system again.
|
|
|
|
*/
|
|
|
|
static void
|
2015-10-02 13:03:43 +02:00
|
|
|
mock_saving_logv(int severity, log_domain_mask_t domain,
|
|
|
|
const char *funcname, const char *suffix,
|
|
|
|
const char *format, va_list ap)
|
2015-09-15 17:20:44 +02:00
|
|
|
{
|
|
|
|
char *buf = tor_malloc_zero(10240);
|
|
|
|
int n;
|
|
|
|
n = tor_vsnprintf(buf,10240,format,ap);
|
2015-10-02 13:03:43 +02:00
|
|
|
tor_assert(n < 10240-1);
|
2015-09-15 17:20:44 +02:00
|
|
|
buf[n]='\n';
|
|
|
|
buf[n+1]='\0';
|
|
|
|
|
|
|
|
mock_saved_log_entry_t *e = tor_malloc_zero(sizeof(mock_saved_log_entry_t));
|
|
|
|
e->severity = severity;
|
|
|
|
e->funcname = funcname;
|
|
|
|
e->suffix = suffix;
|
|
|
|
e->format = format;
|
2015-10-02 13:03:43 +02:00
|
|
|
e->generated_msg = tor_strdup(buf);
|
|
|
|
tor_free(buf);
|
2015-09-15 17:20:44 +02:00
|
|
|
|
|
|
|
if (!saved_logs)
|
|
|
|
saved_logs = smartlist_new();
|
|
|
|
smartlist_add(saved_logs, e);
|
2016-08-31 18:51:22 +02:00
|
|
|
|
|
|
|
if (echo_to_real_logs) {
|
|
|
|
tor_log(severity, domain|LD_NO_MOCK, "%s", e->generated_msg);
|
|
|
|
}
|
2015-09-15 17:20:44 +02:00
|
|
|
}
|
2016-01-15 16:57:03 +01:00
|
|
|
|