mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-14 07:03:44 +01:00
Start of a unit test for options_validate.
I added this so I could write a unit test for ServerTransportOptions, but it incidentally exercises the succeed-on-defaults case of options_validate too.
This commit is contained in:
parent
abedd35de0
commit
f45e1fbd5b
@ -9,6 +9,7 @@
|
|||||||
* \brief Code to parse and interpret configuration files.
|
* \brief Code to parse and interpret configuration files.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#define CONFIG_PRIVATE
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
#include "addressmap.h"
|
#include "addressmap.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
@ -509,10 +510,6 @@ static const config_var_t testing_tor_network_defaults[] = {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static char *get_windows_conf_root(void);
|
static char *get_windows_conf_root(void);
|
||||||
#endif
|
#endif
|
||||||
static int options_validate(or_options_t *old_options,
|
|
||||||
or_options_t *options,
|
|
||||||
or_options_t *default_options,
|
|
||||||
int from_setconf, char **msg);
|
|
||||||
static int options_act_reversible(const or_options_t *old_options, char **msg);
|
static int options_act_reversible(const or_options_t *old_options, char **msg);
|
||||||
static int options_act(const or_options_t *old_options);
|
static int options_act(const or_options_t *old_options);
|
||||||
static int options_transition_allowed(const or_options_t *old,
|
static int options_transition_allowed(const or_options_t *old,
|
||||||
@ -556,7 +553,7 @@ static void config_maybe_load_geoip_files_(const or_options_t *options,
|
|||||||
#define OR_OPTIONS_MAGIC 9090909
|
#define OR_OPTIONS_MAGIC 9090909
|
||||||
|
|
||||||
/** Configuration format for or_options_t. */
|
/** Configuration format for or_options_t. */
|
||||||
static config_format_t options_format = {
|
STATIC config_format_t options_format = {
|
||||||
sizeof(or_options_t),
|
sizeof(or_options_t),
|
||||||
OR_OPTIONS_MAGIC,
|
OR_OPTIONS_MAGIC,
|
||||||
STRUCT_OFFSET(or_options_t, magic_),
|
STRUCT_OFFSET(or_options_t, magic_),
|
||||||
@ -712,7 +709,7 @@ get_short_version(void)
|
|||||||
|
|
||||||
/** Release additional memory allocated in options
|
/** Release additional memory allocated in options
|
||||||
*/
|
*/
|
||||||
static void
|
STATIC void
|
||||||
or_options_free(or_options_t *options)
|
or_options_free(or_options_t *options)
|
||||||
{
|
{
|
||||||
if (!options)
|
if (!options)
|
||||||
@ -2349,7 +2346,7 @@ compute_publishserverdescriptor(or_options_t *options)
|
|||||||
* Log line should stay empty. If it's 0, then give us a default log
|
* Log line should stay empty. If it's 0, then give us a default log
|
||||||
* if there are no logs defined.
|
* if there are no logs defined.
|
||||||
*/
|
*/
|
||||||
static int
|
STATIC int
|
||||||
options_validate(or_options_t *old_options, or_options_t *options,
|
options_validate(or_options_t *old_options, or_options_t *options,
|
||||||
or_options_t *default_options, int from_setconf, char **msg)
|
or_options_t *default_options, int from_setconf, char **msg)
|
||||||
{
|
{
|
||||||
|
@ -116,5 +116,17 @@ smartlist_t *get_options_from_transport_options_line(const char *line,
|
|||||||
const char *transport);
|
const char *transport);
|
||||||
smartlist_t *get_options_for_server_transport(const char *transport);
|
smartlist_t *get_options_for_server_transport(const char *transport);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PRIVATE
|
||||||
|
#ifdef TOR_UNIT_TESTS
|
||||||
|
extern struct config_format_t options_format;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STATIC void or_options_free(or_options_t *options);
|
||||||
|
STATIC int options_validate(or_options_t *old_options,
|
||||||
|
or_options_t *options,
|
||||||
|
or_options_t *default_options,
|
||||||
|
int from_setconf, char **msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ typedef int (*validate_fn_t)(void*,void*,int,char**);
|
|||||||
/** Information on the keys, value types, key-to-struct-member mappings,
|
/** Information on the keys, value types, key-to-struct-member mappings,
|
||||||
* variable descriptions, validation functions, and abbreviations for a
|
* variable descriptions, validation functions, and abbreviations for a
|
||||||
* configuration or storage format. */
|
* configuration or storage format. */
|
||||||
typedef struct {
|
typedef struct config_format_t {
|
||||||
size_t size; /**< Size of the struct that everything gets parsed into. */
|
size_t size; /**< Size of the struct that everything gets parsed into. */
|
||||||
uint32_t magic; /**< Required 'magic value' to make sure we have a struct
|
uint32_t magic; /**< Required 'magic value' to make sure we have a struct
|
||||||
* of the right type. */
|
* of the right type. */
|
||||||
|
@ -27,6 +27,7 @@ src_test_test_SOURCES = \
|
|||||||
src/test/test_dir.c \
|
src/test/test_dir.c \
|
||||||
src/test/test_introduce.c \
|
src/test/test_introduce.c \
|
||||||
src/test/test_microdesc.c \
|
src/test/test_microdesc.c \
|
||||||
|
src/test/test_options.c \
|
||||||
src/test/test_pt.c \
|
src/test/test_pt.c \
|
||||||
src/test/test_replay.c \
|
src/test/test_replay.c \
|
||||||
src/test/test_util.c \
|
src/test/test_util.c \
|
||||||
|
@ -2134,6 +2134,7 @@ extern struct testcase_t replaycache_tests[];
|
|||||||
extern struct testcase_t cell_format_tests[];
|
extern struct testcase_t cell_format_tests[];
|
||||||
extern struct testcase_t circuitlist_tests[];
|
extern struct testcase_t circuitlist_tests[];
|
||||||
extern struct testcase_t cell_queue_tests[];
|
extern struct testcase_t cell_queue_tests[];
|
||||||
|
extern struct testcase_t options_tests[];
|
||||||
|
|
||||||
static struct testgroup_t testgroups[] = {
|
static struct testgroup_t testgroups[] = {
|
||||||
{ "", test_array },
|
{ "", test_array },
|
||||||
@ -2151,6 +2152,7 @@ static struct testgroup_t testgroups[] = {
|
|||||||
{ "replaycache/", replaycache_tests },
|
{ "replaycache/", replaycache_tests },
|
||||||
{ "introduce/", introduce_tests },
|
{ "introduce/", introduce_tests },
|
||||||
{ "circuitlist/", circuitlist_tests },
|
{ "circuitlist/", circuitlist_tests },
|
||||||
|
{ "options/", options_tests },
|
||||||
END_OF_GROUPS
|
END_OF_GROUPS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
169
src/test/test_options.c
Normal file
169
src/test/test_options.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/* Copyright (c) 2001-2004, Roger Dingledine.
|
||||||
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
|
* Copyright (c) 2007-2013, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#define CONFIG_PRIVATE
|
||||||
|
#include "or.h"
|
||||||
|
#include "confparse.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int severity;
|
||||||
|
uint32_t domain;
|
||||||
|
char *msg;
|
||||||
|
} logmsg_t;
|
||||||
|
|
||||||
|
static smartlist_t *messages = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
log_cback(int severity, uint32_t domain, const char *msg)
|
||||||
|
{
|
||||||
|
logmsg_t *x = tor_malloc(sizeof(*x));
|
||||||
|
x->severity = severity;
|
||||||
|
x->domain = domain;
|
||||||
|
x->msg = tor_strdup(msg);
|
||||||
|
if (!messages)
|
||||||
|
messages = smartlist_new();
|
||||||
|
smartlist_add(messages, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_log_callback(void)
|
||||||
|
{
|
||||||
|
log_severity_list_t lst;
|
||||||
|
memset(&lst, 0, sizeof(lst));
|
||||||
|
lst.masks[LOG_ERR - LOG_ERR] = ~0;
|
||||||
|
lst.masks[LOG_WARN - LOG_ERR] = ~0;
|
||||||
|
lst.masks[LOG_NOTICE - LOG_ERR] = ~0;
|
||||||
|
add_callback_log(&lst, log_cback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
dump_logs(void)
|
||||||
|
{
|
||||||
|
smartlist_t *msgs;
|
||||||
|
char *out;
|
||||||
|
if (! messages)
|
||||||
|
return tor_strdup("");
|
||||||
|
msgs = smartlist_new();
|
||||||
|
SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, x) {
|
||||||
|
smartlist_add_asprintf(msgs, "[%s] %s",
|
||||||
|
log_level_to_string(x->severity), x->msg);
|
||||||
|
} SMARTLIST_FOREACH_END(x);
|
||||||
|
out = smartlist_join_strings(msgs, "", 0, NULL);
|
||||||
|
SMARTLIST_FOREACH(msgs, char *, cp, tor_free(cp));
|
||||||
|
smartlist_free(msgs);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_log_messages(void)
|
||||||
|
{
|
||||||
|
if (!messages)
|
||||||
|
return;
|
||||||
|
SMARTLIST_FOREACH(messages, logmsg_t *, m,
|
||||||
|
{ tor_free(m->msg); tor_free(m); });
|
||||||
|
smartlist_free(messages);
|
||||||
|
messages = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_options_validate_impl(const char *configuration,
|
||||||
|
const char *expect_errmsg,
|
||||||
|
int expect_log_severity,
|
||||||
|
const char *expect_log)
|
||||||
|
{
|
||||||
|
or_options_t *opt = options_new();
|
||||||
|
or_options_t *dflt;
|
||||||
|
config_line_t *cl=NULL;
|
||||||
|
char *msg=NULL;
|
||||||
|
int r;
|
||||||
|
opt->command = CMD_RUN_TOR;
|
||||||
|
options_init(opt);
|
||||||
|
|
||||||
|
dflt = config_dup(&options_format, opt);
|
||||||
|
clear_log_messages();
|
||||||
|
|
||||||
|
r = config_get_lines(configuration, &cl, 1);
|
||||||
|
tt_int_op(r, ==, 0);
|
||||||
|
|
||||||
|
r = config_assign(&options_format, opt, cl, 0, 0, &msg);
|
||||||
|
tt_int_op(r, ==, 0);
|
||||||
|
|
||||||
|
r = options_validate(NULL, opt, dflt, 0, &msg);
|
||||||
|
if (expect_errmsg && !msg) {
|
||||||
|
TT_DIE(("Expected error message <%s> from <%s>, but got none.",
|
||||||
|
expect_errmsg, configuration));
|
||||||
|
} else if (expect_errmsg && !strstr(msg, expect_errmsg)) {
|
||||||
|
TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.",
|
||||||
|
expect_errmsg, configuration, msg));
|
||||||
|
} else if (!expect_errmsg && msg) {
|
||||||
|
TT_DIE(("Expected no error message from <%s> but got <%s>.",
|
||||||
|
configuration, msg));
|
||||||
|
}
|
||||||
|
tt_int_op((r == 0), ==, (msg == NULL));
|
||||||
|
|
||||||
|
if (expect_log) {
|
||||||
|
int found = 0;
|
||||||
|
if (messages) {
|
||||||
|
SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, m) {
|
||||||
|
if (m->severity == expect_log_severity &&
|
||||||
|
strstr(m->msg, expect_log)) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} SMARTLIST_FOREACH_END(m);
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
tor_free(msg);
|
||||||
|
msg = dump_logs();
|
||||||
|
TT_DIE(("Expected log message [%s] %s from <%s>, but got <%s>.",
|
||||||
|
log_level_to_string(expect_log_severity), expect_log,
|
||||||
|
configuration, msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
config_free_lines(cl);
|
||||||
|
or_options_free(opt);
|
||||||
|
or_options_free(dflt);
|
||||||
|
tor_free(msg);
|
||||||
|
clear_log_messages();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WANT_ERR(config, msg) \
|
||||||
|
test_options_validate_impl((config), (msg), 0, NULL)
|
||||||
|
#define WANT_LOG(config, severity, msg) \
|
||||||
|
test_options_validate_impl((config), NULL, (severity), (msg))
|
||||||
|
#define WANT_ERR_LOG(config, msg, severity, logmsg) \
|
||||||
|
test_options_validate_impl((config), (msg), (severity), (logmsg))
|
||||||
|
#define OK(config) \
|
||||||
|
test_options_validate_impl((config), NULL, 0, NULL)
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_options_validate(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
setup_log_callback();
|
||||||
|
|
||||||
|
WANT_ERR_LOG("ServerTransportOptions trebuchet",
|
||||||
|
"ServerTransportOptions did not parse",
|
||||||
|
LOG_WARN, "Too few arguments");
|
||||||
|
OK("ServerTransportOptions trebuchet sling=snappy");
|
||||||
|
OK("ServerTransportOptions trebuchet sling=");
|
||||||
|
WANT_ERR_LOG("ServerTransportOptions trebuchet slingsnappy",
|
||||||
|
"ServerTransportOptions did not parse",
|
||||||
|
LOG_WARN, "\"slingsnappy\" is not a k=v");
|
||||||
|
|
||||||
|
// done:
|
||||||
|
clear_log_messages();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct testcase_t options_tests[] = {
|
||||||
|
{ "validate", test_options_validate, TT_FORK, NULL, NULL },
|
||||||
|
END_OF_TESTCASES
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user