/*++
/* NAME
/* nbdb_sniffer_test 1t
/* SUMMARY
/* nbdb_sniffer unit test
/* SYNOPSIS
/* ./nbdb_sniffer_test
/* DESCRIPTION
/* nbdb_sniffer_test runs and logs each configured test, reports if
/* a test is a PASS or FAIL, and returns an exit status of zero if
/* all tests are a PASS.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* porcupine.org
/*--*/
/*
* System library .
*/
#include <sys_defs.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
/*
* Utility library .
*/
#include <msg.h>
#include <msg_vstream.h>
#include <open_as.h>
#include <stringops.h>
#include <vstream.h>
#include <vstring.h>
/*
* Global library .
*/
/*
* Testing library .
*/
#include <mock_open_as.h>
/*
* Application - specific .
*/
#include <nbdb_sniffer.h>
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
/*
* Test structure . Some tests may bring their own .
*/
typedef struct TEST_CASE {
const char *label;
int (*action) (const struct TEST_CASE *);
/*
* nbdb_parse_as_xxx ( ) inputs and expectations .
*/
struct {
const char *in_line;
bool out_want_postmap;
bool out_want_postalias;
} parse_as;
/*
* nbdb_get_index_cmd_as ( ) mock dependencies .
*/
MOCK_OPEN_AS_REQ mock_open;
/*
* nbdb_get_index_cmd_as ( ) inputs and expectations .
*/
struct {
const char *in_path;
uid_t in_uid;
gid_t in_gid;
const char *want_cmd;
const char *want_why;
int want_errno;
} index_cmd;
} TEST_CASE;
#define PASS (0 )
#define FAIL (1 )
/* test_parse_line - single-line vote */
static int test_parse_line(const TEST_CASE *tp)
{
bool got_postmap, got_postalias;
VSTRING *buffer;
buffer = vstring_alloc(strlen(tp->parse_as.in_line));
vstring_strcpy(buffer, tp->parse_as.in_line);
got_postmap = nbdb_parse_as_postmap(buffer);
vstring_strcpy(buffer, tp->parse_as.in_line);
got_postalias = nbdb_parse_as_postalias(buffer);
vstring_free(buffer);
#define bool_to_text(b) ((b) ? "true" : "false" )
/* Verify the results. */
if (got_postmap != tp->parse_as.out_want_postmap) {
msg_warn("got postmap: `%s', want `%s''" ,
bool_to_text(got_postmap),
bool_to_text(tp->parse_as.out_want_postmap));
return (FAIL);
}
if (got_postalias != tp->parse_as.out_want_postalias) {
msg_warn("got postalias: `%s', want `%s''" ,
bool_to_text(got_postalias),
bool_to_text(tp->parse_as.out_want_postalias));
return (FAIL);
}
return (PASS);
}
/* test_index_command - multi-line vote */
static int test_index_command(const TEST_CASE *tp)
{
static VSTRING *msg_buf;
static VSTRING *got_why;
const char *got_cmd;
if (msg_buf == 0 ) {
msg_buf = vstring_alloc(100 );
got_why = vstring_alloc(100 );
}
/* Run the test with fake file data. */
VSTRING_RESET(got_why);
setup_mock_vstream_fopen_as(&tp->mock_open);
got_cmd = nbdb_get_index_cmd_as(tp->index_cmd.in_path,
tp->index_cmd.in_uid,
tp->index_cmd.in_gid,
got_why);
#define CMD_OR_NULL(s) ((s) ? (s) : "(null)" )
/* Verify the results. */
if (!got_cmd != !tp->index_cmd.want_cmd) {
msg_warn("got command: `%s', want `%s''" ,
CMD_OR_NULL(got_cmd), CMD_OR_NULL(tp->index_cmd.want_cmd));
return (FAIL);
}
if (tp->index_cmd.want_cmd == 0 ) {
if (LEN(got_why) == 0
|| strstr(STR(got_why), tp->index_cmd.want_why) == 0 ) {
msg_warn("got warning: '%s', want: '%s'" ,
STR(got_why), tp->index_cmd.want_why);
return (FAIL);
}
if (tp->index_cmd.want_errno != errno) {
msg_warn("got errno: '%s', want: '%s'" ,
strerror(errno), strerror(tp->index_cmd.want_errno));
return (FAIL);
}
} else {
if (tp->index_cmd.want_errno != 0 )
msg_panic("want non-null result AND errno=%d" ,
tp->index_cmd.want_errno);
if (strcmp(got_cmd, tp->index_cmd.want_cmd) != 0 ) {
msg_warn("got command ``%s'', want ``%s''" ,
got_cmd, tp->index_cmd.want_cmd);
return (FAIL);
}
}
return (PASS);
}
/*
* The list of test cases .
*/
static const TEST_CASE test_cases[] = {
/*
* Line - level tests .
*/
{.label = "key_space_value" ,
.action = test_parse_line,
.parse_as = {
.in_line = "foo bar" ,
.out_want_postmap = true ,
.out_want_postalias = false ,
},
},
{.label = "colon_in_quoted_key_space_text" ,
.action = test_parse_line,
.parse_as = {
.in_line = "\" foobar:\" baz" ,
.out_want_postmap = true ,
.out_want_postalias = false ,
},
},
{.label = "quoted_key_colon_value" ,
.action = test_parse_line,
.parse_as = {
.in_line = "\" foo bar\":baz" ,
.out_want_postmap = false ,
.out_want_postalias = true ,
},
},
{.label = "key_space_colon_text" ,
.action = test_parse_line,
.parse_as = {
.in_line = "foo :bar" ,
.out_want_postmap = true ,
.out_want_postalias = true ,
},
},
{.label = "key_colon_value" ,
.action = test_parse_line,
.parse_as = {
.in_line = "foo:bar" ,
.out_want_postmap = false ,
.out_want_postalias = true ,
},
},
{.label = "colon_value" ,
.action = test_parse_line,
.parse_as = {
.in_line = ":bar" ,
.out_want_postmap = false ,
.out_want_postalias = false ,
},
},
{.label = "key_without value" ,
.action = test_parse_line,
.parse_as = {
.in_line = "bar" ,
.out_want_postmap = false ,
.out_want_postalias = false ,
},
},
{.label = "key_colon_without value" ,
.action = test_parse_line,
.parse_as = {
.in_line = "bar:" ,
.out_want_postmap = false ,
.out_want_postalias = false ,
},
},
/*
* File - level tests ( multiple lines with majority voting ) .
*/
{.label = "file_open_error_enoent" ,
.action = test_index_command,
.index_cmd = {
.in_path = "path/to/file" ,
.want_why = "open lookup table source file" ,
.want_errno = ENOENT,
},
.mock_open = {
.want_path = "path/to/file" ,
.out_data = 0 ,
.out_errno = ENOENT,
},
},
{.label = "file_open_error_eacces" ,
.action = test_index_command,
.index_cmd = {
.in_path = "path/to/file" ,
.in_uid = 1 ,
.want_why = "open lookup table source file" ,
.want_errno = EACCES,
},
.mock_open = {
.want_path = "path/to/file" ,
.want_uid = 1 ,
.out_errno = EACCES,
},
},
{.label = "mostly_postmap" ,
.action = test_index_command,
.index_cmd = {
.in_path = "path/to/file" ,
.want_cmd = "postmap" ,
},
.mock_open = {
.want_path = "path/to/file" ,
.out_data = "foo:bar\nfoo bar\nfoo :bar" ,
},
},
{.label = "mostly_postalias" ,
.action = test_index_command,
.index_cmd = {
.in_path = "path/to/file" ,
.want_cmd = "postalias" ,
},
.mock_open = {
.want_path = "path/to/file" ,
.out_data = "foo:bar\n\" foo bar\":baz\nfoo :bar" ,
},
},
{0 },
};
int main(int argc, char **argv)
{
const TEST_CASE *tp;
int pass = 0 ;
int fail = 0 ;
msg_vstream_init(sane_basename((VSTRING *) 0 , argv[0 ]), VSTREAM_ERR);
for (tp = test_cases; tp->label != 0 ; tp++) {
int test_failed;
msg_info("RUN %s" , tp->label);
test_failed = tp->action(tp);
if (test_failed) {
msg_info("FAIL %s" , tp->label);
fail++;
} else {
msg_info("PASS %s" , tp->label);
pass++;
}
}
msg_info("PASS=%d FAIL=%d" , pass, fail);
exit (fail != 0 );
}
Messung V0.5 in Prozent C=85 H=97 G=91
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland