/*++
/* NAME
/* smtpd_peer_test 1t
/* SUMMARY
/* smtpd_peer_init() unit tests
/* SYNOPSIS
/* ./smtpd_peer_test
/* DESCRIPTION
/* Verifies that smtpd_peer_init() will update the SMTPD_STATE
/* structure with the expected error or endpoint information for
/* different input sources.
/* 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>
/*
* Utility library .
*/
#include <htable.h>
#include <msg.h>
#include <msg_vstream.h>
#include <stringops.h>
#include <vstream.h>
/*
* Global library .
*/
#include <haproxy_srvr.h>
#include <inet_proto.h>
#include <mail_params.h>
#include <mail_proto.h>
/*
* TODO ( wietse ) make this a proper VSTREAM interface or test helper API .
*/
/* vstream_swap - capture output for testing */
static void vstream_swap(VSTREAM *one, VSTREAM *two)
{
VSTREAM save;
save = *one;
*one = *two;
*two = save;
}
/*
* Application - specific .
*/
#include <smtpd.h>
int tests_failed = 0 ;
int tests_passed = 0 ;
/*
* Fakes to satisfy some dependencies .
*/
#include <smtpd_chat.h>
#include <smtpd_sasl_glue.h>
#define TEST_TIMEOUT 10
char *var_smtpd_uproxy_proto = "" ;
int var_smtpd_uproxy_tmout = TEST_TIMEOUT;
bool var_smtpd_peername_lookup;
bool var_smtpd_client_port_log;
bool var_smtpd_sasl_enable;
int var_smtpd_cipv4_prefix = DEF_SMTPD_CIPV4_PREFIX;
int var_smtpd_cipv6_prefix = DEF_SMTPD_CIPV6_PREFIX;
char *var_notify_classes = DEF_NOTIFY_CLASSES;
void smtpd_chat_reset(SMTPD_STATE *state)
{
}
void smtpd_sasl_state_init(SMTPD_STATE *state)
{
}
void smtpd_xforward_init(SMTPD_STATE *state)
{
}
/* Reset globals that may be tweaked by individual tests */
static void reset_global_variables(void )
{
var_smtpd_uproxy_proto = "" ;
inet_proto_init("reset_global_variables" , "all" );
}
/*
* Basic tests that smtpd_peer_init ( ) will update the SMTPD_STATE structure
* with the expected error info or endpoint info . This needs to be
* subclassed to support different input sources ( local client , no open
* connection , HaProxy , postscreen , etc . ) .
*/
typedef struct TEST_BASE {
const char *label;
int want_hangup;
const char *want_warning;
const char *want_client_name;
int want_client_name_status;
const char *want_client_reverse_name;
int want_client_reverse_name_status;
const char *want_client_addr;
const char *want_client_rfc_addr;
const char *want_client_port;
int want_client_addr_family;
const char *want_server_addr;
const char *want_server_port;
int want_sockaddr_len;
int want_dest_sockaddr_len;
} TEST_BASE;
/* test_smtpd_peer_init - enforce smtpd_peer_init() expectations */
static int test_smtpd_peer_init(const TEST_BASE *tp, VSTREAM *fp,
SMTPD_STATE *state)
{
VSTRING *msg_buf = vstring_alloc(100 );
VSTREAM *memory_stream;
int test_passed = 1 ;
int aierr;
MAI_HOSTADDR_STR got_addr;
MAI_SERVPORT_STR got_port;
/*
* Detonate smtpd_state_init ( ) in a little sandbox .
*/
VSTRING_RESET(msg_buf);
VSTRING_TERMINATE(msg_buf);
if ((memory_stream = vstream_memopen(msg_buf, O_WRONLY)) == 0 )
msg_fatal("open memory stream: %m" );
vstream_swap(VSTREAM_ERR, memory_stream);
smtpd_state_init(state, fp, "something" );
vstream_swap(memory_stream, VSTREAM_ERR);
(void ) vstream_fclose(memory_stream);
/* Verify the results. */
if (tp->want_hangup != (state->flags & SMTPD_FLAG_HANGUP)) {
msg_warn("got hangup flag '0x%x', want '0x%x'" ,
state->flags & SMTPD_FLAG_HANGUP, tp->want_hangup);
test_passed = 0 ;
} else if (tp->want_warning == 0 && VSTRING_LEN(msg_buf) > 0 ) {
msg_warn("got warning ``%s'', want ``null''" , vstring_str(msg_buf));
test_passed = 0 ;
} else if (tp->want_warning != 0 ) {
if (strstr(vstring_str(msg_buf), tp->want_warning) == 0 ) {
msg_warn("got warning ``%s'', want ``%s''" ,
vstring_str(msg_buf), tp->want_warning);
test_passed = 0 ;
}
}
if (test_passed == 0 ) {
/* void */ ;
} else if (tp->want_client_name
&& strcmp(state->name, tp->want_client_name) != 0 ) {
msg_warn("got client name '%s', want '%s'" ,
state->name, tp->want_client_name);
test_passed = 0 ;
} else if (tp->want_client_name_status != 0
&& state->name_status != tp->want_client_name_status) {
msg_warn("got client name status '%d', want '%d'" ,
state->name_status, tp->want_client_name_status);
test_passed = 0 ;
} else if (tp->want_client_reverse_name
&& strcmp(state->reverse_name, tp->want_client_reverse_name) != 0 ) {
msg_warn("got client reverse name '%s', want '%s'" ,
state->reverse_name, tp->want_client_reverse_name);
test_passed = 0 ;
} else if (tp->want_client_reverse_name_status != 0
&& state->reverse_name_status != tp->want_client_reverse_name_status) {
msg_warn("got client reverse name status '%d', want '%d'" ,
state->reverse_name_status, tp->want_client_reverse_name_status);
test_passed = 0 ;
} else if (tp->want_client_addr
&& strcmp(state->addr, tp->want_client_addr) != 0 ) {
msg_warn("got text client address '%s', want '%s'" ,
state->addr, tp->want_client_addr);
test_passed = 0 ;
} if (tp->want_client_rfc_addr
&& strcmp(tp->want_client_rfc_addr, state->rfc_addr) != 0 ) {
msg_warn("got client rfc_addr '%s', want '%s'" ,
state->rfc_addr, tp->want_client_rfc_addr);
test_passed = 0 ;
} else if (tp->want_client_port
&& strcmp(state->port, tp->want_client_port) != 0 ) {
msg_warn("got text client port '%s', want '%s'" ,
state->port, tp->want_client_port);
test_passed = 0 ;
} else if (!state->sockaddr_len != !tp->want_sockaddr_len) {
msg_warn("got sockaddr_len '%d', want '%d'" ,
(int ) state->sockaddr_len, (int ) tp->want_sockaddr_len);
test_passed = 0 ;
} else if (tp->want_server_addr
&& strcmp(state->dest_addr, tp->want_server_addr) != 0 ) {
msg_warn("got text server address '%s', want '%s'" ,
state->dest_addr, tp->want_server_addr);
test_passed = 0 ;
} else if (tp->want_server_port
&& strcmp(state->dest_port, tp->want_server_port) != 0 ) {
msg_warn("got text server port '%s', want '%s'" ,
state->dest_port, tp->want_server_port);
test_passed = 0 ;
} else if (!state->dest_sockaddr_len != !tp->want_dest_sockaddr_len) {
msg_warn("got dest_sockaddr_len '%d', want '%d'" ,
(int ) state->dest_sockaddr_len, (int ) tp->want_dest_sockaddr_len);
test_passed = 0 ;
} else {
if (state->sockaddr_len > 0 ) {
if ((aierr =
sockaddr_to_hostaddr((struct sockaddr *) &state->sockaddr,
state->sockaddr_len, &got_addr, &got_port, 0 )) != 0 ) {
msg_warn("sockaddr_to_hostaddr: %s" , MAI_STRERROR(aierr));
test_passed = 0 ;
} else if (tp->want_client_addr
&& strcmp(got_addr.buf, tp->want_client_addr) != 0 ) {
msg_warn("got binary client address '%s', want '%s'" ,
got_addr.buf, tp->want_client_addr);
test_passed = 0 ;
} else if (tp->want_client_port
&& strcmp(got_port.buf, tp->want_client_port) != 0 ) {
msg_warn("got binary client port '%s', want '%s'" ,
got_port.buf, tp->want_client_port);
test_passed = 0 ;
}
}
if (state->dest_sockaddr_len > 0 ) {
if ((aierr =
sockaddr_to_hostaddr((struct sockaddr *) &state->dest_sockaddr,
state->dest_sockaddr_len, &got_addr, &got_port, 0 )) != 0 ) {
msg_warn("sockaddr_to_hostaddr: %s" , MAI_STRERROR(aierr));
test_passed = 0 ;
} else if (tp->want_server_addr
&& strcmp(got_addr.buf, tp->want_server_addr) != 0 ) {
msg_warn("got binary server address '%s', want '%s'" ,
got_addr.buf, tp->want_server_addr);
test_passed = 0 ;
} else if (tp->want_server_port
&& strcmp(got_port.buf, tp->want_server_port) != 0 ) {
msg_warn("got binary server port '%s', want '%s'" ,
got_port.buf, tp->want_server_port);
test_passed = 0 ;
}
}
}
(void ) vstring_free(msg_buf);
smtpd_state_reset(state);
return (test_passed);
}
/*
* Tests that a non - socket client results in fake localhost info .
*/
typedef struct PEER_FROM_NON_SOCKET_CASE {
TEST_BASE base;
const char *inet_protocols;
} PEER_FROM_NON_SOCKET_CASE;
static const PEER_FROM_NON_SOCKET_CASE peer_from_non_socket_cases[] = {
{
.base = {
.label = "prefer_ipv4" ,
.want_client_name = "localhost" ,
.want_client_name_status = SMTPD_PEER_CODE_OK,
.want_client_addr = "127.0.0.1" ,
.want_client_addr_family = AF_UNSPEC,
.want_client_rfc_addr = "127.0.0.1" ,
.want_client_reverse_name_status = SMTPD_PEER_CODE_OK,
.want_client_port = "0" ,
.want_server_addr = "127.0.0.1" ,
.want_server_port = "0" ,
},
.inet_protocols = "ipv4" ,
},
{
.base = {
.label = "prefer_ipv6" ,
.want_client_name = "localhost" ,
.want_client_name_status = SMTPD_PEER_CODE_OK,
.want_client_reverse_name = "localhost" ,
.want_client_reverse_name_status = SMTPD_PEER_CODE_OK,
.want_client_addr = "::1" ,
.want_client_addr_family = AF_UNSPEC,
.want_client_rfc_addr = "IPv6:::1" ,
.want_client_port = "0" ,
.want_server_addr = "::1" ,
.want_server_port = "0" ,
},
.inet_protocols = "ipv6" ,
},
{0 },
};
static void test_peer_from_non_socket(void )
{
int test_passed;
const PEER_FROM_NON_SOCKET_CASE *tp;
reset_global_variables();
for (tp = peer_from_non_socket_cases; tp->base.label != 0 ; tp++) {
msg_info("RUN test_peer_from_non_socket/%s" , tp->base.label);
{
SMTPD_STATE state;
VSTREAM *fp;
int pair[2 ];
if (pipe(pair) < 0 )
msg_fatal("pipe: %m" );
if ((fp = vstream_fdopen(pair[0 ], O_RDONLY)) == 0 )
msg_fatal("vstream_fdopen: %m" );
(void ) inet_proto_init("test_peer_from_non_socket" ,
tp->inet_protocols);
test_passed = test_smtpd_peer_init((TEST_BASE *) tp, fp, &state);
(void ) vstream_fdclose(fp);
(void ) close(pair[0 ]);
(void ) close(pair[1 ]);
}
if (test_passed) {
msg_info("PASS test_peer_from_non_socket/%s" , tp->base.label);
tests_passed += 1 ;
} else {
msg_info("FAIL test_peer_from_non_socket/%s" , tp->base.label);
tests_failed += 1 ;
}
}
}
/*
* Tests that a non - connected socket results in ' unknown ' endpoint info .
*/
typedef struct PEER_FROM_UNCONN_SOCKET_CASE {
TEST_BASE base;
int proto_family;
} PEER_FROM_UNCONN_SOCKET_CASE;
static const PEER_FROM_UNCONN_SOCKET_CASE peer_from_unconn_socket_cases[] = {
{
.base = {
.label = "tcp4" ,
.want_client_name = CLIENT_NAME_UNKNOWN,
.want_client_name_status = SMTPD_PEER_CODE_PERM,
.want_client_addr = CLIENT_ADDR_UNKNOWN,
.want_client_addr_family = AF_UNSPEC,
.want_client_rfc_addr = CLIENT_ADDR_UNKNOWN,
.want_client_reverse_name = CLIENT_NAME_UNKNOWN,
.want_client_reverse_name_status = SMTPD_PEER_CODE_PERM,
.want_client_port = CLIENT_PORT_UNKNOWN,
.want_server_addr = SERVER_ADDR_UNKNOWN,
.want_server_port = SERVER_PORT_UNKNOWN,
},
.proto_family = PF_INET,
},
{
.base = {
.label = "tcp6" ,
.want_client_name = CLIENT_NAME_UNKNOWN,
.want_client_name_status = SMTPD_PEER_CODE_PERM,
.want_client_addr = CLIENT_ADDR_UNKNOWN,
.want_client_addr_family = AF_UNSPEC,
.want_client_rfc_addr = CLIENT_ADDR_UNKNOWN,
.want_client_reverse_name = CLIENT_NAME_UNKNOWN,
.want_client_reverse_name_status = SMTPD_PEER_CODE_PERM,
.want_client_port = CLIENT_PORT_UNKNOWN,
.want_server_addr = SERVER_ADDR_UNKNOWN,
.want_server_port = SERVER_PORT_UNKNOWN,
},
.proto_family = PF_INET6,
},
{
.base = {
.label = "unix" ,
.want_client_name = CLIENT_NAME_UNKNOWN,
.want_client_name_status = SMTPD_PEER_CODE_PERM,
.want_client_addr = CLIENT_ADDR_UNKNOWN,
.want_client_addr_family = AF_UNSPEC,
.want_client_rfc_addr = CLIENT_ADDR_UNKNOWN,
.want_client_reverse_name = CLIENT_NAME_UNKNOWN,
.want_client_reverse_name_status = SMTPD_PEER_CODE_PERM,
.want_client_port = CLIENT_PORT_UNKNOWN,
.want_server_addr = SERVER_ADDR_UNKNOWN,
.want_server_port = SERVER_PORT_UNKNOWN,
},
.proto_family = PF_UNIX,
},
{0 },
};
static void test_peer_from_unconn_socket(void )
{
int test_passed;
const PEER_FROM_UNCONN_SOCKET_CASE *tp;
reset_global_variables();
for (tp = peer_from_unconn_socket_cases; tp->base.label != 0 ; tp++) {
msg_info("RUN test_peer_from_unconn_socket/%s" , tp->base.label);
{
SMTPD_STATE state;
VSTREAM *fp;
int sock;
if ((sock = socket(tp->proto_family, SOCK_STREAM, 0 )) < 0 )
msg_fatal("socketpair: %m" );
if ((fp = vstream_fdopen(sock, O_RDONLY)) == 0 )
msg_fatal("vstream_fdopen: %m" );
test_passed = test_smtpd_peer_init((TEST_BASE *) tp, fp, &state);
(void ) vstream_fclose(fp);
}
if (test_passed) {
msg_info("PASS test_peer_from_unconn_socket/%s" , tp->base.label);
tests_passed += 1 ;
} else {
msg_info("FAIL test_peer_from_unconn_socket/%s" , tp->base.label);
tests_failed += 1 ;
}
}
}
/*
* Tests that smtpd_peer_from_pass_attr ( ) updates the SMTPD_STATE structure
* with the expected error or endpoint information .
*/
#define PASS_ATTR_COUNT 5
struct PASS_ATTR {
const char *key;
const char *value;
};
typedef struct PEER_FROM_PASS_ATTR_CASE {
const TEST_BASE base; /* parent class */
struct PASS_ATTR attrs[PASS_ATTR_COUNT];
} PEER_FROM_PASS_ATTR_CASE;
/*
* We need one test for every constraint in smtpd_peer_from_pass ( ) , to
* demonstrate that smtpd_pass_attr . c propagates errors and endpoint info .
*/
static const PEER_FROM_PASS_ATTR_CASE peer_from_pass_attr_cases[] = {
{
.base = {
.label = "propagates_endpoint_info_from_good_pass_attr" ,
.want_client_addr = "1.2.3.4" ,
.want_client_port = "123" ,
.want_client_addr_family = AF_INET,
.want_server_addr = "4.3.2.1" ,
.want_server_port = "321" ,
.want_sockaddr_len = 1 ,
.want_dest_sockaddr_len = 1 ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_bad_IPv4_client_addr" ,
.want_hangup = 1 ,
.want_warning = "bad IPv4 client address" ,
/* TODO(wietse) Should we verify the surrogate endpoint info? */
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_missing_client_addr" ,
.want_hangup = 1 ,
.want_warning = "missing client address" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_bad_TCP_client_port" ,
.want_hangup = 1 ,
.want_warning = "bad TCP client port" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "A23" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_missing_client_port" ,
.want_hangup = 1 ,
.want_warning = "missing client port" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_bad_IPv6_server_addr" ,
.want_hangup = 1 ,
.want_warning = "bad IPv6 server address" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_ADDR, ":::4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_missing_server_addr" ,
.want_hangup = 1 ,
.want_warning = "missing server address" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_PORT, "321" ,
},
},
{
.base = {
.label = "propagates_error_from_bad_TCP_server_port" ,
.want_hangup = 1 ,
.want_warning = "bad TCP server port" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
MAIL_ATTR_ACT_SERVER_PORT, "A21" ,
},
},
{
.base = {
.label = "propagates_error_from_missing_server_port" ,
.want_hangup = 1 ,
.want_warning = "missing server port" ,
},
.attrs = {
MAIL_ATTR_ACT_CLIENT_ADDR, "1.2.3.4" ,
MAIL_ATTR_ACT_CLIENT_PORT, "123" ,
MAIL_ATTR_ACT_SERVER_ADDR, "4.3.2.1" ,
},
},
0 ,
};
static void test_peer_from_pass_attr(void )
{
int test_passed;
const PEER_FROM_PASS_ATTR_CASE *tp;
reset_global_variables();
for (tp = peer_from_pass_attr_cases; tp->base.label != 0 ; tp++) {
msg_info("RUN test_peer_from_pass_attr/%s" , tp->base.label);
{
SMTPD_STATE state;
VSTREAM *fp;
int sock;
HTABLE *attr_table = htable_create(PASS_ATTR_COUNT);
const struct PASS_ATTR *p;
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0 )) < 0 )
msg_fatal("socket: %m" );
if ((fp = vstream_fdopen(sock, O_RDWR)) == 0 )
msg_fatal("vstream_fdopen: %m" );
for (p = tp->attrs; p < tp->attrs + PASS_ATTR_COUNT && p->key != 0 ; p++)
htable_enter(attr_table, p->key, (void *) p->value);
vstream_control(fp,
VSTREAM_CTL_CONTEXT, (void *) attr_table,
VSTREAM_CTL_END);
test_passed = test_smtpd_peer_init((TEST_BASE *) tp, fp, &state);
htable_free(attr_table, (void (*) (void *)) 0 );
(void ) vstream_fclose(fp);
}
if (test_passed) {
msg_info("PASS test_peer_from_pass_attr/%s" , tp->base.label);
tests_passed += 1 ;
} else {
msg_info("FAIL test_peer_from_pass_attr/%s" , tp->base.label);
tests_failed += 1 ;
}
}
}
/*
* Tests that smtpd_peer_from_haproxy ( ) updates the SMTPD_STATE structure
* with the expected error or endpoint information .
*/
typedef struct PEER_FROM_HAPROXY_CASE {
const TEST_BASE base;
const char *proxy_header;
} PEER_FROM_HAPROXY_CASE;
/*
* We need only two tests to show that smtpd_haproxy . c propagates errors and
* non - error endpoint info . We don ' t need to duplicate each individual test
* in haproxy_srvr_test . c for different IP protocols , HaProxy protocol
* versions , and error modes .
*/
static const PEER_FROM_HAPROXY_CASE peer_from_haproxy_caes[] = {
{
.base = {
.label = "propagates_endpoint_info_from_good_proxy_header" ,
.want_client_addr = "1.2.3.4" ,
.want_client_port = "123" ,
.want_client_addr_family = AF_INET,
.want_server_addr = "4.3.2.1" ,
.want_server_port = "321" ,
.want_sockaddr_len = 1 ,
.want_dest_sockaddr_len = 1 ,
},
.proxy_header = "PROXY TCP4 1.2.3.4 4.3.2.1 123 321\n" ,
},
{
.base = {
.label = "propagates_error_from_bad_proxy_header" ,
.want_hangup = 1 ,
.want_warning = "short protocol header" ,
/* TODO(wietse) Should we verify the surrogate endpoint info? */
},
.proxy_header = "bad" ,
},
0 ,
};
static void test_peer_from_haproxy(void )
{
int test_passed;
const PEER_FROM_HAPROXY_CASE *tp;
reset_global_variables();
var_smtpd_uproxy_proto = HAPROXY_PROTO_NAME;
for (tp = peer_from_haproxy_caes; tp->proxy_header != 0 ; tp++) {
msg_info("RUN test_peer_from_haproxy/%s" , tp->base.label);
{
SMTPD_STATE state;
VSTREAM *fp;
int pair[2 ];
if (socketpair(AF_UNIX, SOCK_STREAM, 0 , pair) < 0 )
msg_fatal("socketpair: %m" );
if (write_buf(pair[1 ], tp->proxy_header, strlen(tp->proxy_header),
TEST_TIMEOUT) < 0 )
msg_fatal("write_buf: %m" );
if ((fp = vstream_fdopen(pair[0 ], O_RDONLY)) == 0 )
msg_fatal("vstream_fdopen: %m" );
test_passed = test_smtpd_peer_init((TEST_BASE *) tp, fp, &state);
(void ) vstream_fdclose(fp);
(void ) close(pair[0 ]);
(void ) close(pair[1 ]);
}
if (test_passed) {
msg_info("PASS test_peer_from_haproxy/%s" , tp->base.label);
tests_passed += 1 ;
} else {
msg_info("FAIL test_peer_from_haproxy/%s" , tp->base.label);
tests_failed += 1 ;
}
}
}
int main(int argc, char **argv)
{
msg_vstream_init(sane_basename((VSTRING *) 0 , argv[0 ]), VSTREAM_ERR);
test_peer_from_non_socket();
test_peer_from_unconn_socket();
test_peer_from_pass_attr();
test_peer_from_haproxy();
/*
* TODO ( wietse ) tests for a connected socket . This will require mock
* get_peername / get / sockname ( ) and getnameinfo / getaddrinfo ( )
* infrastructure .
*/
msg_info("PASS=%d FAIL=%d" , tests_passed, tests_failed);
exit (tests_failed != 0 );
}
Messung V0.5 in Prozent C=80 H=91 G=85
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland