Add tests for compat_libevent

This commit is contained in:
Ola Bini 2015-09-15 17:20:44 +02:00
parent a444b11323
commit 9985a62a67
No known key found for this signature in database
GPG Key ID: 465757AF3914B4B7
7 changed files with 382 additions and 33 deletions

View File

@ -11,6 +11,7 @@
#include "orconfig.h" #include "orconfig.h"
#include "compat.h" #include "compat.h"
#define COMPAT_LIBEVENT_PRIVATE
#include "compat_libevent.h" #include "compat_libevent.h"
#include "crypto.h" #include "crypto.h"
@ -28,39 +29,11 @@
#include <event.h> #include <event.h>
#endif #endif
/** A number representing a version of Libevent.
This is a 4-byte number, with the first three bytes representing the
major, minor, and patchlevel respectively of the library. The fourth
byte is unused.
This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
to be equivalent to 1.0.1, and so on.
*/
typedef uint32_t le_version_t;
/** @{ */
/** Macros: returns the number of a libevent version as a le_version_t */
#define V(major, minor, patch) \
(((major) << 24) | ((minor) << 16) | ((patch) << 8))
#define V_OLD(major, minor, patch) \
V((major), (minor), (patch)-'a'+1)
/** @} */
/** Represetns a version of libevent so old we can't figure out what version
* it is. */
#define LE_OLD V(0,0,0)
/** Represents a version of libevent so weird we can't figure out what version
* it is. */
#define LE_OTHER V(0,0,99)
/** A string which, if it appears in a libevent log, should be ignored. */ /** A string which, if it appears in a libevent log, should be ignored. */
static const char *suppress_msg = NULL; static const char *suppress_msg = NULL;
/** Callback function passed to event_set_log() so we can intercept /** Callback function passed to event_set_log() so we can intercept
* log messages from libevent. */ * log messages from libevent. */
static void STATIC void
libevent_logging_callback(int severity, const char *msg) libevent_logging_callback(int severity, const char *msg)
{ {
char buf[1024]; char buf[1024];
@ -291,7 +264,7 @@ tor_libevent_get_method(void)
/** Return the le_version_t for the version of libevent specified in the /** Return the le_version_t for the version of libevent specified in the
* string <b>v</b>. If the version is very new or uses an unrecognized * string <b>v</b>. If the version is very new or uses an unrecognized
* version, format, return LE_OTHER. */ * version, format, return LE_OTHER. */
static le_version_t STATIC le_version_t
tor_decode_libevent_version(const char *v) tor_decode_libevent_version(const char *v)
{ {
unsigned major, minor, patchlevel; unsigned major, minor, patchlevel;
@ -322,7 +295,7 @@ tor_decode_libevent_version(const char *v)
* Two different versions with different numbers are sure not to be binary * Two different versions with different numbers are sure not to be binary
* compatible. Two different versions with the same numbers have a decent * compatible. Two different versions with the same numbers have a decent
* chance of binary compatibility.*/ * chance of binary compatibility.*/
static int STATIC int
le_versions_compatibility(le_version_t v) le_versions_compatibility(le_version_t v)
{ {
if (v == LE_OTHER) if (v == LE_OTHER)
@ -653,4 +626,3 @@ tor_gettimeofday_cached_monotonic(struct timeval *tv)
memcpy(&last_tv, tv, sizeof(struct timeval)); memcpy(&last_tv, tv, sizeof(struct timeval));
} }
} }

View File

@ -91,5 +91,43 @@ void tor_gettimeofday_cache_set(const struct timeval *tv);
#endif #endif
void tor_gettimeofday_cached_monotonic(struct timeval *tv); void tor_gettimeofday_cached_monotonic(struct timeval *tv);
#ifdef COMPAT_LIBEVENT_PRIVATE
/** A number representing a version of Libevent.
This is a 4-byte number, with the first three bytes representing the
major, minor, and patchlevel respectively of the library. The fourth
byte is unused.
This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
to be equivalent to 1.0.1, and so on.
*/
typedef uint32_t le_version_t;
/** @{ */
/** Macros: returns the number of a libevent version as a le_version_t */
#define V(major, minor, patch) \
(((major) << 24) | ((minor) << 16) | ((patch) << 8))
#define V_OLD(major, minor, patch) \
V((major), (minor), (patch)-'a'+1)
/** @} */
/** Represetns a version of libevent so old we can't figure out what version
* it is. */
#define LE_OLD V(0,0,0)
/** Represents a version of libevent so weird we can't figure out what version
* it is. */
#define LE_OTHER V(0,0,99)
STATIC void
libevent_logging_callback(int severity, const char *msg);
STATIC le_version_t
tor_decode_libevent_version(const char *v);
STATIC int
le_versions_compatibility(le_version_t v);
#endif #endif
#endif

View File

@ -51,6 +51,7 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# matters a lot there, and is quite hard to debug if you forget to do it. # matters a lot there, and is quite hard to debug if you forget to do it.
src_test_test_SOURCES = \ src_test_test_SOURCES = \
src/test/log_test_helpers.c \
src/test/test.c \ src/test/test.c \
src/test/test_accounting.c \ src/test/test_accounting.c \
src/test/test_addr.c \ src/test/test_addr.c \
@ -63,6 +64,7 @@ src_test_test_SOURCES = \
src/test/test_checkdir.c \ src/test/test_checkdir.c \
src/test/test_circuitlist.c \ src/test/test_circuitlist.c \
src/test/test_circuitmux.c \ src/test/test_circuitmux.c \
src/test/test_compat_libevent.c \
src/test/test_config.c \ src/test/test_config.c \
src/test/test_containers.c \ src/test/test_containers.c \
src/test/test_controller.c \ src/test/test_controller.c \

View File

@ -0,0 +1,95 @@
#define LOG_PRIVATE
#include "torlog.h"
#include "log_test_helpers.h"
static smartlist_t *saved_logs = NULL;
int
setup_capture_of_logs(int new_level)
{
int previous_log = log_global_min_severity_;
log_global_min_severity_ = new_level;
mock_clean_saved_logs();
MOCK(logv, mock_saving_logv);
return previous_log;
}
void
teardown_capture_of_logs(int prev)
{
UNMOCK(logv);
log_global_min_severity_ = prev;
mock_clean_saved_logs();
}
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;
}
char *
mock_saved_log_at(int ix)
{
int saved_log_count = mock_saved_log_number();
if(ix < 0) {
ix = saved_log_count + ix;
}
if (saved_log_count <= ix)
return "";
return ((mock_saved_log_entry_t *)smartlist_get(saved_logs, ix))->generated_msg;
}
int
mock_saved_severity_at(int ix)
{
int saved_log_count = mock_saved_log_number();
if(ix < 0) {
ix = saved_log_count + ix;
}
if (saved_log_count <= ix)
return -1;
return ((mock_saved_log_entry_t *)smartlist_get(saved_logs, ix))->severity;
}
int
mock_saved_log_number(void)
{
if (!saved_logs)
return 0;
return smartlist_len(saved_logs);
}
const smartlist_t *
mock_saved_logs(void)
{
return saved_logs;
}
void
mock_saving_logv(int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap)
{
char *buf = tor_malloc_zero(10240);
int n;
n = tor_vsnprintf(buf,10240,format,ap);
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;
e->generated_msg = buf;
if (!saved_logs)
saved_logs = smartlist_new();
smartlist_add(saved_logs, e);
}

View File

@ -0,0 +1,27 @@
/* Copyright (c) 2014-2015, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "or.h"
#ifndef TOR_LOG_TEST_HELPERS_H
#define TOR_LOG_TEST_HELPERS_H
typedef struct mock_saved_log_entry_t {
int severity;
const char *funcname;
const char *suffix;
const char *format;
char *generated_msg;
struct mock_saved_log_entry_t *next;
} mock_saved_log_entry_t;
void mock_saving_logv(int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap);
void mock_clean_saved_logs(void);
const smartlist_t *mock_saved_logs(void);
int setup_capture_of_logs(int new_level);
void teardown_capture_of_logs(int prev);
char *mock_saved_log_at(int ix);
int mock_saved_severity_at(int ix);
int mock_saved_log_number(void);
#endif

View File

@ -1125,6 +1125,7 @@ extern struct testcase_t channeltls_tests[];
extern struct testcase_t checkdir_tests[]; extern struct testcase_t checkdir_tests[];
extern struct testcase_t circuitlist_tests[]; extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[]; extern struct testcase_t circuitmux_tests[];
extern struct testcase_t compat_libevent_tests[];
extern struct testcase_t config_tests[]; extern struct testcase_t config_tests[];
extern struct testcase_t container_tests[]; extern struct testcase_t container_tests[];
extern struct testcase_t controller_tests[]; extern struct testcase_t controller_tests[];
@ -1173,6 +1174,7 @@ struct testgroup_t testgroups[] = {
{ "checkdir/", checkdir_tests }, { "checkdir/", checkdir_tests },
{ "circuitlist/", circuitlist_tests }, { "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests }, { "circuitmux/", circuitmux_tests },
{ "compat/libevent/", compat_libevent_tests },
{ "config/", config_tests }, { "config/", config_tests },
{ "container/", container_tests }, { "container/", container_tests },
{ "control/", controller_tests }, { "control/", controller_tests },
@ -1208,4 +1210,3 @@ struct testgroup_t testgroups[] = {
{ "dns/", dns_tests }, { "dns/", dns_tests },
END_OF_GROUPS END_OF_GROUPS
}; };

View File

@ -0,0 +1,214 @@
/* Copyright (c) 2010-2015, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define COMPAT_LIBEVENT_PRIVATE
#include "orconfig.h"
#include "or.h"
#include "test.h"
#include "compat_libevent.h"
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
#include <event2/thread.h>
#ifdef USE_BUFFEREVENTS
#include <event2/bufferevent.h>
#endif
#else
#include <event.h>
#endif
#include "log_test_helpers.h"
#define NS_MODULE compat_libevent
static void
test_compat_libevent_logging_callback(void *ignored)
{
(void)ignored;
int previous_log = setup_capture_of_logs(LOG_DEBUG);
libevent_logging_callback(_EVENT_LOG_DEBUG, "hello world");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Message from libevent: hello world\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_DEBUG);
mock_clean_saved_logs();
libevent_logging_callback(_EVENT_LOG_MSG, "hello world another time");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Message from libevent: hello world another time\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
mock_clean_saved_logs();
libevent_logging_callback(_EVENT_LOG_WARN, "hello world a third time");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Warning from libevent: hello world a third time\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
mock_clean_saved_logs();
libevent_logging_callback(_EVENT_LOG_ERR, "hello world a fourth time");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Error from libevent: hello world a fourth time\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_ERR);
mock_clean_saved_logs();
libevent_logging_callback(42, "hello world a fifth time");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Message [42] from libevent: hello world a fifth time\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
mock_clean_saved_logs();
libevent_logging_callback(_EVENT_LOG_DEBUG, "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Message from libevent: 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_DEBUG);
mock_clean_saved_logs();
libevent_logging_callback(42, "xxx\n");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Message [42] from libevent: xxx\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
suppress_libevent_log_msg("something");
mock_clean_saved_logs();
libevent_logging_callback(_EVENT_LOG_MSG, "hello there");
tt_int_op(mock_saved_log_number(), OP_EQ, 1);
tt_str_op(mock_saved_log_at(0), OP_EQ, "Message from libevent: hello there\n");
tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
mock_clean_saved_logs();
libevent_logging_callback(_EVENT_LOG_MSG, "hello there something else");
tt_int_op(mock_saved_log_number(), OP_EQ, 0);
// No way of verifying the result of this, it seems =/
configure_libevent_logging();
done:
suppress_libevent_log_msg(NULL);
teardown_capture_of_logs(previous_log);
}
static void
test_compat_libevent_le_versions_compatibility(void *ignored)
{
(void)ignored;
int res;
res = le_versions_compatibility(LE_OTHER);
tt_int_op(res, OP_EQ, 0);
res = le_versions_compatibility(V_OLD(0,9,'c'));
tt_int_op(res, OP_EQ, 1);
res = le_versions_compatibility(V(1,3,98));
tt_int_op(res, OP_EQ, 2);
res = le_versions_compatibility(V(1,4,98));
tt_int_op(res, OP_EQ, 3);
res = le_versions_compatibility(V(1,5,0));
tt_int_op(res, OP_EQ, 4);
res = le_versions_compatibility(V(2,0,0));
tt_int_op(res, OP_EQ, 4);
res = le_versions_compatibility(V(2,0,2));
tt_int_op(res, OP_EQ, 5);
done:
(void)0;
}
static void
test_compat_libevent_tor_decode_libevent_version(void *ignored)
{
(void)ignored;
le_version_t res;
res = tor_decode_libevent_version("SOMETHING WRONG");
tt_int_op(res, OP_EQ, LE_OTHER);
res = tor_decode_libevent_version("1.4.11");
tt_int_op(res, OP_EQ, V(1,4,11));
res = tor_decode_libevent_version("1.4.12b-stable");
tt_int_op(res, OP_EQ, V(1,4,12));
res = tor_decode_libevent_version("1.4.17b_stable");
tt_int_op(res, OP_EQ, V(1,4,17));
res = tor_decode_libevent_version("1.4.12!stable");
tt_int_op(res, OP_EQ, LE_OTHER);
res = tor_decode_libevent_version("1.4.12b!stable");
tt_int_op(res, OP_EQ, LE_OTHER);
res = tor_decode_libevent_version("1.4.13-");
tt_int_op(res, OP_EQ, V(1,4,13));
res = tor_decode_libevent_version("1.4.14_");
tt_int_op(res, OP_EQ, V(1,4,14));
res = tor_decode_libevent_version("1.4.15c-");
tt_int_op(res, OP_EQ, V(1,4,15));
res = tor_decode_libevent_version("1.4.16c_");
tt_int_op(res, OP_EQ, V(1,4,16));
res = tor_decode_libevent_version("1.4.17-s");
tt_int_op(res, OP_EQ, V(1,4,17));
res = tor_decode_libevent_version("1.5");
tt_int_op(res, OP_EQ, V(1,5,0));
res = tor_decode_libevent_version("1.2");
tt_int_op(res, OP_EQ, V(1,2,0));
res = tor_decode_libevent_version("1.2-");
tt_int_op(res, OP_EQ, LE_OTHER);
res = tor_decode_libevent_version("1.6e");
tt_int_op(res, OP_EQ, V_OLD(1,6,'e'));
done:
(void)0;
}
#if defined(LIBEVENT_VERSION)
#define HEADER_VERSION LIBEVENT_VERSION
#elif defined(_EVENT_VERSION)
#define HEADER_VERSION _EVENT_VERSION
#endif
static void
test_compat_libevent_header_version(void *ignored)
{
(void)ignored;
const char *res;
res = tor_libevent_get_header_version_str();
tt_str_op(res, OP_EQ, HEADER_VERSION);
done:
(void)0;
}
struct testcase_t compat_libevent_tests[] = {
{ "logging_callback", test_compat_libevent_logging_callback, TT_FORK, NULL, NULL },
{ "le_versions_compatibility", test_compat_libevent_le_versions_compatibility, 0, NULL, NULL },
{ "tor_decode_libevent_version", test_compat_libevent_tor_decode_libevent_version, 0, NULL, NULL },
{ "header_version", test_compat_libevent_header_version, 0, NULL, NULL },
END_OF_TESTCASES
};