autotrust test routines.

git-svn-id: file:///svn/unbound/trunk@1771 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards
2009-08-24 14:40:25 +00:00
parent 28be658942
commit 6f1f6dafb5
16 changed files with 527 additions and 113 deletions
+63
View File
@@ -51,6 +51,7 @@
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/config_file.h"
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "testcode/replay.h"
@@ -76,6 +77,18 @@ timeval_add(struct timeval* d, const struct timeval* add)
#endif
}
void
fake_temp_file(const char* adj, const char* id, char* buf, size_t len)
{
#ifdef USE_WINSOCK
snprintf(buf, len, "testbound_%u%s%s.tmp",
(unsigned)getpid(), adj, id);
#else
snprintf(buf, len, "/tmp/testbound_%u%s%s.tmp",
(unsigned)getpid(), adj, id);
#endif
}
void
fake_event_init(struct replay_scenario* scen)
{
@@ -116,6 +129,7 @@ repevt_string(enum replay_event_type t)
case repevt_time_passes: return "TIME_PASSES";
case repevt_back_reply: return "REPLY";
case repevt_back_query: return "CHECK_OUT_QUERY";
case repevt_autotrust_check: return "CHECK_AUTOTRUST";
case repevt_error: return "ERROR";
default: return "UNKNOWN";
}
@@ -437,6 +451,51 @@ time_passes(struct replay_runtime* runtime, struct replay_moment* mom)
#endif
}
/** check autotrust file contents */
static void
autotrust_check(struct replay_moment* mom)
{
char name[1024], line[1024];
FILE *in;
int lineno = 0, oke=1;
struct config_strlist* p;
line[sizeof(line)-1] = 0;
log_assert(mom->autotrust_id);
fake_temp_file("_auto_", mom->autotrust_id, name, sizeof(name));
in = fopen(name, "r");
if(!in) fatal_exit("could not open %s: %s", name, strerror(errno));
for(p=mom->file_content; p; p=p->next) {
lineno++;
if(!fgets(line, (int)sizeof(line)-1, in)) {
log_err("autotrust check failed, could not read line");
log_err("file %s, line %d", name, lineno);
log_err("should be: %s", p->str);
fatal_exit("autotrust_check failed");
}
if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
if(strcmp(p->str, line) != 0) {
log_err("mismatch in file %s, line %d", name, lineno);
log_err("file has : %s", line);
log_err("should be: %s", p->str);
oke = 0;
continue;
}
fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line);
}
if(fgets(line, (int)sizeof(line)-1, in)) {
log_err("autotrust check failed, extra lines in %s after %d",
name, lineno);
do {
fprintf(stderr, "file has: %s", line);
} while(fgets(line, (int)sizeof(line)-1, in));
oke = 0;
}
fclose(in);
if(!oke)
fatal_exit("autotrust_check STEP %d failed", mom->time_step);
log_info("autotrust %s is OK", mom->autotrust_id);
}
/**
* Advance to the next moment.
*/
@@ -504,6 +563,10 @@ do_moment_and_advance(struct replay_runtime* runtime)
time_passes(runtime, runtime->now);
advance_moment(runtime);
break;
case repevt_autotrust_check:
autotrust_check(runtime->now);
advance_moment(runtime);
break;
default:
fatal_exit("testbound: unknown event type %d",
runtime->now->evt_type);
+9
View File
@@ -63,4 +63,13 @@ void fake_event_init(struct replay_scenario* scen);
*/
void fake_event_cleanup();
/**
* Get filename to store temporary config stuff. The pid is added. in /tmp.
* @param adj: adjective, like "_cfg_", "_auto_"
* @param id: identifier, like "example.com".
* @param buf: where to store.
* @param len: length of buf.
*/
void fake_temp_file(const char* adj, const char* id, char* buf, size_t len);
#endif /* TESTCODE_FAKE_EVENT_H */
+36
View File
@@ -42,6 +42,7 @@
#include "config.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
#include "testcode/replay.h"
#include "testcode/ldns-testpkts.h"
@@ -73,6 +74,8 @@ replay_moment_delete(struct replay_moment* mom)
if(mom->match) {
delete_entry(mom->match);
}
free(mom->autotrust_id);
config_delstrlist(mom->file_content);
free(mom);
}
@@ -173,6 +176,31 @@ replay_range_read(char* remain, FILE* in, const char* name, int* lineno,
return NULL;
}
/** Read FILE match content */
static void
read_file_content(FILE* in, int* lineno, struct replay_moment* mom)
{
char line[MAX_LINE_LEN];
char* remain = line;
struct config_strlist** last = &mom->file_content;
line[MAX_LINE_LEN-1]=0;
if(!fgets(line, MAX_LINE_LEN-1, in))
fatal_exit("FILE_BEGIN expected at line %d", *lineno);
if(!parse_keyword(&remain, "FILE_BEGIN"))
fatal_exit("FILE_BEGIN expected at line %d", *lineno);
while(fgets(line, MAX_LINE_LEN-1, in)) {
(*lineno)++;
if(strncmp(line, "FILE_END", 8) == 0) {
return;
}
if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
if(!cfg_strlist_insert(last, strdup(line)))
fatal_exit("malloc failure");
last = &( (*last)->next );
}
fatal_exit("no FILE_END in input file");
}
/**
* Read a replay moment 'STEP' from file.
* @param remain: Rest of line (after STEP keyword).
@@ -223,6 +251,14 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
mom->evt_type = repevt_timeout;
} else if(parse_keyword(&remain, "TIME_PASSES")) {
mom->evt_type = repevt_time_passes;
} else if(parse_keyword(&remain, "CHECK_AUTOTRUST")) {
mom->evt_type = repevt_autotrust_check;
while(isspace((int)*remain))
remain++;
if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
remain[strlen(remain)-1] = 0;
mom->autotrust_id = strdup(remain);
read_file_content(in, lineno, mom);
} else if(parse_keyword(&remain, "ERROR")) {
mom->evt_type = repevt_error;
} else {
+17
View File
@@ -41,6 +41,15 @@
* <pre>
* File format for replay files.
*
* ; unbound.conf options.
* ; ...
* ; additional commandline options to pass to unbound
* COMMANDLINE cmdline_option
* ; autotrust key file contents, also adds auto-trust-anchor-file: "x" to cfg
* AUTOTRUST_FILE id
* ; contents of that file
* AUTOTRUST_END
* CONFIG_END
* ; comment line.
* SCENARIO_BEGIN name_of_scenario
* RANGE_BEGIN start_time end_time
@@ -60,6 +69,7 @@
* o TIMEOUT
* o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
* a floating point number.
* o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
* o ERROR
* ; following entry starts on the next line, ENTRY_BEGIN.
* ; more STEP items
@@ -156,6 +166,8 @@ struct replay_moment {
repevt_back_reply,
/** test fails if query to the network does not match */
repevt_back_query,
/** check autotrust key file */
repevt_autotrust_check,
/** an error happens to outbound query */
repevt_error
}
@@ -178,6 +190,11 @@ struct replay_moment {
* Unused at this time.
*/
ldns_rr* qname;
/** the autotrust file id to check */
char* autotrust_id;
/** file contents to match, one string per line */
struct config_strlist* file_content;
};
/**
+60 -20
View File
@@ -43,6 +43,7 @@
#include "testcode/replay.h"
#include "testcode/fake_event.h"
#include "daemon/remote.h"
#include "util/config_file.h"
/**
* include the main program from the unbound daemon.
@@ -54,8 +55,8 @@
/** maximum line length for lines in the replay file. */
#define MAX_LINE_LEN 1024
/** the config file (removed at exit) */
static char cfgfile[MAX_LINE_LEN];
/** config files (removed at exit) */
static struct config_strlist* cfgfiles = NULL;
/** give commandline usage for testbound. */
static void
@@ -122,27 +123,60 @@ echo_cmdline(int argc, char* argv[])
fprintf(stderr, "\n");
}
/** process config elements */
/** spool autotrust file */
static void
setup_config(FILE* in, char* configfile, int* lineno,
int* pass_argc, char* pass_argv[])
spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id)
{
char line[MAX_LINE_LEN];
char* parse;
FILE* spool;
/* find filename for new file */
while(isspace((int)*id))
id++;
if(strlen(id)==0)
fatal_exit("AUTROTRUST_FILE must have id, line %d", *lineno);
id[strlen(id)-1]=0; /* remove newline */
fake_temp_file("_auto_", id, line, sizeof(line));
/* add option for the file */
fprintf(cfg, "server: auto-trust-anchor-file: \"%s\"\n", line);
/* open file and spool to it */
spool = fopen(line, "w");
if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno));
fprintf(stderr, "testbound is spooling key file: %s\n", line);
if(!cfg_strlist_insert(&cfgfiles, strdup(line)))
fatal_exit("out of memory");
line[sizeof(line)-1] = 0;
while(fgets(line, MAX_LINE_LEN-1, in)) {
parse = line;
(*lineno)++;
while(isspace((int)*parse))
parse++;
if(strncmp(parse, "AUTOTRUST_END", 13) == 0) {
fclose(spool);
return;
}
fputs(line, spool);
}
fatal_exit("no AUTOTRUST_END in input file");
}
/** process config elements */
static void
setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
{
char configfile[MAX_LINE_LEN];
char line[MAX_LINE_LEN];
char* parse;
FILE* cfg;
#ifdef USE_WINSOCK
snprintf(configfile, MAX_LINE_LEN, "testbound_cfg_%u.tmp",
(unsigned)getpid());
#else
snprintf(configfile, MAX_LINE_LEN, "/tmp/testbound_cfg_%u.tmp",
(unsigned)getpid());
#endif
fake_temp_file("_cfg", "", configfile, sizeof(configfile));
add_opts("-c", pass_argc, pass_argv);
add_opts(configfile, pass_argc, pass_argv);
cfg = fopen(configfile, "w");
if(!cfg) fatal_exit("could not open %s: %s",
configfile, strerror(errno));
line[MAX_LINE_LEN-1] = 0;
if(!cfg_strlist_insert(&cfgfiles, strdup(configfile)))
fatal_exit("out of memory");
line[sizeof(line)-1] = 0;
/* some basic settings to not pollute the host system */
fprintf(cfg, "server: use-syslog: no\n");
fprintf(cfg, " directory: \"\"\n");
@@ -161,6 +195,10 @@ setup_config(FILE* in, char* configfile, int* lineno,
add_opts(parse+11, pass_argc, pass_argv);
continue;
}
if(strncmp(parse, "AUTOTRUST_FILE", 14) == 0) {
spool_auto_file(in, lineno, cfg, parse+14);
continue;
}
if(strncmp(parse, "CONFIG_END", 10) == 0) {
fclose(cfg);
return;
@@ -173,8 +211,7 @@ setup_config(FILE* in, char* configfile, int* lineno,
/** read playback file */
static struct replay_scenario*
setup_playback(const char* filename, char* configfile,
int* pass_argc, char* pass_argv[])
setup_playback(const char* filename, int* pass_argc, char* pass_argv[])
{
struct replay_scenario* scen = NULL;
int lineno = 0;
@@ -185,7 +222,7 @@ setup_playback(const char* filename, char* configfile,
perror(filename);
exit(1);
}
setup_config(in, configfile, &lineno, pass_argc, pass_argv);
setup_config(in, &lineno, pass_argc, pass_argv);
scen = replay_scenario_read(in, filename, &lineno);
fclose(in);
if(!scen)
@@ -199,9 +236,13 @@ setup_playback(const char* filename, char* configfile,
/** remove config file at exit */
void remove_configfile(void)
{
unlink(cfgfile);
struct config_strlist* p;
for(p=cfgfiles; p; p=p->next)
unlink(p->str);
config_delstrlist(cfgfiles);
cfgfiles = NULL;
}
/**
* Main fake event test program. Setup, teardown and report errors.
* @param argc: arg count.
@@ -221,7 +262,6 @@ main(int argc, char* argv[])
log_init(NULL, 0, NULL);
log_info("Start of %s testbound program.", PACKAGE_STRING);
/* determine commandline options for the daemon */
cfgfile[0] = 0;
pass_argc = 1;
pass_argv[0] = "unbound";
add_opts("-d", &pass_argc, pass_argv);
@@ -273,7 +313,7 @@ main(int argc, char* argv[])
fatal_exit("atexit() failed: %s", strerror(errno));
/* setup test environment */
scen = setup_playback(playback_file, cfgfile, &pass_argc, pass_argv);
scen = setup_playback(playback_file, &pass_argc, pass_argv);
/* init fake event backend */
fake_event_init(scen);