mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
variable processing.
git-svn-id: file:///svn/unbound/trunk@1795 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
dafe1ae21b
commit
a24f9ff9ea
12 changed files with 452 additions and 1 deletions
|
|
@ -120,6 +120,14 @@ static void usage()
|
||||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef unbound_testbound
|
||||||
|
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** check file descriptor count */
|
/** check file descriptor count */
|
||||||
static void
|
static void
|
||||||
checkrlimits(struct config_file* cfg)
|
checkrlimits(struct config_file* cfg)
|
||||||
|
|
|
||||||
|
|
@ -1305,3 +1305,4 @@ int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
31 August 2009: Wouter
|
||||||
|
- testbound variable processing.
|
||||||
|
|
||||||
28 August 2009: Wouter
|
28 August 2009: Wouter
|
||||||
- fixup unbound-control lookup to print forward and stub servers.
|
- fixup unbound-control lookup to print forward and stub servers.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -851,6 +851,12 @@ codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef UB_ON_WINDOWS
|
#ifdef UB_ON_WINDOWS
|
||||||
void
|
void
|
||||||
worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
|
worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
|
||||||
|
|
|
||||||
|
|
@ -233,3 +233,9 @@ codeline_cmp(const void* a, const void* b)
|
||||||
{
|
{
|
||||||
return strcmp((const char*)a, (const char*)b);
|
return strcmp((const char*)a, (const char*)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -708,6 +708,8 @@ comm_base_create(int ATTR_UNUSED(sigs))
|
||||||
struct replay_runtime* runtime = (struct replay_runtime*)
|
struct replay_runtime* runtime = (struct replay_runtime*)
|
||||||
calloc(1, sizeof(struct replay_runtime));
|
calloc(1, sizeof(struct replay_runtime));
|
||||||
runtime->scenario = saved_scenario;
|
runtime->scenario = saved_scenario;
|
||||||
|
runtime->vars = macro_store_create();
|
||||||
|
if(!runtime->vars) fatal_exit("out of memory");
|
||||||
return (struct comm_base*)runtime;
|
return (struct comm_base*)runtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,6 +741,7 @@ comm_base_delete(struct comm_base* b)
|
||||||
free(t);
|
free(t);
|
||||||
t = nt;
|
t = nt;
|
||||||
}
|
}
|
||||||
|
macro_store_delete(runtime->vars);
|
||||||
free(runtime);
|
free(runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,17 @@
|
||||||
/** max length of lines in file */
|
/** max length of lines in file */
|
||||||
#define MAX_LINE_LEN 10240
|
#define MAX_LINE_LEN 10240
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand a macro
|
||||||
|
* @param store: value storage
|
||||||
|
* @param runtime: replay runtime for other stuff.
|
||||||
|
* @param text: the macro text, after the ${, Updated to after the } when
|
||||||
|
* done (successfully).
|
||||||
|
* @return expanded text, malloced. NULL on failure.
|
||||||
|
*/
|
||||||
|
static char* macro_expand(rbtree_t* store,
|
||||||
|
struct replay_runtime* runtime, char** text);
|
||||||
|
|
||||||
/** parse keyword in string.
|
/** parse keyword in string.
|
||||||
* @param line: if found, the line is advanced to after the keyword.
|
* @param line: if found, the line is advanced to after the keyword.
|
||||||
* @param keyword: string.
|
* @param keyword: string.
|
||||||
|
|
@ -420,3 +431,328 @@ replay_scenario_delete(struct replay_scenario* scen)
|
||||||
}
|
}
|
||||||
free(scen);
|
free(scen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
replay_var_compare(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
struct replay_var* x = (struct replay_var*)a;
|
||||||
|
struct replay_var* y = (struct replay_var*)b;
|
||||||
|
return strcmp(x->name, y->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
rbtree_t*
|
||||||
|
macro_store_create(void)
|
||||||
|
{
|
||||||
|
return rbtree_create(&replay_var_compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** helper function to delete macro values */
|
||||||
|
static void
|
||||||
|
del_macro(rbnode_t* x, void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
struct replay_var* v = (struct replay_var*)x;
|
||||||
|
free(v->name);
|
||||||
|
free(v->value);
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
macro_store_delete(rbtree_t* store)
|
||||||
|
{
|
||||||
|
if(!store)
|
||||||
|
return;
|
||||||
|
traverse_postorder(store, del_macro, NULL);
|
||||||
|
free(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** return length of macro */
|
||||||
|
static size_t
|
||||||
|
macro_length(char* text)
|
||||||
|
{
|
||||||
|
/* we are after ${, looking for } */
|
||||||
|
int depth = 0;
|
||||||
|
size_t len = 0;
|
||||||
|
while(*text) {
|
||||||
|
len++;
|
||||||
|
if(*text == '}') {
|
||||||
|
if(depth == 0)
|
||||||
|
break;
|
||||||
|
depth--;
|
||||||
|
} else if(text[0] == '$' && text[1] == '{') {
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
text++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** insert new stuff at start of buffer */
|
||||||
|
static int
|
||||||
|
do_buf_insert(char* buf, size_t remain, char* after, char* inserted)
|
||||||
|
{
|
||||||
|
char* save = strdup(after);
|
||||||
|
if(!save) return 0;
|
||||||
|
if(strlen(inserted) > remain) {
|
||||||
|
free(save);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strlcpy(buf, inserted, remain);
|
||||||
|
buf += strlen(inserted);
|
||||||
|
remain -= strlen(inserted);
|
||||||
|
strlcpy(buf, save, remain);
|
||||||
|
free(save);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** do macro recursion */
|
||||||
|
static char*
|
||||||
|
do_macro_recursion(rbtree_t* store, struct replay_runtime* runtime,
|
||||||
|
char* at, size_t remain)
|
||||||
|
{
|
||||||
|
char* after = at+2;
|
||||||
|
char* expand = macro_expand(store, runtime, &after);
|
||||||
|
if(!expand)
|
||||||
|
return NULL; /* expansion failed */
|
||||||
|
if(!do_buf_insert(at, remain, after, expand)) {
|
||||||
|
free(expand);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
free(expand);
|
||||||
|
return at; /* and parse over the expanded text to see if again */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** get var from store */
|
||||||
|
struct replay_var*
|
||||||
|
macro_getvar(rbtree_t* store, char* name)
|
||||||
|
{
|
||||||
|
struct replay_var k;
|
||||||
|
k.node.key = &k;
|
||||||
|
k.name = name;
|
||||||
|
return (struct replay_var*)rbtree_search(store, &k);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** do macro variable */
|
||||||
|
static char*
|
||||||
|
do_macro_variable(rbtree_t* store, char* buf, size_t remain)
|
||||||
|
{
|
||||||
|
struct replay_var* v;
|
||||||
|
char* at = buf+1;
|
||||||
|
char* name = at;
|
||||||
|
char sv;
|
||||||
|
if(at[0]==0)
|
||||||
|
return NULL; /* no variable name after $ */
|
||||||
|
while(*at && (isalnum((int)*at) || *at=='_')) {
|
||||||
|
at++;
|
||||||
|
}
|
||||||
|
/* terminator, we are working in macro_expand() buffer */
|
||||||
|
sv = *at;
|
||||||
|
*at = 0;
|
||||||
|
v = macro_getvar(store, name);
|
||||||
|
*at = sv;
|
||||||
|
|
||||||
|
if(!v) {
|
||||||
|
log_err("variable is not defined: $%s", name);
|
||||||
|
return NULL; /* variable undefined is error for now */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert the variable contents */
|
||||||
|
if(!do_buf_insert(buf, remain, at, v->value))
|
||||||
|
return NULL;
|
||||||
|
return buf; /* and expand the variable contents */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** do ctime macro on argument */
|
||||||
|
static char*
|
||||||
|
do_macro_ctime(char* arg)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
time_t tt = atoi(arg);
|
||||||
|
if(tt == 0 && strcmp(arg, "0") != 0) {
|
||||||
|
log_err("macro ctime: expected number, not: %s", arg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctime_r(&tt, buf);
|
||||||
|
return strdup(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
macro_expand(rbtree_t* store, struct replay_runtime* runtime, char** text)
|
||||||
|
{
|
||||||
|
char buf[10240];
|
||||||
|
char* at = *text;
|
||||||
|
size_t len = macro_length(at);
|
||||||
|
int dofunc = 0;
|
||||||
|
/*printf("macro: '%s', len=%d\n", at, len);*/
|
||||||
|
if(len >= sizeof(buf))
|
||||||
|
return NULL; /* too long */
|
||||||
|
buf[0] = 0;
|
||||||
|
strlcpy(buf, at, len+1-1); /* do not copy last '}' character */
|
||||||
|
at = buf;
|
||||||
|
|
||||||
|
/* check for functions */
|
||||||
|
if(strcmp(buf, "time") == 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "%u", (unsigned)runtime->now_secs);
|
||||||
|
return strdup(buf);
|
||||||
|
} else if(strcmp(buf, "timeout") == 0) {
|
||||||
|
/* TODO: find timeout value */
|
||||||
|
snprintf(buf, sizeof(buf), "%u", (unsigned)runtime->now_secs);
|
||||||
|
return strdup(buf);
|
||||||
|
} else if(strncmp(buf, "ctime ", 6) == 0 ||
|
||||||
|
strncmp(buf, "ctime\t", 6) == 0) {
|
||||||
|
at += 6;
|
||||||
|
dofunc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* actual macro text expansion */
|
||||||
|
while(*at) {
|
||||||
|
size_t remain = sizeof(buf)-strlen(buf);
|
||||||
|
if(strncmp(at, "${", 2) == 0) {
|
||||||
|
at = do_macro_recursion(store, runtime, at, remain);
|
||||||
|
} else if(*at == '$') {
|
||||||
|
at = do_macro_variable(store, at, remain);
|
||||||
|
} else if(isdigit((int)*at)) {
|
||||||
|
/* TODO replace arithmatic with result */
|
||||||
|
} else {
|
||||||
|
/* copy until whitespace */
|
||||||
|
at++;
|
||||||
|
while(*at && !isblank((int)*at) && *at != '$')
|
||||||
|
at++;
|
||||||
|
}
|
||||||
|
if(!at) return NULL; /* failure */
|
||||||
|
}
|
||||||
|
*text += len;
|
||||||
|
if(dofunc) {
|
||||||
|
/* post process functions, buf has the argument(s) */
|
||||||
|
if(strncmp(*text, "ctime", 5) == 0) {
|
||||||
|
return do_macro_ctime(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*printf("macro return '%s'\n", buf);*/
|
||||||
|
return strdup(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
macro_process(rbtree_t* store, struct replay_runtime* runtime, char* text)
|
||||||
|
{
|
||||||
|
char buf[10240];
|
||||||
|
char* next, *expand;
|
||||||
|
char* at = text;
|
||||||
|
if(!strstr(text, "${"))
|
||||||
|
return strdup(text); /* no macros */
|
||||||
|
buf[0] = 0;
|
||||||
|
buf[sizeof(buf)-1]=0;
|
||||||
|
while( (next=strstr(at, "${")) ) {
|
||||||
|
/* copy text before next macro */
|
||||||
|
if((size_t)(next-at) >= sizeof(buf)-strlen(buf))
|
||||||
|
return NULL; /* string too long */
|
||||||
|
strlcpy(buf+strlen(buf), at, next-at+1);
|
||||||
|
/* process the macro itself */
|
||||||
|
next += 2;
|
||||||
|
expand = macro_expand(store, runtime, &next);
|
||||||
|
if(!expand) return NULL; /* expansion failed */
|
||||||
|
strlcpy(buf+strlen(buf), expand, sizeof(buf)-strlen(buf));
|
||||||
|
free(expand);
|
||||||
|
at = next;
|
||||||
|
}
|
||||||
|
/* copy remainder fixed text */
|
||||||
|
strlcpy(buf+strlen(buf), at, sizeof(buf)-strlen(buf));
|
||||||
|
return strdup(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
macro_lookup(rbtree_t* store, char* name)
|
||||||
|
{
|
||||||
|
struct replay_var* x = macro_getvar(store, name);
|
||||||
|
if(!x) return strdup("");
|
||||||
|
return strdup(x->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
macro_assign(rbtree_t* store, char* name, char* value)
|
||||||
|
{
|
||||||
|
struct replay_var* x = macro_getvar(store, name);
|
||||||
|
if(x) {
|
||||||
|
free(x->value);
|
||||||
|
} else {
|
||||||
|
x = (struct replay_var*)malloc(sizeof(*x));
|
||||||
|
if(!x) return 0;
|
||||||
|
x->node.key = x;
|
||||||
|
x->name = strdup(name);
|
||||||
|
if(!x->name) {
|
||||||
|
free(x);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
(void)rbtree_insert(store, &x->node);
|
||||||
|
}
|
||||||
|
x->value = strdup(value);
|
||||||
|
return x->value != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testbound_selftest(void)
|
||||||
|
{
|
||||||
|
/* test the macro store */
|
||||||
|
rbtree_t* store = macro_store_create();
|
||||||
|
char* v;
|
||||||
|
int r;
|
||||||
|
log_assert(store);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "bla");
|
||||||
|
log_assert(strcmp(v, "") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "vlerk");
|
||||||
|
log_assert(strcmp(v, "") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
r = macro_assign(store, "bla", "waarde1");
|
||||||
|
log_assert(r);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "vlerk");
|
||||||
|
log_assert(strcmp(v, "") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "bla");
|
||||||
|
log_assert(strcmp(v, "waarde1") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
r = macro_assign(store, "vlerk", "kanteel");
|
||||||
|
log_assert(r);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "bla");
|
||||||
|
log_assert(strcmp(v, "waarde1") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "vlerk");
|
||||||
|
log_assert(strcmp(v, "kanteel") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
r = macro_assign(store, "bla", "ww");
|
||||||
|
log_assert(r);
|
||||||
|
|
||||||
|
v = macro_lookup(store, "bla");
|
||||||
|
log_assert(strcmp(v, "ww") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
log_assert( macro_length("}") == 1);
|
||||||
|
log_assert( macro_length("blabla}") == 7);
|
||||||
|
log_assert( macro_length("bla${zoink}bla}") == 7+8);
|
||||||
|
log_assert( macro_length("bla${zoink}${bla}bla}") == 7+8+6);
|
||||||
|
|
||||||
|
v = macro_process(store, NULL, "");
|
||||||
|
log_assert( v && strcmp(v, "") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
v = macro_process(store, NULL, "${}");
|
||||||
|
log_assert( v && strcmp(v, "") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
v = macro_process(store, NULL, "blabla ${} dinges");
|
||||||
|
log_assert( v && strcmp(v, "blabla dinges") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
v = macro_process(store, NULL, "1${$bla}2${$bla}3");
|
||||||
|
log_assert( v && strcmp(v, "1ww2ww3") == 0);
|
||||||
|
free(v);
|
||||||
|
|
||||||
|
macro_store_delete(store);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,17 @@
|
||||||
* ; more STEP items
|
* ; more STEP items
|
||||||
* SCENARIO_END
|
* SCENARIO_END
|
||||||
*
|
*
|
||||||
|
* Calculations, a macro-like system: ${$myvar + 3600}
|
||||||
|
* STEP 10 ASSIGN $myvar = 3600
|
||||||
|
* ; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
|
||||||
|
* ${..} is macro expanded from its expression. Text substitution.
|
||||||
|
* o $var replaced with its value. var is identifier [azAZ09_]*
|
||||||
|
* o number is that number.
|
||||||
|
* o +, -, / and *. Note, evaluated left-to-right. Use ${} for brackets.
|
||||||
|
* o ${time} is the current time.
|
||||||
|
* o ${ctime value} is the text ctime(value), i.e. Fri 3 Aug 2009, ...
|
||||||
|
* must have one space after 'ctime'.
|
||||||
|
* o ${timeout} is the time until next timeout in the comm_timer list.
|
||||||
*
|
*
|
||||||
* ; Example file
|
* ; Example file
|
||||||
* SCENARIO_BEGIN Example scenario
|
* SCENARIO_BEGIN Example scenario
|
||||||
|
|
@ -108,11 +119,13 @@
|
||||||
#define TESTCODE_REPLAY_H
|
#define TESTCODE_REPLAY_H
|
||||||
#include "util/netevent.h"
|
#include "util/netevent.h"
|
||||||
#include "testcode/ldns-testpkts.h"
|
#include "testcode/ldns-testpkts.h"
|
||||||
|
#include "util/rbtree.h"
|
||||||
struct replay_answer;
|
struct replay_answer;
|
||||||
struct replay_moment;
|
struct replay_moment;
|
||||||
struct replay_range;
|
struct replay_range;
|
||||||
struct fake_pending;
|
struct fake_pending;
|
||||||
struct fake_timer;
|
struct fake_timer;
|
||||||
|
struct replay_var;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A replay scenario.
|
* A replay scenario.
|
||||||
|
|
@ -267,6 +280,11 @@ struct replay_runtime {
|
||||||
|
|
||||||
/** size of buffers */
|
/** size of buffers */
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tree of macro values. Of type replay_var
|
||||||
|
*/
|
||||||
|
rbtree_t* vars;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -328,6 +346,18 @@ struct fake_timer {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replay macro variable. And its value.
|
||||||
|
*/
|
||||||
|
struct replay_var {
|
||||||
|
/** rbtree node. Key is this structure. Sorted by name. */
|
||||||
|
rbnode_t node;
|
||||||
|
/** the variable name */
|
||||||
|
char* name;
|
||||||
|
/** the variable value */
|
||||||
|
char* value;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a replay scenario from the file.
|
* Read a replay scenario from the file.
|
||||||
* @param in: file to read from.
|
* @param in: file to read from.
|
||||||
|
|
@ -344,4 +374,50 @@ struct replay_scenario* replay_scenario_read(FILE* in, const char* name,
|
||||||
*/
|
*/
|
||||||
void replay_scenario_delete(struct replay_scenario* scen);
|
void replay_scenario_delete(struct replay_scenario* scen);
|
||||||
|
|
||||||
|
/** compare two replay_vars */
|
||||||
|
int replay_var_compare(const void* a, const void* b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create variable storage
|
||||||
|
* @return new or NULL on failure.
|
||||||
|
*/
|
||||||
|
rbtree_t* macro_store_create(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete variable storage
|
||||||
|
* @param store: the macro storage to free up.
|
||||||
|
*/
|
||||||
|
void macro_store_delete(rbtree_t* store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply macro substitution to string.
|
||||||
|
* @param store: variable store.
|
||||||
|
* @param runtime: the runtime to look up values as needed.
|
||||||
|
* @param text: string to work on.
|
||||||
|
* @return newly malloced string with result.
|
||||||
|
*/
|
||||||
|
char* macro_process(rbtree_t* store, struct replay_runtime* runtime,
|
||||||
|
char* text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a macro value. Like calling ${$name}.
|
||||||
|
* @param store: variable store
|
||||||
|
* @param name: macro name
|
||||||
|
* @return newly malloced string with result or strdup("") if not found.
|
||||||
|
* or NULL on malloc failure.
|
||||||
|
*/
|
||||||
|
char* macro_lookup(rbtree_t* store, char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set macro value.
|
||||||
|
* @param store: variable store
|
||||||
|
* @param name: macro name
|
||||||
|
* @param value: text to set it to. Not expanded.
|
||||||
|
* @return false on failure.
|
||||||
|
*/
|
||||||
|
int macro_assign(rbtree_t* store, char* name, char* value);
|
||||||
|
|
||||||
|
/** testbounds self test */
|
||||||
|
void testbound_selftest(void);
|
||||||
|
|
||||||
#endif /* TESTCODE_REPLAY_H */
|
#endif /* TESTCODE_REPLAY_H */
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@
|
||||||
#include "daemon/remote.h"
|
#include "daemon/remote.h"
|
||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
|
|
||||||
|
/** signal that this is a testbound compile */
|
||||||
|
#define unbound_testbound 1
|
||||||
/**
|
/**
|
||||||
* include the main program from the unbound daemon.
|
* include the main program from the unbound daemon.
|
||||||
* rename main to daemon_main to call it
|
* rename main to daemon_main to call it
|
||||||
|
|
@ -68,6 +70,7 @@ testbound_usage()
|
||||||
printf("-p file playback text file\n");
|
printf("-p file playback text file\n");
|
||||||
printf("-2 detect SHA256 support (exit code 0 or 1)\n");
|
printf("-2 detect SHA256 support (exit code 0 or 1)\n");
|
||||||
printf("-g detect GOST support (exit code 0 or 1)\n");
|
printf("-g detect GOST support (exit code 0 or 1)\n");
|
||||||
|
printf("-s testbound self-test - unit test of testbound parts.\n");
|
||||||
printf("-o str unbound commandline options separated by spaces.\n");
|
printf("-o str unbound commandline options separated by spaces.\n");
|
||||||
printf("Version %s\n", PACKAGE_VERSION);
|
printf("Version %s\n", PACKAGE_VERSION);
|
||||||
printf("BSD licensed, see LICENSE file in source package.\n");
|
printf("BSD licensed, see LICENSE file in source package.\n");
|
||||||
|
|
@ -265,8 +268,13 @@ main(int argc, char* argv[])
|
||||||
pass_argc = 1;
|
pass_argc = 1;
|
||||||
pass_argv[0] = "unbound";
|
pass_argv[0] = "unbound";
|
||||||
add_opts("-d", &pass_argc, pass_argv);
|
add_opts("-d", &pass_argc, pass_argv);
|
||||||
while( (c=getopt(argc, argv, "2gho:p:")) != -1) {
|
while( (c=getopt(argc, argv, "2gho:p:s")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
|
case 's':
|
||||||
|
free(pass_argv[1]);
|
||||||
|
testbound_selftest();
|
||||||
|
printf("selftest successful\n");
|
||||||
|
exit(0);
|
||||||
case '2':
|
case '2':
|
||||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||||
printf("SHA256 supported\n");
|
printf("SHA256 supported\n");
|
||||||
|
|
|
||||||
BIN
testdata/03-testbound.tpkg
vendored
BIN
testdata/03-testbound.tpkg
vendored
Binary file not shown.
|
|
@ -184,6 +184,7 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
|
||||||
else if(fptr == &val_neg_data_compare) return 1;
|
else if(fptr == &val_neg_data_compare) return 1;
|
||||||
else if(fptr == &val_neg_zone_compare) return 1;
|
else if(fptr == &val_neg_zone_compare) return 1;
|
||||||
else if(fptr == &probetree_cmp) return 1;
|
else if(fptr == &probetree_cmp) return 1;
|
||||||
|
else if(fptr == &replay_var_compare) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -334,4 +334,7 @@ int order_lock_cmp(const void* e1, const void* e2);
|
||||||
*/
|
*/
|
||||||
int codeline_cmp(const void* a, const void* b);
|
int codeline_cmp(const void* a, const void* b);
|
||||||
|
|
||||||
|
/** compare two replay_vars */
|
||||||
|
int replay_var_compare(const void* a, const void* b);
|
||||||
|
|
||||||
#endif /* UTIL_FPTR_WLIST_H */
|
#endif /* UTIL_FPTR_WLIST_H */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue