From: Stephan Bosch Date: Sat, 7 May 2016 12:53:29 +0000 (+0200) Subject: lib-auth-client: auth-master - Make request reply handling asynchronous X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=529e9d98cb637fc69bd5e8a3ed769b0031558c67;p=thirdparty%2Fdovecot%2Fcore.git lib-auth-client: auth-master - Make request reply handling asynchronous --- diff --git a/src/lib-auth-client/auth-master-private.h b/src/lib-auth-client/auth-master-private.h index 9e2f860123..d8f0fb04a1 100644 --- a/src/lib-auth-client/auth-master-private.h +++ b/src/lib-auth-client/auth-master-private.h @@ -12,7 +12,15 @@ #define MAX_INBUF_SIZE 8192 #define MAX_OUTBUF_SIZE 1024 +enum auth_master_request_state { + AUTH_MASTER_REQUEST_STATE_SENT = 0, + AUTH_MASTER_REQUEST_STATE_REPLIED, + AUTH_MASTER_REQUEST_STATE_FINISHED, + AUTH_MASTER_REQUEST_STATE_ABORTED, +}; + struct auth_master_request { + int refcount; pool_t pool; struct event *event; @@ -24,10 +32,14 @@ struct auth_master_request { size_t args_size; unsigned int id; + struct timeval create_stamp; + + enum auth_master_request_state state; auth_master_request_callback_t *callback; void *context; + bool sent:1; bool aborted:1; bool removed:1; bool in_callback:1; @@ -42,11 +54,11 @@ struct auth_master_connection { const char *auth_socket_path; enum auth_master_flags flags; + struct timeout *to_connect, *to_idle, *to_request; struct ioloop *ioloop, *prev_ioloop; - struct timeout *to; unsigned int id_counter; - + HASH_TABLE(void *, struct auth_master_request *) requests; struct auth_master_request *requests_head, *requests_tail; unsigned int requests_count; @@ -54,6 +66,7 @@ struct auth_master_connection { pid_t auth_server_pid; + bool in_timeout:1; bool connected:1; bool sent_handshake:1; bool waiting:1; @@ -63,6 +76,9 @@ struct auth_master_connection { * Request */ +unsigned int +auth_master_request_get_timeout_msecs(struct auth_master_request *req); + int auth_master_request_got_reply(struct auth_master_request **_req, const char *reply, const char *const *args); void auth_master_request_fail(struct auth_master_request **_req, @@ -72,7 +88,10 @@ void auth_master_request_fail(struct auth_master_request **_req, * Connection */ -void auth_master_set_io(struct auth_master_connection *conn); -void auth_master_unset_io(struct auth_master_connection *conn); +void auth_master_check_idle(struct auth_master_connection *conn); +void auth_master_stop_idle(struct auth_master_connection *conn); + +void auth_master_connection_update_timeout(struct auth_master_connection *conn); +void auth_master_connection_start_timeout(struct auth_master_connection *conn); #endif diff --git a/src/lib-auth-client/auth-master-request.c b/src/lib-auth-client/auth-master-request.c index a3c16784a8..7b80a58e8d 100644 --- a/src/lib-auth-client/auth-master-request.c +++ b/src/lib-auth-client/auth-master-request.c @@ -1,10 +1,13 @@ /* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" +#include "hash.h" #include "llist.h" #include "ioloop.h" #include "istream.h" #include "ostream.h" +#include "time-util.h" #include "master-service.h" #include "auth-master-private.h" @@ -16,6 +19,18 @@ static void auth_master_request_update_event(struct auth_master_request *req) t_strdup_printf("request [%u]: ", req->id)); } +unsigned int +auth_master_request_get_timeout_msecs(struct auth_master_request *req) +{ + struct timeval expires = req->create_stamp; + int msecs; + + timeval_add_msecs(&expires, req->conn->timeout_msecs); + + msecs = timeval_diff_msecs(&expires, &ioloop_timeval); + return (unsigned int)(msecs < 0 ? 0 : msecs); +} + static void auth_master_request_remove(struct auth_master_request *req) { struct auth_master_connection *conn = req->conn; @@ -24,29 +39,42 @@ static void auth_master_request_remove(struct auth_master_request *req) return; req->removed = TRUE; + if (req->sent) + hash_table_remove(conn->requests, POINTER_CAST(req->id)); DLLIST2_REMOVE(&conn->requests_head, &conn->requests_tail, req); conn->requests_count--; + auth_master_connection_update_timeout(conn); + auth_master_check_idle(conn); + if (conn->waiting) { i_assert(conn->ioloop != NULL); io_loop_stop(conn->ioloop); - } else if (conn->requests_head == NULL) { - auth_master_unset_io(conn); } } -static void auth_master_request_free(struct auth_master_request **_req) +static void auth_master_request_ref(struct auth_master_request *req) +{ + req->refcount++; +} + +static bool auth_master_request_unref(struct auth_master_request **_req) { struct auth_master_request *req = *_req; *_req = NULL; if (req == NULL) - return; + return TRUE; + + i_assert(req->refcount > 0); + if (--req->refcount > 0) + return TRUE; auth_master_request_remove(req); event_unref(&req->event); pool_unref(&req->pool); + return FALSE; } void auth_master_request_set_event(struct auth_master_request *req, @@ -64,7 +92,9 @@ static int auth_master_request_callback(struct auth_master_request *req, const struct auth_master_reply *mreply) { + struct auth_master_connection *conn = req->conn; auth_master_request_callback_t *callback = req->callback; + struct auth_master_request *tmp_req = req; int ret; req->callback = NULL; @@ -79,9 +109,21 @@ auth_master_request_callback(struct auth_master_request *req, if (callback == NULL) return 1; + if (conn->prev_ioloop != NULL) { + /* Don't let callback see that we've created our + internal ioloop in case it wants to add some ios + or timeouts. */ + current_ioloop = conn->prev_ioloop; + } + + auth_master_request_ref(tmp_req); req->in_callback = TRUE; ret = callback(mreply, req->context); req->in_callback = FALSE; + auth_master_request_unref(&tmp_req); + + if (conn->prev_ioloop != NULL) + current_ioloop = conn->ioloop; if (ret == 0) { /* Application expects more replies for this request. */ @@ -101,6 +143,9 @@ int auth_master_request_got_reply(struct auth_master_request **_req, i_assert(!req->in_callback); + if (req->state < AUTH_MASTER_REQUEST_STATE_FINISHED) + req->state = AUTH_MASTER_REQUEST_STATE_REPLIED; + e_debug(req->event, "Got reply: %s %s", reply, t_strarray_join(args, " ")); @@ -116,8 +161,10 @@ int auth_master_request_got_reply(struct auth_master_request **_req, io_loop_stop(conn->ioloop); } } else { + if (req->state < AUTH_MASTER_REQUEST_STATE_FINISHED) + req->state = AUTH_MASTER_REQUEST_STATE_FINISHED; auth_master_request_remove(req); - auth_master_request_free(&req); + auth_master_request_unref(&req); } return ret; } @@ -133,10 +180,14 @@ void auth_master_request_abort(struct auth_master_request **_req) if (req->in_callback) return; + if (req->state >= AUTH_MASTER_REQUEST_STATE_FINISHED) + return; + req->state = AUTH_MASTER_REQUEST_STATE_ABORTED; + e_debug(req->event, "Aborted"); auth_master_request_remove(req); - auth_master_request_free(&req); + auth_master_request_unref(&req); } void auth_master_request_fail(struct auth_master_request **_req, @@ -190,7 +241,9 @@ auth_master_request(struct auth_master_connection *conn, const char *cmd, pool = pool_alloconly_create("auth_master_request", 256 + args_size); req = p_new(pool, struct auth_master_request, 1); req->pool = pool; + req->refcount = 1; req->conn = conn; + req->create_stamp = ioloop_timeval; if (++conn->id_counter == 0) { /* avoid zero */ @@ -224,14 +277,15 @@ int auth_master_request_submit(struct auth_master_request **_req) if (req == NULL) return -1; - auth_master_set_io(conn); - if (!conn->connected) { if (auth_master_connect(conn) < 0) { - auth_master_unset_io(conn); - auth_master_request_free(_req); + // FIXME: handle + /* we couldn't connect to auth now, + so we probably can't in future either. */ + auth_master_request_unref(_req); return -1; } + // FIXME: allow asynchronous connection i_assert(conn->connected); connection_input_resume(&conn->conn); } @@ -253,11 +307,17 @@ int auth_master_request_submit(struct auth_master_request **_req) if (o_stream_flush(conn->conn.output) < 0) { e_error(conn->conn.event, "write(auth socket) failed: %s", o_stream_get_error(conn->conn.output)); - auth_master_unset_io(conn); auth_master_disconnect(conn); - auth_master_request_free(_req); + auth_master_request_unref(_req); return -1; } + + hash_table_insert(conn->requests, POINTER_CAST(req->id), req); + req->sent = TRUE; + + auth_master_connection_start_timeout(conn); + auth_master_stop_idle(conn); + return 0; } @@ -274,8 +334,25 @@ static void auth_master_request_stop(struct auth_master_request *req) bool auth_master_request_wait(struct auth_master_request *req) { struct auth_master_connection *conn = req->conn; + struct ioloop *ioloop, *prev_ioloop; + enum auth_master_request_state last_state; struct timeout *to; - bool was_corked = FALSE; + bool waiting = conn->waiting, was_corked = FALSE, freed; + + if (req->state >= AUTH_MASTER_REQUEST_STATE_FINISHED) + return TRUE; + + i_assert(auth_master_request_count(conn) > 0); + + if ((conn->flags & AUTH_MASTER_FLAG_NO_INNER_IOLOOP) != 0) + ioloop = conn->ioloop; + else { + prev_ioloop = conn->ioloop; + if (!waiting) + conn->prev_ioloop = prev_ioloop; + ioloop = io_loop_create(); + auth_master_switch_ioloop_to(conn, ioloop); + } if (conn->conn.input != NULL && i_stream_get_data_size(conn->conn.input) > 0) @@ -285,21 +362,41 @@ bool auth_master_request_wait(struct auth_master_request *req) o_stream_uncork(conn->conn.output); } + /* either we're waiting for network I/O or we're getting out of a + callback using timeout_add_short(0) */ + i_assert(io_loop_have_ios(ioloop) || + io_loop_have_immediate_timeouts(ioloop)); + + auth_master_request_ref(req); + req->state = AUTH_MASTER_REQUEST_STATE_SENT; + /* add stop handler */ to = timeout_add_short(100, auth_master_request_stop, req); conn->waiting = TRUE; - io_loop_run(conn->ioloop); - conn->waiting = FALSE; + while (req->state < AUTH_MASTER_REQUEST_STATE_REPLIED) + io_loop_run(conn->ioloop); + conn->waiting = waiting; timeout_remove(&to); if (conn->conn.output != NULL && was_corked) o_stream_cork(conn->conn.output); - if (conn->requests_head != NULL) - return FALSE; + last_state = req->state; + freed = !auth_master_request_unref(&req); + + if ((conn->flags & AUTH_MASTER_FLAG_NO_INNER_IOLOOP) == 0) { + auth_master_switch_ioloop_to(conn, prev_ioloop); + io_loop_destroy(&ioloop); + if (!waiting) + conn->prev_ioloop = NULL; + } + + return (freed || last_state >= AUTH_MASTER_REQUEST_STATE_FINISHED); +} - auth_master_unset_io(conn); - return TRUE; +unsigned int auth_master_request_count(struct auth_master_connection *conn) +{ + return conn->requests_count; } diff --git a/src/lib-auth-client/auth-master.c b/src/lib-auth-client/auth-master.c index d6579738f4..9cb9b2c5fe 100644 --- a/src/lib-auth-client/auth-master.c +++ b/src/lib-auth-client/auth-master.c @@ -3,6 +3,7 @@ #include "lib.h" #include "lib-signals.h" #include "array.h" +#include "hash.h" #include "ioloop.h" #include "eacces-error.h" #include "net.h" @@ -10,6 +11,7 @@ #include "ostream.h" #include "str.h" #include "strescape.h" +#include "time-util.h" #include "auth-master-private.h" @@ -60,6 +62,7 @@ auth_master_init(const char *auth_socket_path, enum auth_master_flags flags) conn = p_new(pool, struct auth_master_connection, 1); conn->pool = pool; conn->refcount = 1; + conn->ioloop = current_ioloop; conn->auth_socket_path = p_strdup(pool, auth_socket_path); conn->flags = flags; conn->timeout_msecs = 1000*MASTER_AUTH_LOOKUP_TIMEOUT_SECS; @@ -79,6 +82,13 @@ auth_master_init(const char *auth_socket_path, enum auth_master_flags flags) if ((flags & AUTH_MASTER_FLAG_NO_INNER_IOLOOP) != 0) conn->ioloop = current_ioloop; + + hash_table_create_direct(&conn->requests, pool, 0); + + /* Try to use auth request ID numbers from wider range to ease + debugging. */ + conn->id_counter = i_rand_limit(32767) * 131072U; + return conn; } @@ -97,13 +107,16 @@ auth_master_connection_failure(struct auth_master_connection *conn, conn->connected = FALSE; conn->sent_handshake = FALSE; - timeout_remove(&conn->to); + timeout_remove(&conn->to_connect); + timeout_remove(&conn->to_request); + timeout_remove(&conn->to_idle); while (conn->requests_head != NULL) { req = conn->requests_head; auth_master_request_fail(&req, reason); } + i_assert(hash_table_count(conn->requests) == 0); if (conn->ioloop != NULL && conn->waiting) io_loop_stop(conn->ioloop); @@ -136,6 +149,7 @@ auth_master_unref(struct auth_master_connection **_conn) auth_master_disconnect(conn); connection_deinit(&conn->conn); connection_list_deinit(&clist); + hash_table_destroy(&conn->requests); pool_unref(&conn->pool); } @@ -187,17 +201,68 @@ static void auth_master_destroy(struct connection *_conn) } } -static void auth_request_timeout(struct auth_master_connection *conn) +static void +auth_master_connection_timeout(struct auth_master_connection *conn) { - if (!connection_handshake_received(&conn->conn)) { - e_error(conn->conn.event, "Connecting timed out"); - auth_master_connection_failure(conn, "Connecting timed out"); + struct auth_master_request *req; + const char *reason; + + timeout_remove(&conn->to_request); + + conn->in_timeout = TRUE; + req = conn->requests_head; + while (req != NULL && auth_master_request_get_timeout_msecs(req) == 0) { + struct auth_master_request *req_next = req->next; + int msecs; + + if (req->in_callback) { + req = req_next; + continue; + } + + msecs = timeval_diff_msecs(&ioloop_timeval, &req->create_stamp); + reason = t_strdup_printf( + "Auth server request timed out after %u.%03u secs", + msecs / 1000, msecs % 1000); + auth_master_request_fail(&req, reason); + + req = req_next; + } + conn->in_timeout = FALSE; + + auth_master_connection_update_timeout(conn); +} + +void auth_master_connection_update_timeout(struct auth_master_connection *conn) +{ + struct auth_master_request *req; + + if (conn->in_timeout) + return; + if (!conn->connected) { + i_assert(conn->to_request == NULL); return; } - e_error(conn->conn.event, "Request timed out"); - struct auth_master_request *req = conn->requests_head; - auth_master_request_abort(&req); + req = conn->requests_head; + while (req != NULL && req->in_callback) + req = req->next; + + timeout_remove(&conn->to_request); + if (req == NULL) + return; + + conn->to_request = timeout_add_to( + conn->ioloop, auth_master_request_get_timeout_msecs(req), + auth_master_connection_timeout, conn); +} + +void auth_master_connection_start_timeout(struct auth_master_connection *conn) +{ + if (conn->to_request != NULL || conn->to_connect != NULL) + return; + + auth_master_connection_update_timeout(conn); } static int @@ -233,6 +298,10 @@ auth_master_handshake_line(struct connection *_conn, const char *line) "Authentication server sent invalid SPID: %s", line); return -1; } + + /* Handshake complete */ + timeout_remove(&conn->to_connect); + auth_master_connection_update_timeout(conn); return 1; } @@ -256,10 +325,11 @@ auth_master_handle_input(struct auth_master_connection *conn, return -1; } - req = conn->requests_head; - if (req == NULL || id != req->id) { - e_error(conn->conn.event, - "Auth server sent reply with unknown ID %u", id); + req = hash_table_lookup(conn->requests, POINTER_CAST(id)); + if (req == NULL) { + e_debug(conn->conn.event, + "Auth server sent reply with unknown ID %u " + "(this request was probably aborted)", id); return -1; } @@ -316,11 +386,30 @@ static void auth_master_connected(struct connection *_conn, bool success) conn->connected = TRUE; } +static void auth_master_connect_timeout(struct auth_master_connection *conn) +{ + e_error(conn->conn.event, "Connecting timed out"); + auth_master_connection_failure(conn, "Connecting timed out"); +} + +static void +auth_master_delayed_connect_failure(struct auth_master_connection *conn) +{ + e_debug(conn->conn.event, "Delayed connect failure"); + + i_assert(conn->to_connect != NULL); + timeout_remove(&conn->to_connect); + auth_master_connection_failure(conn, "Connect failed"); +} + int auth_master_connect(struct auth_master_connection *conn) { if (conn->connected) return 0; + i_assert(conn->to_connect == NULL); + i_assert(conn->to_request == NULL); + if (conn->ioloop != NULL) connection_switch_ioloop_to(&conn->conn, conn->ioloop); if (connection_client_connect(&conn->conn) < 0) { @@ -332,59 +421,61 @@ int auth_master_connect(struct auth_master_connection *conn) e_error(conn->conn.event, "connect(%s) failed: %m", conn->auth_socket_path); } + conn->to_connect = timeout_add_to( + conn->ioloop, 0, + auth_master_delayed_connect_failure, conn); return -1; } - connection_input_halt(&conn->conn); + conn->to_connect = timeout_add_to(conn->ioloop, conn->timeout_msecs, + auth_master_connect_timeout, conn); return 0; } +void auth_master_switch_ioloop_to(struct auth_master_connection *conn, + struct ioloop *ioloop) +{ + conn->ioloop = ioloop; + + if (conn->to_connect != NULL) { + conn->to_connect = + io_loop_move_timeout_to(ioloop, &conn->to_connect); + } + if (conn->to_request != NULL) { + conn->to_request = + io_loop_move_timeout_to(ioloop, &conn->to_request); + } + if (conn->to_idle != NULL) + conn->to_idle = io_loop_move_timeout_to(ioloop, &conn->to_idle); + connection_switch_ioloop_to(&conn->conn, conn->ioloop); +} + +void auth_master_switch_ioloop(struct auth_master_connection *conn) +{ + auth_master_switch_ioloop_to(conn, current_ioloop); +} static void auth_master_idle_timeout(struct auth_master_connection *conn) { auth_master_disconnect(conn); } -void auth_master_set_io(struct auth_master_connection *conn) +void auth_master_check_idle(struct auth_master_connection *conn) { - if (conn->ioloop != NULL) + if ((conn->flags & AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT) != 0) return; - - timeout_remove(&conn->to); - - conn->prev_ioloop = current_ioloop; - conn->ioloop = io_loop_create(); - connection_switch_ioloop_to(&conn->conn, conn->ioloop); - if (conn->connected) - connection_input_resume(&conn->conn); - - conn->to = timeout_add_to(conn->ioloop, conn->timeout_msecs, - auth_request_timeout, conn); + if (current_ioloop == NULL) + return; + i_assert(conn->to_idle == NULL); + if (conn->requests_head != NULL) + return; + conn->to_idle = timeout_add_to(conn->ioloop, + 1000 * AUTH_MASTER_IDLE_SECS, + auth_master_idle_timeout, conn); } -void auth_master_unset_io(struct auth_master_connection *conn) +void auth_master_stop_idle(struct auth_master_connection *conn) { - if (conn->ioloop == NULL) - return; - - if (conn->prev_ioloop != NULL) { - io_loop_set_current(conn->prev_ioloop); - } - if ((conn->flags & AUTH_MASTER_FLAG_NO_INNER_IOLOOP) == 0) { - io_loop_set_current(conn->ioloop); - connection_switch_ioloop_to(&conn->conn, conn->ioloop); - connection_input_halt(&conn->conn); - timeout_remove(&conn->to); - io_loop_destroy(&conn->ioloop); - } - - if ((conn->flags & AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT) == 0) { - if (conn->prev_ioloop == NULL) - auth_master_disconnect(conn); - else if (conn->to == NULL) { - conn->to = timeout_add(1000*AUTH_MASTER_IDLE_SECS, - auth_master_idle_timeout, conn); - } - } + timeout_remove(&conn->to_idle); } /* @@ -848,8 +939,6 @@ auth_user_list_reply_callback(const struct auth_master_reply *reply, { const char *const *args = reply->args; - timeout_reset(ctx->conn->to); - if (reply->errormsg != NULL) { e_error(ctx->event, "User listing failed: %s", reply->errormsg); ctx->req = NULL; @@ -892,6 +981,8 @@ auth_master_user_list_init(struct auth_master_connection *conn, struct auth_master_user_list_ctx *ctx; string_t *args; + i_assert(auth_master_request_count(conn) == 0); + ctx = i_new(struct auth_master_user_list_ctx, 1); ctx->conn = conn; ctx->username = str_new(default_pool, 128); @@ -917,8 +1008,8 @@ auth_master_user_list_init(struct auth_master_connection *conn, ctx->failed = TRUE; else auth_master_request_set_event(ctx->req, ctx->event); - if (conn->prev_ioloop != NULL) - io_loop_set_current(conn->prev_ioloop); + + connection_input_halt(&conn->conn); return ctx; } @@ -936,22 +1027,25 @@ auth_master_user_do_list_next(struct auth_master_user_list_ctx *ctx) str_truncate(ctx->username, 0); /* try to read already buffered input */ - line = i_stream_next_line(conn->conn.input); - if (line != NULL) { - T_BEGIN { - conn->conn.v.input_line(&conn->conn, line); - } T_END; + if (conn->to_connect == NULL) { + line = i_stream_next_line(conn->conn.input); + if (line != NULL) { + T_BEGIN { + conn->conn.v.input_line(&conn->conn, line); + } T_END; + } + if (ctx->finished || ctx->failed) + return NULL; + if (str_len(ctx->username) > 0) + return str_c(ctx->username); } - if (ctx->finished || ctx->failed) - return NULL; - if (str_len(ctx->username) > 0) - return str_c(ctx->username); /* wait for more data */ - io_loop_set_current(conn->ioloop); + if (!conn->conn.disconnected) + connection_input_resume(&conn->conn); if (auth_master_request_wait(ctx->req)) ctx->req = NULL; - io_loop_set_current(conn->prev_ioloop); + connection_input_halt(&conn->conn); if (ctx->finished || ctx->failed) return NULL; @@ -973,6 +1067,7 @@ const char *auth_master_user_list_next(struct auth_master_user_list_ctx *ctx) int auth_master_user_list_deinit(struct auth_master_user_list_ctx **_ctx) { struct auth_master_user_list_ctx *ctx = *_ctx; + struct auth_master_connection *conn = ctx->conn; int ret = ctx->failed ? -1 : 0; *_ctx = NULL; @@ -991,6 +1086,9 @@ int auth_master_user_list_deinit(struct auth_master_user_list_ctx **_ctx) } auth_master_request_abort(&ctx->req); + if (!conn->conn.disconnected) + connection_input_resume(&conn->conn); + str_free(&ctx->username); event_unref(&ctx->event); i_free(ctx); diff --git a/src/lib-auth-client/auth-master.h b/src/lib-auth-client/auth-master.h index ed1cdb9fb2..bf7b93f76b 100644 --- a/src/lib-auth-client/auth-master.h +++ b/src/lib-auth-client/auth-master.h @@ -3,6 +3,7 @@ #include "net.h" +struct ioloop; struct auth_master_request; struct auth_master_reply; struct auth_master_connection; @@ -52,6 +53,8 @@ void auth_master_request_set_event(struct auth_master_request *req, void auth_master_request_abort(struct auth_master_request **_req); bool auth_master_request_wait(struct auth_master_request *req); +unsigned int auth_master_request_count(struct auth_master_connection *conn); + /* * Connection */ @@ -69,6 +72,10 @@ void auth_master_set_timeout(struct auth_master_connection *conn, /* Returns the auth_socket_path */ const char *auth_master_get_socket_path(struct auth_master_connection *conn); +void auth_master_switch_ioloop_to(struct auth_master_connection *conn, + struct ioloop *ioloop); +void auth_master_switch_ioloop(struct auth_master_connection *conn); + /* * Lookup common */ diff --git a/src/lib-auth-client/test-auth-master.c b/src/lib-auth-client/test-auth-master.c index 7b23ce7b8e..7790cfe26c 100644 --- a/src/lib-auth-client/test-auth-master.c +++ b/src/lib-auth-client/test-auth-master.c @@ -454,7 +454,9 @@ static bool test_client_passdb_timeout(void) ret = test_client_passdb_lookup_simple("holger", FALSE, &error); test_out("run (ret == -1)", ret == -1); - test_assert(error == NULL); + test_assert(error != NULL && + str_begins_with( + error, "Auth server request timed out after")); return FALSE; } @@ -500,7 +502,6 @@ static void test_passdb_fail(void) test_end(); test_begin("passdb timeout"); - test_expect_error_string("Request timed out"); test_run_client_server(test_client_passdb_timeout, test_server_passdb_fail); test_end(); @@ -641,7 +642,9 @@ static bool test_client_userdb_timeout(void) ret = test_client_userdb_lookup_simple("holger", FALSE, &error); test_out("run (ret == -1)", ret == -1); - test_assert(error == NULL); + test_assert(error != NULL && + str_begins_with( + error, "Auth server request timed out after")); return FALSE; } @@ -687,7 +690,6 @@ static void test_userdb_fail(void) test_end(); test_begin("userdb timeout"); - test_expect_error_string("Request timed out"); test_run_client_server(test_client_userdb_timeout, test_server_userdb_fail); test_end();