Mercurial > dovecot > core-2.2
changeset 20359:bd15bf4e46f5
lib-http: test-http-payload: Added tests for the use of nested ioloops.
author | Stephan Bosch <stephan@dovecot.fi> |
---|---|
date | Tue, 24 May 2016 03:11:07 +0200 |
parents | 075b812a6e6e |
children | 2ce144c4dbd7 |
files | src/lib-http/test-http-payload.c |
diffstat | 1 files changed, 142 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-http/test-http-payload.c Mon May 23 21:57:18 2016 +0200 +++ b/src/lib-http/test-http-payload.c Tue May 24 03:11:07 2016 +0200 @@ -31,11 +31,15 @@ static size_t read_server_partial = 0; static size_t read_client_partial = 0; static unsigned int test_max_pending = 200; +static unsigned int client_ioloop_nesting = 0; static struct ip_addr bind_ip; static in_port_t bind_port = 0; static int fd_listen = -1; static pid_t server_pid = (pid_t)-1; +static struct ioloop *ioloop_nested = NULL; +static unsigned ioloop_nested_first = 0; +static unsigned ioloop_nested_last = 0; /* * Test files @@ -583,6 +587,9 @@ */ struct test_client_request { + struct test_client_request *prev, *next; + struct http_client_request *hreq; + struct io *io; struct istream *payload; struct istream *file; @@ -590,8 +597,20 @@ }; static struct http_client *http_client; +static struct test_client_request *client_requests; static unsigned int client_files_first, client_files_last; +static struct test_client_request * +test_client_request_new(void) +{ + struct test_client_request *tcreq; + + tcreq = i_new(struct test_client_request, 1); + DLLIST_PREPEND(&client_requests, tcreq); + + return tcreq; +} + static void test_client_request_destroy(void *context) { @@ -604,25 +623,41 @@ i_stream_unref(&tcreq->payload); if (tcreq->file != NULL) i_stream_unref(&tcreq->file); + + DLLIST_REMOVE(&client_requests, tcreq); i_free(tcreq); } +static void +test_client_requests_switch_ioloop(void) +{ + struct test_client_request *tcreq; + + for (tcreq = client_requests; tcreq != NULL; + tcreq = tcreq->next) { + if (tcreq->io != NULL) + tcreq->io = io_loop_move_io(&tcreq->io); + if (tcreq->payload != NULL) + i_stream_switch_ioloop(tcreq->payload); + } +} + /* download */ static void test_client_download_continue(void); static void -test_client_download_finished(struct test_client_request *tcreq) +test_client_download_finished(unsigned int files_idx) { const char **paths; unsigned int count; paths = array_get_modifiable(&files, &count); - i_assert(tcreq->files_idx < count); + i_assert(files_idx < count); i_assert(client_files_first < count); - i_assert(paths[tcreq->files_idx] != NULL); + i_assert(paths[files_idx] != NULL); - paths[tcreq->files_idx] = NULL; + paths[files_idx] = NULL; test_client_download_continue(); } @@ -632,6 +667,7 @@ struct istream *payload = tcreq->payload; const unsigned char *pdata, *fdata; size_t psize, fsize, pleft; + unsigned int files_idx = tcreq->files_idx; off_t ret; /* read payload */ @@ -689,13 +725,13 @@ tcreq->files_idx); } - /* finished */ - test_client_download_finished(tcreq); - /* dereference payload stream; finishes the request */ tcreq->payload = NULL; io_remove(&tcreq->io); /* holds a reference too */ i_stream_unref(&payload); + + /* finished */ + test_client_download_finished(files_idx); } } @@ -741,7 +777,7 @@ path, resp->status, resp->reason); } i_stream_unref(&fstream); - test_client_download_finished(tcreq); + test_client_download_finished(tcreq->files_idx); return; } @@ -752,7 +788,7 @@ path, tcreq->files_idx); } i_stream_unref(&fstream); - test_client_download_finished(tcreq); + test_client_download_finished(tcreq->files_idx); return; } @@ -806,7 +842,7 @@ client_files_last++) { const char *path = paths[client_files_last]; - tcreq = i_new(struct test_client_request, 1); + tcreq = test_client_request_new(); tcreq->files_idx = client_files_last; if (debug) { @@ -814,7 +850,7 @@ "retrieving %s [%u]", path, tcreq->files_idx); } - hreq = http_client_request(http_client, + hreq = tcreq->hreq = http_client_request(http_client, "GET", net_ip2addr(&bind_ip), t_strconcat("/download/", path, NULL), test_client_download_response, tcreq); @@ -841,17 +877,17 @@ static void test_client_echo_continue(void); static void -test_client_echo_finished(struct test_client_request *tcreq) +test_client_echo_finished(unsigned int files_idx) { const char **paths; unsigned int count; paths = array_get_modifiable(&files, &count); - i_assert(tcreq->files_idx < count); + i_assert(files_idx < count); i_assert(client_files_first < count); - i_assert(paths[tcreq->files_idx] != NULL); + i_assert(paths[files_idx] != NULL); - paths[tcreq->files_idx] = NULL; + paths[files_idx] = NULL; test_client_echo_continue(); } @@ -861,6 +897,7 @@ struct istream *payload = tcreq->payload; const unsigned char *pdata, *fdata; size_t psize, fsize, pleft; + unsigned int files_idx = tcreq->files_idx; off_t ret; /* read payload */ @@ -918,13 +955,13 @@ tcreq->files_idx); } - /* finished */ - test_client_echo_finished(tcreq); - /* dereference payload stream; finishes the request */ tcreq->payload = NULL; io_remove(&tcreq->io); /* holds a reference too */ i_stream_unref(&payload); + + /* finished */ + test_client_echo_finished(files_idx); } } @@ -982,7 +1019,7 @@ path, tcreq->files_idx); } i_stream_unref(&fstream); - test_client_echo_finished(tcreq); + test_client_echo_finished(tcreq->files_idx); return; } @@ -1001,7 +1038,7 @@ struct test_client_request *tcreq; struct http_client_request *hreq; const char **paths; - unsigned int count; + unsigned int count, first_submitted; paths = array_get_modifiable(&files, &count); @@ -1010,7 +1047,7 @@ i_assert(client_files_first <= client_files_last); for (; client_files_first < client_files_last && - paths[client_files_first] == NULL; client_files_first++) + paths[client_files_first] == NULL; client_files_first++); if (debug) { i_debug("test client: echo: " @@ -1020,7 +1057,9 @@ if (debug && client_files_first < count) { const char *path = paths[client_files_first]; i_debug("test client: echo: " - "next blocking: %s", (path == NULL ? "none" : path)); + "next blocking: %s [%d]", + (path == NULL ? "none" : path), + client_files_first); } if (client_files_first >= count) { @@ -1028,6 +1067,7 @@ return; } + first_submitted = client_files_last; for (; client_files_last < count && (client_files_last - client_files_first) < test_max_pending; client_files_last++) { @@ -1051,10 +1091,10 @@ path, client_files_last); } - tcreq = i_new(struct test_client_request, 1); + tcreq = test_client_request_new(); tcreq->files_idx = client_files_last; - hreq = http_client_request(http_client, + hreq = tcreq->hreq = http_client_request(http_client, "PUT", net_ip2addr(&bind_ip), t_strconcat("/echo/", path, NULL), test_client_echo_response, tcreq); @@ -1067,6 +1107,60 @@ i_stream_unref(&fstream); } + + /* run nested ioloop (if requested) if new requests cross a nesting + boundary */ + if (ioloop_nested != NULL) { + unsigned int i; + + i_assert(ioloop_nested_first <= count); + i_assert(ioloop_nested_last <= count); + for (i = ioloop_nested_first; i < ioloop_nested_last; i++) { + if (paths[i] != NULL) { + if (debug) { + i_debug("test client: " + "not leaving ioloop [%u]", i); + } + break; + } + } + + if (i == ioloop_nested_last) + io_loop_stop(ioloop_nested); + } else if (client_ioloop_nesting > 0 && + ((client_files_last / client_ioloop_nesting) != + (first_submitted / client_ioloop_nesting)) ) { + struct ioloop *prev_ioloop = current_ioloop; + + ioloop_nested_first = first_submitted; + ioloop_nested_last = first_submitted + client_ioloop_nesting; + if (ioloop_nested_last > client_files_last) + ioloop_nested_last = client_files_last; + + if (debug) { + i_debug("test client: echo: entering ioloop for %u...%u", + ioloop_nested_first, ioloop_nested_last); + } + + ioloop_nested = io_loop_create(); + http_client_switch_ioloop(http_client); + test_client_requests_switch_ioloop(); + + io_loop_run(ioloop_nested); + + io_loop_set_current(prev_ioloop); + http_client_switch_ioloop(http_client); + test_client_requests_switch_ioloop(); + io_loop_set_current(ioloop_nested); + io_loop_destroy(&ioloop_nested); + ioloop_nested = NULL; + + if (debug) { + i_debug("test client: echo: leaving ioloop for %u...%u", + ioloop_nested_first, ioloop_nested_last); + } + ioloop_nested_first = ioloop_nested_last = 0; + } } static void @@ -1128,6 +1222,7 @@ if (debug) i_debug("server: PID=%s", my_pid); /* child: server */ + ioloop_nested = FALSE; ioloop = io_loop_create(); test_server_init(server_set); io_loop_run(ioloop); @@ -1139,6 +1234,7 @@ i_debug("client: PID=%s", my_pid); i_close_fd(&fd_listen); /* parent: client */ + ioloop_nested = FALSE; ioloop = io_loop_create(); client_init(client_set); io_loop_run(ioloop); @@ -1247,6 +1343,7 @@ blocking = FALSE; request_100_continue = FALSE; read_server_partial = 0; + client_ioloop_nesting = 0; test_run_sequential(test_client_download); test_run_pipeline(test_client_download); test_run_parallel(test_client_download); @@ -1259,6 +1356,7 @@ blocking = TRUE; request_100_continue = FALSE; read_server_partial = 0; + client_ioloop_nesting = 0; test_run_sequential(test_client_download); test_run_pipeline(test_client_download); test_run_parallel(test_client_download); @@ -1271,6 +1369,7 @@ blocking = FALSE; request_100_continue = FALSE; read_server_partial = 0; + client_ioloop_nesting = 0; test_run_sequential(test_client_echo); test_run_pipeline(test_client_echo); test_run_parallel(test_client_echo); @@ -1283,6 +1382,7 @@ blocking = TRUE; request_100_continue = FALSE; read_server_partial = 0; + client_ioloop_nesting = 0; test_run_sequential(test_client_echo); test_run_pipeline(test_client_echo); test_run_parallel(test_client_echo); @@ -1295,6 +1395,7 @@ blocking = FALSE; request_100_continue = TRUE; read_server_partial = 0; + client_ioloop_nesting = 0; test_run_sequential(test_client_echo); test_run_pipeline(test_client_echo); test_run_parallel(test_client_echo); @@ -1307,6 +1408,7 @@ blocking = TRUE; request_100_continue = TRUE; read_server_partial = 0; + client_ioloop_nesting = 0; test_run_sequential(test_client_echo); test_run_pipeline(test_client_echo); test_run_parallel(test_client_echo); @@ -1319,6 +1421,7 @@ blocking = FALSE; request_100_continue = FALSE; read_server_partial = 1024; + client_ioloop_nesting = 0; test_run_sequential(test_client_echo); test_run_pipeline(test_client_echo); test_run_parallel(test_client_echo); @@ -1337,6 +1440,7 @@ blocking = TRUE; request_100_continue = FALSE; read_server_partial = 1024; + client_ioloop_nesting = 0; test_run_sequential(test_client_echo); test_run_pipeline(test_client_echo); test_run_parallel(test_client_echo); @@ -1356,6 +1460,7 @@ request_100_continue = FALSE; read_server_partial = 0; read_client_partial = 1024; + client_ioloop_nesting = 0; test_run_sequential(test_client_download); test_run_pipeline(test_client_download); test_run_parallel(test_client_download); @@ -1371,6 +1476,18 @@ test_end(); } +static void test_download_client_nested_ioloop(void) +{ + test_begin("http payload echo (client nested ioloop)"); + blocking = FALSE; + request_100_continue = FALSE; + read_server_partial = 0; + read_client_partial = 0; + client_ioloop_nesting = 10; + test_run_parallel(test_client_echo); + test_end(); +} + static void (*test_functions[])(void) = { test_download_server_nonblocking, test_download_server_blocking, @@ -1381,6 +1498,7 @@ test_echo_server_nonblocking_partial, test_echo_server_blocking_partial, test_download_client_partial, + test_download_client_nested_ioloop, NULL };