/*++
/* AUTHOR(S)
/* Wietse Venema
/* porcupine.org
/*--*/
/*
* System library .
*/
#include <sys_defs.h>
#include <stdlib.h>
#include <string.h>
/*
* Utility library .
*/
#include <argv.h>
#include <dict_union.h>
#include <msg.h>
#include <msg_vstream.h>
#include <stringops.h>
#include <vstring.h>
/*
* Testing library .
*/
#include <dict_test_helper.h>
#define LEN(x) VSTRING_LEN(x)
#define STR(x) vstring_str(x)
/*
* TODO ( wietse ) move these to common testing header file .
*/
#define PASS 1
#define FAIL 0
static VSTRING *msg_buf;
static int valid_refcounts_for_good_composite_syntax(void )
{
DICT *dict;
int open_flags = O_RDONLY;
int dict_flags = DICT_FLAG_LOCK;
VSTRING *composite_spec = vstring_alloc(100 );
ARGV *reg_component_specs = argv_alloc(3 );
const char *component_specs[] = {
"static:one" ,
"static:two" ,
"inline:{foo=three}" ,
0 ,
};
char **cpp;
dict_compose_spec(DICT_TYPE_UNION, component_specs, open_flags, dict_flags,
composite_spec, reg_component_specs);
dict = dict_open_and_capture_msg(STR(composite_spec), open_flags, dict_flags,
msg_buf);
#undef RETURN
#define RETURN (x) do { \
if (dict) dict_close(dict); \
vstring_free(composite_spec); \
argv_free(reg_component_specs); \
return (x); \
} while (0 );
if (LEN(msg_buf) > 0 ) {
msg_warn("unexpected dict_open() warning: got '%s'" , STR(msg_buf));
RETURN (FAIL);
}
for (cpp = reg_component_specs->argv; *cpp; cpp++) {
if (dict_handle(*cpp) == 0 ) {
msg_warn("table '%s' is not registered after dict_open()" , *cpp);
RETURN (FAIL);
}
}
dict_close(dict);
dict = 0 ;
for (cpp = reg_component_specs->argv; *cpp; cpp++) {
if (dict_handle(*cpp) != 0 ) {
msg_warn("table '%s' is still registered after dict_close()" , *cpp);
RETURN (FAIL);
}
}
RETURN (PASS);
}
static int valid_refcounts_for_bad_composite_syntax(void )
{
DICT *dict;
int open_flags = O_RDONLY;
int dict_flags = DICT_FLAG_LOCK;
VSTRING *composite_spec = vstring_alloc(100 );
ARGV *reg_component_specs = argv_alloc(3 );
const char *component_specs[] = {
"static:one" ,
"static:two" ,
"inline{foo=three}" ,
0 ,
};
char **cpp;
const char *want_msg = "bad syntax:" ;
dict_compose_spec(DICT_TYPE_UNION, component_specs, open_flags, dict_flags,
composite_spec, reg_component_specs);
dict = dict_open_and_capture_msg(STR(composite_spec), open_flags,
dict_flags, msg_buf);
#undef RETURN
#define RETURN (x) do { \
dict_close(dict); \
vstring_free(composite_spec); \
argv_free(reg_component_specs); \
return (x); \
} while (0 );
if (LEN(msg_buf) == 0 ) {
msg_warn("missing dict_open() warning: want '%s'" , want_msg);
RETURN (FAIL);
}
if (strstr(STR(msg_buf), want_msg) == 0 ) {
msg_warn("unexpected warning message: got '%s', want '%s'" ,
STR(msg_buf), want_msg);
RETURN (FAIL);
}
for (cpp = reg_component_specs->argv; *cpp; cpp++) {
if (dict_handle(*cpp) != 0 ) {
msg_warn("table '%s' is registered after failed dict_open()" ,
*cpp);
RETURN (FAIL);
}
}
RETURN (PASS);
}
static int propagates_notfound_and_found(void )
{
DICT *dict;
int open_flags = O_RDONLY;
int dict_flags = DICT_FLAG_LOCK;
const char *dict_spec = ("unionmap:{static:one,static:two,"
"inline:{foo=three}}" );
static struct dict_get_verify_data expectations[] = {
{.key = "foo" ,.want_value = "one,two,three" },
{.key = "bar" ,.want_value = "one,two" },
{0 },
};
int ret;
dict = dict_open_and_capture_msg(dict_spec, open_flags, dict_flags,
msg_buf);
if (LEN(msg_buf) > 0 ) {
msg_warn("unexpected dict_open() warning: got '%s'" , STR(msg_buf));
ret = FAIL;
} else {
ret = dict_get_and_verify_bulk(dict, expectations);
}
dict_close(dict);
return (ret);
}
static int propagates_error(void )
{
DICT *dict;
int open_flags = O_RDONLY;
int dict_flags = DICT_FLAG_LOCK;
const char *dict_spec = "unionmap:{static:one,fail:fail}" ;
static struct dict_get_verify_data expectations[] = {
{.key = "foo" ,.want_value = 0 ,.want_error = DICT_ERR_RETRY},
{0 },
};
int ret;
dict = dict_open_and_capture_msg(dict_spec, open_flags, dict_flags,
msg_buf);
if (LEN(msg_buf) > 0 ) {
msg_warn("unexpected dict_open() warning: got '%s'" , STR(msg_buf));
ret = FAIL;
} else {
ret = dict_get_and_verify_bulk(dict, expectations);
}
dict_close(dict);
return (ret);
}
static int no_comma_for_not_found(void )
{
DICT *dict;
int open_flags = O_RDONLY;
int dict_flags = DICT_FLAG_LOCK;
const char *dict_spec = "unionmap:{regexp:{{/a|c/ 1}},regexp:{{/b|c/ 2}}}" ;
static struct dict_get_verify_data expectations[] = {
{.key = "x" ,.want_value = 0 },
{.key = "a" ,.want_value = "1" },
{.key = "b" ,.want_value = "2" },
{.key = "c" ,.want_value = "1,2" },
{0 },
};
int ret;
dict = dict_open_and_capture_msg(dict_spec, open_flags, dict_flags,
msg_buf);
if (LEN(msg_buf) > 0 ) {
msg_warn("unexpected dict_open() warning: got '%s'" , STR(msg_buf));
ret = FAIL;
} else {
ret = dict_get_and_verify_bulk(dict, expectations);
}
dict_close(dict);
return (ret);
}
struct TEST_CASE {
const char *label;
int (*action) (void );
};
static const struct TEST_CASE test_cases[] = {
{"valid_refcounts_for_good_composite_syntax" , valid_refcounts_for_good_composite_syntax,},
{"valid_refcounts_for_bad_composite_syntax" , valid_refcounts_for_bad_composite_syntax,},
{"propagates_notfound_and_found" , propagates_notfound_and_found,},
{"propagates_error" , propagates_error,},
{"no_comma_for_not_found" , no_comma_for_not_found,},
{0 },
};
int main(int argc, char **argv)
{
static int tests_passed = 0 ;
static int tests_failed = 0 ;
const struct TEST_CASE *tp;
msg_vstream_init(sane_basename((VSTRING *) 0 , argv[0 ]), VSTREAM_ERR);
msg_buf = vstring_alloc(100 );
dict_allow_surrogate = 1 ;
for (tp = test_cases; tp->label; tp++) {
msg_info("RUN %s" , tp->label);
if (tp->action() == PASS) {
msg_info("PASS %s" , tp->label);
tests_passed += 1 ;
} else {
msg_info("FAIL %s" , tp->label);
tests_failed += 1 ;
}
}
vstring_free(msg_buf);
msg_info("PASS=%d FAIL=%d" , tests_passed, tests_failed);
exit (tests_failed != 0 );
}
Messung V0.5 in Prozent C=72 H=94 G=83
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland