test-smtp-submit.c revision eea481b7931f1a31080acfa92209662d2322a576
/* Copyright (c) 2016-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "lib-signals.h"
#include "str.h"
#include "hostpid.h"
#include "ioloop.h"
#include "istream.h"
#include "istream-chain.h"
#include "ostream.h"
#include "time-util.h"
#include "unlink-directory.h"
#include "write-full.h"
#include "connection.h"
#include "master-service.h"
#include "istream-dot.h"
#include "test-common.h"
#include "smtp-address.h"
#include "smtp-submit.h"
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
static const char *test_message1 =
"Subject: Test message\r\n"
"To: rcpt@example.com\r\n"
"From: sender@example.com\r\n"
"\r\n"
"Test message\r\n";
static const char *test_message2 =
"Subject: Test message\r\n"
"To: rcpt@example.com\r\n"
"From: sender@example.com\r\n"
"\r\n"
"Test message Test message Test message Test message Test message\r\n"
"Test message Test message Test message Test message Test message\r\n"
"Test message Test message Test message Test message Test message\r\n"
"Test message Test message Test message Test message Test message\r\n"
"Test message Test message Test message Test message Test message\r\n"
"Test message Test message Test message Test message Test message\r\n";
/*
* Types
*/
struct server_connection {
struct connection conn;
void *context;
};
typedef void (*test_server_init_t)(unsigned int index);
typedef bool (*test_client_init_t)
(const struct smtp_submit_settings *submit_set);
/*
* State
*/
/* common */
/* server */
static int fd_listen = -1;
static in_port_t server_port = 0;
static unsigned int server_pids_count = 0;
static struct connection_list *server_conn_list;
static unsigned int server_index;
/* client */
/*
* Forward declarations
*/
/* server */
static void test_server_run(unsigned int index);
static void
/* client */
static void
static void test_client_deinit(void);
static int
const char **error_r);
static int
const char **error_r);
/* test*/
static const char *test_tmp_dir_get(void);
static void
static void test_run_client_server(
const struct smtp_submit_settings *submit_set,
unsigned int server_tests_count)
ATTR_NULL(3);
/*
* Host lookup failed
*/
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_host_lookup_failed(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("host lookup failed");
NULL, 0);
test_end();
}
/*
* Connection refused
*/
/* server */
static void
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_connection_refused(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("connection refused");
test_end();
}
/*
* Connection timed out
*/
/* server */
static void
{
sleep(10);
}
static void test_server_connection_timed_out(unsigned int index)
{
}
/* client */
static bool
{
int ret;
time = ioloop_time;
return FALSE;
}
/* test */
static void test_connection_timed_out(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("connection timed out");
test_end();
}
/*
* Bad greeting
*/
/* server */
static void
{
}
static void
{
"554 No SMTP service here.\r\n");
}
static void test_server_bad_greeting(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_bad_greeting(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("bad greeting");
test_end();
}
/*
* Denied HELO
*/
/* server */
static void
{
const char *line;
return;
}
"550 Command rejected for testing reasons\r\n");
}
static void
{
}
static void test_server_denied_helo(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_denied_helo(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("denied helo");
test_end();
}
/*
* Disconnect HELO
*/
/* server */
static void
{
const char *line;
return;
}
}
static void
{
}
static void test_server_disconnect_helo(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_disconnect_helo(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("disconnect helo");
test_end();
}
/*
* Denied MAIL
*/
/* server */
enum _denied_mail_state {
};
struct _denied_mail_server {
enum _denied_mail_state state;
};
static void
{
struct _denied_mail_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
case DENIED_MAIL_STATE_EHLO:
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"453 4.3.2 Incapable of accepting messages at this time.\r\n");
return;
}
i_unreached();
}
}
static void
{
}
static void test_server_denied_mail(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_denied_mail(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("denied mail");
test_end();
}
/*
* Denied RCPT
*/
/* server */
enum _denied_rcpt_state {
};
struct _denied_rcpt_server {
enum _denied_rcpt_state state;
};
static void
{
struct _denied_rcpt_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
case DENIED_RCPT_STATE_EHLO:
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"550 5.4.3 Directory server failure\r\n");
return;
}
i_unreached();
}
}
static void
{
}
static void test_server_denied_rcpt(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_denied_rcpt(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("denied rcpt");
test_end();
}
/*
* Denied second RCPT
*/
/* server */
enum _denied_second_rcpt_state {
};
struct _denied_second_rcpt_server {
};
static void
{
struct _denied_second_rcpt_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"250 2.1.5 Ok\r\n");
continue;
"550 5.4.3 Directory server failure\r\n");
return;
}
i_unreached();
}
}
static void
{
}
static void test_server_denied_second_rcpt(unsigned int index)
{
}
/* client */
static bool
{
struct smtp_submit *smtp_submit;
struct smtp_submit_settings smtp_submit_set;
int ret;
return FALSE;
}
/* test */
static void test_denied_second_rcpt(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("denied second rcpt");
test_end();
}
/*
* Denied DATA
*/
/* server */
enum _denied_data_state {
};
struct _denied_data_server {
enum _denied_data_state state;
};
static void
{
struct _denied_data_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
case DENIED_DATA_STATE_EHLO:
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"250 2.1.5 Ok\r\n");
continue;
case DENIED_DATA_STATE_DATA:
"500 5.0.0 Unacceptabe recipients\r\n");
return;
}
i_unreached();
}
}
static void
{
}
static void test_server_denied_data(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_denied_data(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("denied data");
test_end();
}
/*
* Data failure
*/
/* server */
enum _data_failure_state {
};
struct _data_failure_server {
enum _data_failure_state state;
};
static void
{
struct _data_failure_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
case DATA_FAILURE_STATE_EHLO:
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"250 2.1.5 Ok\r\n");
continue;
case DATA_FAILURE_STATE_DATA:
"354 End data with <CR><LF>.<CR><LF>\r\n");
continue;
"552 5.2.3 Message length exceeds administrative limit\r\n");
return;
}
continue;
}
i_unreached();
}
}
static void
{
}
static void test_server_data_failure(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_data_failure(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("data failure");
test_end();
}
/*
* Data disconnect
*/
/* server */
enum _data_disconnect_state {
};
struct _data_disconnect_server {
enum _data_disconnect_state state;
};
static void
{
struct _data_disconnect_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"250 2.1.5 Ok\r\n");
continue;
"354 End data with <CR><LF>.<CR><LF>\r\n");
continue;
return;
}
i_unreached();
}
}
static void
{
}
static void test_server_data_disconnect(unsigned int index)
{
}
/* client */
static bool
{
int ret;
return FALSE;
}
/* test */
static void test_data_disconnect(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("data disconnect");
test_end();
}
/*
* Data timout
*/
/* server */
enum _data_timout_state {
};
struct _data_timout_server {
enum _data_timout_state state;
};
static void
{
struct _data_timout_server *ctx;
const char *line;
} else {
}
for (;;) {
return;
}
case DATA_TIMEOUT_STATE_EHLO:
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"250 2.1.5 Ok\r\n");
continue;
case DATA_TIMEOUT_STATE_DATA:
"354 End data with <CR><LF>.<CR><LF>\r\n");
continue;
sleep(10);
return;
}
i_unreached();
}
}
static void
{
}
static void test_server_data_timout(unsigned int index)
{
}
/* client */
static bool
{
int ret;
time = ioloop_time;
return FALSE;
}
/* test */
static void test_data_timeout(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("data timeout");
test_end();
}
/*
* Successful delivery
*/
/* server */
enum _successful_delivery_state {
};
struct _successful_delivery_server {
char *file_path;
};
static void
{
struct _successful_delivery_server *ctx;
const char *line;
} else {
}
// FIXME: take structure from test-smtp-client-errors
for (;;) {
int fd;
i_fatal("failed create tmp file for message: "
}
}
switch (res) {
break;
return;
i_error("test server: "
return;
i_error("test server: "
return;
}
"250 2.0.0 Ok: queued as 73BDE342129\r\n");
continue;
}
return;
}
"250-testserver\r\n"
"250-PIPELINING\r\n"
"250-ENHANCEDSTATUSCODES\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n");
return;
"250 2.1.0 Ok\r\n");
continue;
"250 2.1.5 Ok\r\n");
continue;
"354 End data with <CR><LF>.<CR><LF>\r\n");
continue;
break;
}
i_unreached();
}
}
static void
{
}
static void
{
struct _successful_delivery_server *ctx =
}
static void test_server_successful_delivery(unsigned int index)
{
}
/* client */
static bool
{
int ret;
/* send the message */
/* verify delivery */
t_strdup_printf("%s/message-%u.eml",
test_tmp_dir_get(), bind_ports[0]));
return FALSE;
}
struct _parallel_delivery_client {
unsigned int count;
};
static void
struct _parallel_delivery_client *ctx)
{
}
static bool
{
struct smtp_submit_settings smtp_submit_set;
struct _parallel_delivery_client *ctx;
ioloop = io_loop_create();
/* submit 1 */
/* submit 2 */
/* verify delivery */
t_strdup_printf("%s/message-%u.eml",
test_tmp_dir_get(), bind_ports[0]));
t_strdup_printf("%s/message-%u.eml",
return FALSE;
}
/* test */
static void test_successful_delivery(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("successful delivery");
test_end();
test_begin("parallel delivery");
test_end();
}
/*
* Failed sendmail
*/
/* client */
static bool
{
struct smtp_submit_settings smtp_submit_set;
struct smtp_submit *smtp_submit;
int ret;
return FALSE;
}
/* test */
static void test_failed_sendmail(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("failed sendmail");
test_end();
}
/*
* Successful sendmail
*/
/* client */
static bool
{
struct smtp_submit_settings smtp_submit_set;
struct smtp_submit *smtp_submit;
int ret;
/* verify delivery */
return FALSE;
}
/* test */
static void test_successful_sendmail(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("successful sendmail");
test_end();
}
/*
* Parallel sendmail
*/
/* client */
struct _parallel_sendmail_client {
unsigned int count;
};
static void
struct _parallel_sendmail_client *ctx)
{
}
static bool
{
struct smtp_submit_settings smtp_submit_set;
struct _parallel_sendmail_client *ctx;
const char *sendmail_path1, *sendmail_path2;
ioloop = io_loop_create();
/* submit 1 */
/* submit 2 */
/* verify delivery */
return FALSE;
}
/* test */
static void test_parallel_sendmail(void)
{
struct smtp_submit_settings smtp_submit_set;
test_begin("parallel sendmail");
test_end();
}
/*
* All tests
*/
static void (*const test_functions[])(void) = {
};
/*
* Test client
*/
static void
{
}
static void test_client_deinit(void)
{
}
static int
const char **error_r)
{
struct smtp_submit_settings smtp_submit_set;
struct smtp_submit *smtp_submit;
int ret;
/* send the message */
return ret;
}
static int
const struct smtp_submit_settings *smtp_set,
const char **error_r)
{
return test_client_smtp_send_simple(smtp_set,
}
/*
* Test server
*/
/* client connection */
static void
{
}
static void
server_connection_init(int fd)
{
struct server_connection *conn;
if (test_server_init != NULL)
}
static void
{
if (test_server_deinit != NULL)
}
static void
{
struct server_connection *conn =
(struct server_connection *)_conn;
}
static void
{
int fd;
/* accept new client */
if (fd == -1)
return;
if (fd == -2) {
i_fatal("test server: accept() failed: %m");
}
}
/* */
static struct connection_settings server_connection_set = {
};
static const struct connection_vfuncs server_connection_vfuncs = {
};
static void test_server_run(unsigned int index)
{
/* open server socket */
/* close server socket */
}
/*
* Tests
*/
{
if (debug)
if (fd == -1) {
i_fatal("listen(%s:%u) failed: %m",
}
return fd;
}
static void test_servers_kill_all(void)
{
unsigned int i;
if (server_pids_count > 0) {
for (i = 0; i < server_pids_count; i++) {
server_pids[i] = -1;
}
}
}
server_pids_count = 0;
}
static void test_tmp_dir_init(void)
{
("/tmp/dovecot-test-smtp-client.%s.%s",
}
static const char *test_tmp_dir_get(void)
{
i_fatal("failed to create temporary directory `%s': %m",
tmp_dir);
}
return tmp_dir;
}
static void test_tmp_dir_deinit(void)
{
const char *error;
if (unlink_directory(tmp_dir,
UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0) {
i_warning("failed to remove temporary directory `%s': %s.",
}
}
static void
{
const unsigned char *data;
int ret;
const unsigned char *mdata;
if (test_has_failed())
break;
if (test_has_failed())
break;
}
input->stream_errno == 0 &&
}
static void test_run_client_server(
const struct smtp_submit_settings *submit_set,
unsigned int server_tests_count)
{
unsigned int i;
server_pids = NULL;
server_pids_count = 0;
if (server_tests_count > 0) {
int fds[server_tests_count];
for (i = 0; i < server_tests_count; i++)
for (i = 0; i < server_tests_count; i++)
for (i = 0; i < server_tests_count; i++) {
server_port = bind_ports[i];
i_fatal("fork() failed: %m");
if (server_pids[i] == 0) {
server_pids_count = 0;
hostpid_init();
while (current_ioloop != NULL) {
}
if (debug)
/* child: server */
ioloop = io_loop_create();
server_test(i);
if (fd_listen != -1)
/* wait for it to be killed; this way, valgrind will not
object to this process going away inelegantly. */
sleep(60);
exit(1);
}
if (fd_listen != -1)
}
if (debug)
}
/* parent: client */
server_port = 0;
ioloop = io_loop_create();
if (client_test(submit_set))
}
/*
* Main
*/
volatile sig_atomic_t terminating = 0;
static void
test_signal_handler(int signo)
{
if (terminating != 0)
terminating = 1;
/* make sure we don't leave any pesky children alive */
}
static void test_atexit(void)
{
}
{
int c;
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'D':
break;
default:
}
}
/* listen on localhost */
}