mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Add tests for compat_libevent
This commit is contained in:
parent
a444b11323
commit
9985a62a67
@ -11,6 +11,7 @@
|
||||
|
||||
#include "orconfig.h"
|
||||
#include "compat.h"
|
||||
#define COMPAT_LIBEVENT_PRIVATE
|
||||
#include "compat_libevent.h"
|
||||
|
||||
#include "crypto.h"
|
||||
@ -28,39 +29,11 @@
|
||||
#include <event.h>
|
||||
#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. */
|
||||
static const char *suppress_msg = NULL;
|
||||
/** Callback function passed to event_set_log() so we can intercept
|
||||
* log messages from libevent. */
|
||||
static void
|
||||
STATIC void
|
||||
libevent_logging_callback(int severity, const char *msg)
|
||||
{
|
||||
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
|
||||
* string <b>v</b>. If the version is very new or uses an unrecognized
|
||||
* version, format, return LE_OTHER. */
|
||||
static le_version_t
|
||||
STATIC le_version_t
|
||||
tor_decode_libevent_version(const char *v)
|
||||
{
|
||||
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
|
||||
* compatible. Two different versions with the same numbers have a decent
|
||||
* chance of binary compatibility.*/
|
||||
static int
|
||||
STATIC int
|
||||
le_versions_compatibility(le_version_t v)
|
||||
{
|
||||
if (v == LE_OTHER)
|
||||
@ -653,4 +626,3 @@ tor_gettimeofday_cached_monotonic(struct timeval *tv)
|
||||
memcpy(&last_tv, tv, sizeof(struct timeval));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,5 +91,43 @@ void tor_gettimeofday_cache_set(const struct timeval *tv);
|
||||
#endif
|
||||
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
|
||||
|
@ -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.
|
||||
|
||||
src_test_test_SOURCES = \
|
||||
src/test/log_test_helpers.c \
|
||||
src/test/test.c \
|
||||
src/test/test_accounting.c \
|
||||
src/test/test_addr.c \
|
||||
@ -63,6 +64,7 @@ src_test_test_SOURCES = \
|
||||
src/test/test_checkdir.c \
|
||||
src/test/test_circuitlist.c \
|
||||
src/test/test_circuitmux.c \
|
||||
src/test/test_compat_libevent.c \
|
||||
src/test/test_config.c \
|
||||
src/test/test_containers.c \
|
||||
src/test/test_controller.c \
|
||||
|
95
src/test/log_test_helpers.c
Normal file
95
src/test/log_test_helpers.c
Normal 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);
|
||||
}
|
27
src/test/log_test_helpers.h
Normal file
27
src/test/log_test_helpers.h
Normal 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
|
@ -1125,6 +1125,7 @@ extern struct testcase_t channeltls_tests[];
|
||||
extern struct testcase_t checkdir_tests[];
|
||||
extern struct testcase_t circuitlist_tests[];
|
||||
extern struct testcase_t circuitmux_tests[];
|
||||
extern struct testcase_t compat_libevent_tests[];
|
||||
extern struct testcase_t config_tests[];
|
||||
extern struct testcase_t container_tests[];
|
||||
extern struct testcase_t controller_tests[];
|
||||
@ -1173,6 +1174,7 @@ struct testgroup_t testgroups[] = {
|
||||
{ "checkdir/", checkdir_tests },
|
||||
{ "circuitlist/", circuitlist_tests },
|
||||
{ "circuitmux/", circuitmux_tests },
|
||||
{ "compat/libevent/", compat_libevent_tests },
|
||||
{ "config/", config_tests },
|
||||
{ "container/", container_tests },
|
||||
{ "control/", controller_tests },
|
||||
@ -1208,4 +1210,3 @@ struct testgroup_t testgroups[] = {
|
||||
{ "dns/", dns_tests },
|
||||
END_OF_GROUPS
|
||||
};
|
||||
|
||||
|
214
src/test/test_compat_libevent.c
Normal file
214
src/test/test_compat_libevent.c
Normal 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
|
||||
};
|
Loading…
Reference in New Issue
Block a user