bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "lib.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "array.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "hostpid.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "net.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "istream.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "ostream.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "ioloop.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "unlink-directory.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "test-common.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include "imapc-client-private.h"
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include <stdio.h>
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include <unistd.h>
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include <signal.h>
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include <sys/stat.h>
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#include <sys/wait.h>
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen#define IMAPC_COMMAND_STATE_INVALID (enum imapc_command_state)-1
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainentypedef void test_server_init_t(void);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainentypedef void test_client_init_t(void);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstruct test_server {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen in_port_t port;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen pid_t pid;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen int fd_listen, fd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct istream *input;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct ostream *output;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen};
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic struct ip_addr bind_ip;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic struct test_server server;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic struct imapc_client *imapc_client;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic enum imapc_command_state imapc_login_last_reply;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic ARRAY(enum imapc_command_state) imapc_cmd_last_replies;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic bool debug = FALSE;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic struct imapc_client_settings test_imapc_default_settings = {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .host = "127.0.0.1",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .username = "testuser",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .password = "testpass",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .dns_client_socket_path = "",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .temp_path_prefix = ".test-tmp/",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .rawlog_dir = "",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .connect_timeout_msecs = 500,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .connect_retry_count = 3,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .connect_retry_interval_msecs = 10,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen .max_idle_time = 10000,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen};
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic int test_open_server_fd(in_port_t *bind_port)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen int fd = net_listen(&bind_ip, bind_port, 128);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (debug)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_debug("server listening on %u", *bind_port);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (fd == -1) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_fatal("listen(%s:%u) failed: %m",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen net_ip2addr(&bind_ip), *bind_port);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen fd_set_nonblock(fd, FALSE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return fd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainentest_server_wait_connection(struct test_server *server, bool send_banner)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server->fd = net_accept(server->fd_listen, NULL, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_assert(server->fd >= 0);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen fd_set_nonblock(server->fd, FALSE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server->input = i_stream_create_fd(server->fd, (size_t)-1);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server->output = o_stream_create_fd(server->fd, (size_t)-1);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_set_no_error_handling(server->output, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (send_banner) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server->output,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen "* OK [CAPABILITY IMAP4rev1 UNSELECT QUOTA] ready\r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_server_disconnect(struct test_server *server)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek i_stream_unref(&server->input);
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek o_stream_unref(&server->output);
7b032348d7bbb93ff96188289d3dfc1899b9abb3Josef 'Jeff' Sipek i_close_fd(&server->fd);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_server_disconnect_and_wait(bool send_banner)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect(&server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, send_banner);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_server_kill(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (server.pid != (pid_t)-1) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (kill(server.pid, SIGKILL) < 0)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_fatal("kill(%ld) failed: %m", (long)server.pid);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (waitpid(server.pid, NULL, 0) < 0)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_fatal("waitpid(%ld) failed: %m", (long)server.pid);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server.pid = -1;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_run_client_server(
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen const struct imapc_client_settings *client_set,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_client_init_t *client_test,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_init_t *server_test)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings client_set_copy = *client_set;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct ioloop *ioloop;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen const char *error;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_cmd_tag_counter = 0;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_last_reply = IMAPC_COMMAND_STATE_INVALID;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen t_array_init(&imapc_cmd_last_replies, 4);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_zero(&server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server.pid = (pid_t)-1;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server.fd = -1;
be97d7e54ef50ac49f3fd4ca27f0b8660e239036Timo Sirainen server.fd_listen = test_open_server_fd(&server.port);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen client_set_copy.port = server.port;
be97d7e54ef50ac49f3fd4ca27f0b8660e239036Timo Sirainen if (server_test == NULL)
be97d7e54ef50ac49f3fd4ca27f0b8660e239036Timo Sirainen i_close_fd(&server.fd_listen);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (mkdir(client_set->temp_path_prefix, 0700) < 0 && errno != EEXIST)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_fatal("mkdir(%s) failed: %m", client_set->temp_path_prefix);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if ((server.pid = fork()) == (pid_t)-1)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_fatal("fork() failed: %m");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (server.pid == 0) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen server.pid = (pid_t)-1;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen hostpid_init();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (debug)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_debug("server: PID=%s", my_pid);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* child: server */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen ioloop = io_loop_create();
a2328a1c60026f3d3d47c5c75a2e972fec86d5b4Timo Sirainen if (server_test != NULL)
a2328a1c60026f3d3d47c5c75a2e972fec86d5b4Timo Sirainen server_test();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect(&server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen io_loop_destroy(&ioloop);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* wait for it to be killed; this way, valgrind will not
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen object to this process going away inelegantly. */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen sleep(60);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen exit(1);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* parent: client */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen usleep(100000); /* wait a little for server setup */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen ioloop = io_loop_create();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client = imapc_client_init(&client_set_copy);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen client_test();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(array_count(&imapc_cmd_last_replies) == 0);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (imapc_client != NULL)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_deinit(&imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen io_loop_destroy(&ioloop);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
7b032348d7bbb93ff96188289d3dfc1899b9abb3Josef 'Jeff' Sipek i_close_fd(&server.fd_listen);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_kill();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (unlink_directory(client_set->temp_path_prefix,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen UNLINK_DIRECTORY_FLAG_RMDIR, &error) < 0)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_fatal("%s", error);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic enum imapc_command_state test_imapc_cmd_last_reply_pop(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen const enum imapc_command_state *replies;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen enum imapc_command_state reply;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen unsigned int count;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen replies = array_get(&imapc_cmd_last_replies, &count);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (count == 0)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return IMAPC_COMMAND_STATE_INVALID;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen reply = replies[0];
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen array_delete(&imapc_cmd_last_replies, 0, 1);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return reply;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic bool test_imapc_cmd_last_reply_expect(enum imapc_command_state state)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (array_count(&imapc_cmd_last_replies) == 0)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return test_imapc_cmd_last_reply_pop() == state;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic bool test_imapc_server_expect(const char *expected_line)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen const char *line = i_stream_read_next_line(server.input);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (line == NULL) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen printf("imapc client disconnected unexpectedly: %s\n",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_stream_get_error(server.input));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return FALSE;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen } else if (strcmp(line, expected_line) != 0) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen printf("imapc client sent '%s' when expecting '%s'\n",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen line, expected_line);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return FALSE;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen } else {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return TRUE;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void imapc_login_callback(const struct imapc_command_reply *reply,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen void *context ATTR_UNUSED)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (debug) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_debug("Login reply: %s %s",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_state_names[reply->state],
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen reply->text_full);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_last_reply = reply->state;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_stop(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void imapc_command_callback(const struct imapc_command_reply *reply,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen void *context ATTR_UNUSED)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen if (debug) {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_debug("Command reply: %s %s",
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_state_names[reply->state],
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen reply->text_full);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen }
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen array_append(&imapc_cmd_last_replies, &reply->state, 1);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_stop(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void imapc_reopen_callback(void *context)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_mailbox *box = context;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_command *cmd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_mailbox_cmd(box, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "SELECT");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_connect_failed_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* connection refused & one reconnect */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_errors(2);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_DISCONNECTED);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_connect_failed(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc connect failed");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_connect_failed_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_banner_hangs_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_errors(2);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_DISCONNECTED);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_banner_hangs_server(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct test_server server2 = { .fd_listen = server.fd_listen };
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, FALSE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server2, FALSE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(i_stream_read_next_line(server2.input) == NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect(&server2);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_banner_hangs(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc banner hangs");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_banner_hangs_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_banner_hangs_server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_login_hangs_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_errors(2);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_DISCONNECTED);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_login_hangs_server(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct test_server server2 = { .fd_listen = server.fd_listen };
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server2, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(i_stream_read_next_line(server2.input) == NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect(&server2);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_login_hangs(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc login hangs");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_login_hangs_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_login_hangs_server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_command *cmd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* login to server */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_OK);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_last_reply = IMAPC_COMMAND_STATE_INVALID;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* disconnect */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "DISCONNECT");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_error_string("reconnecting");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_pop() == IMAPC_COMMAND_STATE_DISCONNECTED);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* we should be reconnected now. try a command. */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "NOOP");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_INVALID);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_pop() == IMAPC_COMMAND_STATE_OK);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_server(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "1 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("2 DISCONNECT"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect_and_wait(TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("4 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "4 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("3 NOOP"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "3 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
a2328a1c60026f3d3d47c5c75a2e972fec86d5b4Timo Sirainen test_assert(i_stream_read_next_line(server.input) == NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc reconnect");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_reconnect_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_resend_cmds_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_command *cmd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* login to server */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_OK);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_last_reply = IMAPC_COMMAND_STATE_INVALID;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* send two commands */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "RETRY1");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "RETRY2");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* disconnect & reconnect automatically */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "DISCONNECT");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_error_string("reconnecting");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_DISCONNECTED));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* continue reconnection */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_OK));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_OK));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_resend_cmds_server(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "1 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("2 RETRY1"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("3 RETRY2"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("4 DISCONNECT"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect_and_wait(TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("5 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "5 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("2 RETRY1"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "2 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("3 RETRY2"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "3 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
a2328a1c60026f3d3d47c5c75a2e972fec86d5b4Timo Sirainen test_assert(i_stream_read_next_line(server.input) == NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_resend_commands(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc reconnect resend commands");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_reconnect_resend_cmds_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_resend_cmds_server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_resend_cmds_failed_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_command *cmd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* login to server */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_OK);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_last_reply = IMAPC_COMMAND_STATE_INVALID;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* send two commands */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "RETRY1");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "RETRY2");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* disconnect & try to reconnect automatically */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "DISCONNECT");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_error_string("reconnecting");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_DISCONNECTED));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_error_string("timed out");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_DISCONNECTED));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_DISCONNECTED));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_resend_cmds_failed_server(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "1 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("2 RETRY1"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("3 RETRY2"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("4 DISCONNECT"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect(&server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_resend_commands_failed(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc reconnect resend commands failed");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_reconnect_resend_cmds_failed_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_resend_cmds_failed_server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_mailbox_client(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_command *cmd;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_mailbox *box;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* login to server */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_set_login_callback(imapc_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_login(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(imapc_login_last_reply == IMAPC_COMMAND_STATE_OK);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_login_last_reply = IMAPC_COMMAND_STATE_INVALID;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* select a mailbox */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen box = imapc_client_mailbox_open(imapc_client, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_mailbox_set_reopen_cb(box, imapc_reopen_callback, box);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_mailbox_cmd(box, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "SELECT");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_OK));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* send a command */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_mailbox_cmd(box, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "RETRY");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* disconnect & reconnect automatically */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen cmd = imapc_client_cmd(imapc_client, imapc_command_callback, NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_command_send(cmd, "DISCONNECT");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_error_string("reconnecting");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_run(imapc_client);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_expect_no_more_errors();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_DISCONNECTED));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* continue reconnection */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_OK));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_cmd_last_reply_expect(IMAPC_COMMAND_STATE_OK));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen imapc_client_mailbox_close(&box);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_mailbox_server(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_wait_connection(&server, TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "1 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("2 SELECT"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "2 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("3 RETRY"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("4 DISCONNECT"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_server_disconnect_and_wait(TRUE);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("5 LOGIN \"testuser\" \"testpass\""));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "5 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("6 SELECT"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "6 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_assert(test_imapc_server_expect("3 RETRY"));
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen o_stream_nsend_str(server.output, "3 OK \r\n");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
a2328a1c60026f3d3d47c5c75a2e972fec86d5b4Timo Sirainen test_assert(i_stream_read_next_line(server.input) == NULL);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenstatic void test_imapc_reconnect_mailbox(void)
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_begin("imapc reconnect mailbox");
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_run_client_server(&set, test_imapc_reconnect_mailbox_client,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_mailbox_server);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_end();
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_client(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen enum imapc_capability capabilities;
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(imapc_client_get_capabilities(imapc_client, &capabilities) == 0);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(capabilities == (IMAPC_CAPABILITY_IMAP4REV1 |
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen IMAPC_CAPABILITY_UNSELECT |
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen IMAPC_CAPABILITY_QUOTA));
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_server(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_server_wait_connection(&server, TRUE);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(test_imapc_server_expect("1 LOGIN \"testuser\" \"testpass\""));
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen o_stream_nsend_str(server.output, "1 OK \r\n");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(test_imapc_server_expect("2 LOGOUT"));
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen o_stream_nsend_str(server.output, "2 OK \r\n");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(i_stream_read_next_line(server.input) == NULL);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_begin("imapc_client_get_capabilities()");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_run_client_server(&set, test_imapc_client_get_capabilities_client,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_imapc_client_get_capabilities_server);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_end();
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_reconnected_client(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen enum imapc_capability capabilities;
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_expect_errors(2);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(imapc_client_get_capabilities(imapc_client, &capabilities) == 0);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(capabilities == (IMAPC_CAPABILITY_IMAP4REV1 |
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen IMAPC_CAPABILITY_UNSELECT |
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen IMAPC_CAPABILITY_QUOTA));
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_expect_no_more_errors();
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_reconnected_server(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_server_wait_connection(&server, TRUE);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_server_disconnect_and_wait(TRUE);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(test_imapc_server_expect("2 LOGIN \"testuser\" \"testpass\""));
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen o_stream_nsend_str(server.output, "2 OK \r\n");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(test_imapc_server_expect("3 LOGOUT"));
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen o_stream_nsend_str(server.output, "3 OK \r\n");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(i_stream_read_next_line(server.input) == NULL);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_reconnected(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_begin("imapc_client_get_capabilities() reconnected");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_run_client_server(&set, test_imapc_client_get_capabilities_reconnected_client,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_imapc_client_get_capabilities_reconnected_server);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_end();
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_disconnected_client(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen enum imapc_capability capabilities;
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_expect_errors(4);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_assert(imapc_client_get_capabilities(imapc_client, &capabilities) < 0);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_expect_no_more_errors();
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_disconnected_server(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_server_wait_connection(&server, TRUE);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_server_disconnect_and_wait(TRUE);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainenstatic void test_imapc_client_get_capabilities_disconnected(void)
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen{
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen struct imapc_client_settings set = test_imapc_default_settings;
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_begin("imapc_client_get_capabilities() disconnected");
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_run_client_server(&set, test_imapc_client_get_capabilities_disconnected_client,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_imapc_client_get_capabilities_disconnected_server);
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_end();
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen}
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainenint main(int argc ATTR_UNUSED, char *argv[])
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen{
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen static void (*const test_functions[])(void) = {
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_connect_failed,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_banner_hangs,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_login_hangs,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_resend_commands,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_resend_commands_failed,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_reconnect_mailbox,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_imapc_client_get_capabilities,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_imapc_client_get_capabilities_reconnected,
a345bc2d9fbad3d48ea124285e85d574698eeb96Timo Sirainen test_imapc_client_get_capabilities_disconnected,
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen NULL
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen };
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen debug = null_strcmp(argv[1], "-D") == 0;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen test_imapc_default_settings.debug = debug;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen /* listen on localhost */
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen i_zero(&bind_ip);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen bind_ip.family = AF_INET;
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen bind_ip.u.ip4.s_addr = htonl(INADDR_LOOPBACK);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen return test_run(test_functions);
bac4b1dc3aa56cda1c9d4fdd7e673b94e5c559a9Timo Sirainen}