diff options
Diffstat (limited to 'tests/connection-test.c')
-rw-r--r-- | tests/connection-test.c | 509 |
1 files changed, 334 insertions, 175 deletions
diff --git a/tests/connection-test.c b/tests/connection-test.c index ddf0c988..8f8c74be 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#include <gio/gnetworking.h> + SoupServer *server; SoupURI *base_uri; GMutex server_mutex; @@ -164,7 +166,7 @@ do_content_length_framing_test (void) SoupURI *request_uri; goffset declared_length; - debug_printf (1, "\nInvalid Content-Length framing tests\n"); + g_test_bug ("611481"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -172,21 +174,14 @@ do_content_length_framing_test (void) request_uri = soup_uri_new_with_base (base_uri, "/content-length/long"); msg = soup_message_new_from_uri ("GET", request_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } else { - declared_length = soup_message_headers_get_content_length (msg->response_headers); - debug_printf (2, " Content-Length: %lu, body: %s\n", - (gulong)declared_length, msg->response_body->data); - if (msg->response_body->length >= declared_length) { - debug_printf (1, " Body length %lu >= declared length %lu\n", - (gulong)msg->response_body->length, - (gulong)declared_length); - errors++; - } - } + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + declared_length = soup_message_headers_get_content_length (msg->response_headers); + debug_printf (2, " Content-Length: %lu, body: %s\n", + (gulong)declared_length, msg->response_body->data); + g_assert_cmpint (msg->response_body->length, <, declared_length); + soup_uri_free (request_uri); g_object_unref (msg); @@ -194,21 +189,12 @@ do_content_length_framing_test (void) request_uri = soup_uri_new_with_base (base_uri, "/content-length/noclose"); msg = soup_message_new_from_uri ("GET", request_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } else { - declared_length = soup_message_headers_get_content_length (msg->response_headers); - debug_printf (2, " Content-Length: %lu, body: %s\n", - (gulong)declared_length, msg->response_body->data); - if (msg->response_body->length != declared_length) { - debug_printf (1, " Body length %lu != declared length %lu\n", - (gulong)msg->response_body->length, - (gulong)declared_length); - errors++; - } - } + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + declared_length = soup_message_headers_get_content_length (msg->response_headers); + g_assert_cmpint (msg->response_body->length, ==, declared_length); + soup_uri_free (request_uri); g_object_unref (msg); @@ -232,12 +218,11 @@ request_started_socket_collector (SoupSession *session, SoupMessage *msg, * two consecutive sockets. */ sockets[i] = g_object_ref (socket); - return; + break; } } - debug_printf (1, " socket queue overflowed!\n"); - errors++; + soup_test_assert (i < 4, "socket queue overflowed"); } static void @@ -257,14 +242,10 @@ do_timeout_test_for_session (SoupSession *session) msg = soup_message_new_from_uri ("GET", timeout_uri); soup_uri_free (timeout_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + if (sockets[1]) { - debug_printf (1, " Message was retried??\n"); - errors++; + soup_test_assert (sockets[1] == NULL, "Message was retried"); sockets[1] = sockets[2] = sockets[3] = NULL; } g_object_unref (msg); @@ -272,24 +253,16 @@ do_timeout_test_for_session (SoupSession *session) debug_printf (1, " Second message\n"); msg = soup_message_new_from_uri ("GET", base_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - if (sockets[1] != sockets[0]) { - debug_printf (1, " Message was not retried on existing connection\n"); - errors++; - } else if (!sockets[2]) { - debug_printf (1, " Message was not retried after disconnect\n"); - errors++; - } else if (sockets[2] == sockets[1]) { - debug_printf (1, " Message was retried on closed connection??\n"); - errors++; - } else if (sockets[3]) { - debug_printf (1, " Message was retried again??\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_assert (sockets[1] == sockets[0], + "Message was not retried on existing connection"); + soup_test_assert (sockets[2] != NULL, + "Message was not retried after disconnect"); + soup_test_assert (sockets[2] != sockets[1], + "Message was retried on closed connection"); + soup_test_assert (sockets[3] == NULL, + "Message was retried again"); g_object_unref (msg); for (i = 0; sockets[i]; i++) @@ -299,7 +272,6 @@ do_timeout_test_for_session (SoupSession *session) static void do_timeout_req_test_for_session (SoupSession *session) { - SoupRequester *requester; SoupRequest *req; SoupMessage *msg; GInputStream *stream; @@ -308,94 +280,67 @@ do_timeout_req_test_for_session (SoupSession *session) GError *error = NULL; int i; - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); - g_signal_connect (session, "request-started", G_CALLBACK (request_started_socket_collector), &sockets); debug_printf (1, " First request\n"); timeout_uri = soup_uri_new_with_base (base_uri, "/timeout-persistent"); - req = soup_requester_request_uri (requester, timeout_uri, NULL); + req = soup_session_request_uri (session, timeout_uri, NULL); soup_uri_free (timeout_uri); - if (SOUP_IS_SESSION_SYNC (session)) - stream = soup_request_send (req, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (req, NULL, &error); - - if (!stream) { - debug_printf (1, " Unexpected error on send: %s\n", - error->message); - errors++; + stream = soup_test_request_send (req, NULL, 0, &error); + if (error) { + g_assert_no_error (error); g_clear_error (&error); } else { - if (SOUP_IS_SESSION_SYNC (session)) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_read_all (req, stream, NULL, &error); + if (error) { + g_assert_no_error (error); + g_clear_error (&error); + } + + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { - debug_printf (1, " Unexpected error on close: %s\n", - error->message); - errors++; + g_assert_no_error (error); g_clear_error (&error); } + g_object_unref (stream); } if (sockets[1]) { - debug_printf (1, " Message was retried??\n"); - errors++; + soup_test_assert (sockets[1] == NULL, "Message was retried"); sockets[1] = sockets[2] = sockets[3] = NULL; } g_object_unref (req); debug_printf (1, " Second request\n"); - req = soup_requester_request_uri (requester, base_uri, NULL); + req = soup_session_request_uri (session, base_uri, NULL); - if (SOUP_IS_SESSION_SYNC (session)) - stream = soup_request_send (req, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (req, NULL, &error); - - if (!stream) { - debug_printf (1, " Unexpected error on send: %s\n", - error->message); - errors++; + stream = soup_test_request_send (req, NULL, 0, &error); + if (error) { + g_assert_no_error (error); g_clear_error (&error); } else { - if (SOUP_IS_SESSION_SYNC (session)) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { - debug_printf (1, " Unexpected error on close: %s\n", - error->message); - errors++; + g_assert_no_error (error); g_clear_error (&error); } + g_object_unref (stream); } msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - if (sockets[1] != sockets[0]) { - debug_printf (1, " Message was not retried on existing connection\n"); - errors++; - } else if (!sockets[2]) { - debug_printf (1, " Message was not retried after disconnect\n"); - errors++; - } else if (sockets[2] == sockets[1]) { - debug_printf (1, " Message was retried on closed connection??\n"); - errors++; - } else if (sockets[3]) { - debug_printf (1, " Message was retried again??\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_assert (sockets[1] == sockets[0], + "Message was not retried on existing connection"); + soup_test_assert (sockets[2] != NULL, + "Message was not retried after disconnect"); + soup_test_assert (sockets[2] != sockets[1], + "Message was retried on closed connection"); + soup_test_assert (sockets[3] == NULL, + "Message was retried again"); g_object_unref (msg); g_object_unref (req); @@ -408,13 +353,14 @@ do_persistent_connection_timeout_test (void) { SoupSession *session; - debug_printf (1, "\nUnexpected timing out of persistent connections\n"); + g_test_bug ("631525"); debug_printf (1, " Async session, message API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_timeout_test_for_session (session); soup_test_session_abort_unref (session); + debug_printf (1, " Async session, request API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -426,6 +372,7 @@ do_persistent_connection_timeout_test (void) do_timeout_test_for_session (session); soup_test_session_abort_unref (session); + debug_printf (1, " Sync session, request API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); do_timeout_req_test_for_session (session); soup_test_session_abort_unref (session); @@ -491,26 +438,18 @@ do_max_conns_test_for_session (SoupSession *session) } g_main_loop_run (max_conns_loop); - if (msgs_done != MAX_CONNS) { - debug_printf (1, " Queued %d connections out of max %d?", - msgs_done, MAX_CONNS); - errors++; - } + g_assert_cmpint (msgs_done, ==, MAX_CONNS); g_signal_handlers_disconnect_by_func (session, max_conns_request_started, NULL); msgs_done = 0; g_idle_add (idle_start_server, NULL); + if (quit_loop_timeout) + g_source_remove (quit_loop_timeout); quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL); g_main_loop_run (max_conns_loop); - for (i = 0; i < TEST_CONNS; i++) { - if (!SOUP_STATUS_IS_SUCCESSFUL (msgs[i]->status_code)) { - debug_printf (1, " Message %d failed? %d %s\n", - i, msgs[i]->status_code, - msgs[i]->reason_phrase ? msgs[i]->reason_phrase : "-"); - errors++; - } - } + for (i = 0; i < TEST_CONNS; i++) + soup_test_assert_message_status (msgs[i], SOUP_STATUS_OK); if (msgs_done != TEST_CONNS) { /* Clean up so we don't get a spurious "Leaked @@ -522,8 +461,10 @@ do_max_conns_test_for_session (SoupSession *session) } g_main_loop_unref (max_conns_loop); - if (quit_loop_timeout) + if (quit_loop_timeout) { g_source_remove (quit_loop_timeout); + quit_loop_timeout = 0; + } for (i = 0; i < TEST_CONNS; i++) g_object_unref (msgs[i]); @@ -534,7 +475,7 @@ do_max_conns_test (void) { SoupSession *session; - debug_printf (1, "\nExceeding max-conns\n"); + g_test_bug ("634422"); debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, @@ -551,8 +492,6 @@ do_max_conns_test (void) soup_test_session_abort_unref (session); } -GMainLoop *loop; - static void np_request_started (SoupSession *session, SoupMessage *msg, SoupSocket *socket, gpointer user_data) @@ -568,10 +507,14 @@ np_request_unqueued (SoupSession *session, SoupMessage *msg, { SoupSocket *socket = *(SoupSocket **)user_data; - if (soup_socket_is_connected (socket)) { - debug_printf (1, " socket is still connected\n"); - errors++; - } + g_assert_false (soup_socket_is_connected (socket)); +} + +static void +np_request_finished (SoupSession *session, SoupMessage *msg, + gpointer user_data) +{ + GMainLoop *loop = user_data; g_main_loop_quit (loop); } @@ -581,6 +524,7 @@ do_non_persistent_test_for_session (SoupSession *session) { SoupMessage *msg; SoupSocket *socket = NULL; + GMainLoop *loop; loop = g_main_loop_new (NULL, FALSE); @@ -594,15 +538,15 @@ do_non_persistent_test_for_session (SoupSession *session) msg = soup_message_new_from_uri ("GET", base_uri); soup_message_headers_append (msg->request_headers, "Connection", "close"); g_object_ref (msg); - soup_session_queue_message (session, msg, NULL, NULL); + soup_session_queue_message (session, msg, + np_request_finished, loop); g_main_loop_run (loop); + g_main_loop_unref (loop); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } g_object_unref (msg); + g_object_unref (socket); } static void @@ -610,7 +554,7 @@ do_non_persistent_connection_test (void) { SoupSession *session; - debug_printf (1, "\nNon-persistent connections are closed immediately\n"); + g_test_bug ("578990"); debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -637,14 +581,9 @@ do_non_idempotent_test_for_session (SoupSession *session) debug_printf (2, " GET\n"); msg = soup_message_new_from_uri ("GET", base_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); if (sockets[1]) { - debug_printf (1, " Message was retried??\n"); - errors++; + soup_test_assert (sockets[1] == NULL, "Message was retried"); sockets[1] = sockets[2] = sockets[3] = NULL; } g_object_unref (msg); @@ -652,19 +591,12 @@ do_non_idempotent_test_for_session (SoupSession *session) debug_printf (2, " POST\n"); msg = soup_message_new_from_uri ("POST", base_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - if (sockets[1] == sockets[0]) { - debug_printf (1, " Message was sent on existing connection!\n"); - errors++; - } - if (sockets[2]) { - debug_printf (1, " Too many connections used...\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + soup_test_assert (sockets[1] != sockets[0], + "Message was sent on existing connection"); + soup_test_assert (sockets[2] == NULL, + "Too many connections used"); + g_object_unref (msg); for (i = 0; sockets[i]; i++) @@ -676,8 +608,6 @@ do_non_idempotent_connection_test (void) { SoupSession *session; - debug_printf (1, "\nNon-idempotent methods are always sent on new connections\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_non_idempotent_test_for_session (session); @@ -689,25 +619,254 @@ do_non_idempotent_connection_test (void) soup_test_session_abort_unref (session); } +#define HTTP_SERVER "http://127.0.0.1:47524" +#define HTTPS_SERVER "https://127.0.0.1:47525" +#define HTTP_PROXY "http://127.0.0.1:47526" + +static SoupConnectionState state_transitions[] = { + /* NEW -> */ SOUP_CONNECTION_CONNECTING, + /* CONNECTING -> */ SOUP_CONNECTION_IN_USE, + /* IDLE -> */ SOUP_CONNECTION_DISCONNECTED, + /* IN_USE -> */ SOUP_CONNECTION_IDLE, + + /* REMOTE_DISCONNECTED */ -1, + /* DISCONNECTED */ -1, +}; + +static const char *state_names[] = { + "NEW", "CONNECTING", "IDLE", "IN_USE", + "REMOTE_DISCONNECTED", "DISCONNECTED" +}; + +static void +connection_state_changed (GObject *object, GParamSpec *param, + gpointer user_data) +{ + SoupConnectionState *state = user_data; + SoupConnectionState new_state; + + g_object_get (object, "state", &new_state, NULL); + debug_printf (2, " %s -> %s\n", + state_names[*state], state_names[new_state]); + soup_test_assert (state_transitions[*state] == new_state, + "Unexpected transition: %s -> %s\n", + state_names[*state], state_names[new_state]); + *state = new_state; +} + +static void +connection_created (SoupSession *session, GObject *conn, + gpointer user_data) +{ + SoupConnectionState *state = user_data; + + g_object_get (conn, "state", state, NULL); + g_assert_cmpint (*state, ==, SOUP_CONNECTION_NEW); + + g_signal_connect (conn, "notify::state", + G_CALLBACK (connection_state_changed), + state); +} + +static void +do_one_connection_state_test (SoupSession *session, const char *uri) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); + soup_session_abort (session); +} + +static void +do_connection_state_test_for_session (SoupSession *session) +{ + SoupConnectionState state; + SoupURI *proxy_uri; + + g_signal_connect (session, "connection-created", + G_CALLBACK (connection_created), + &state); + + debug_printf (1, " http\n"); + do_one_connection_state_test (session, HTTP_SERVER); + + if (tls_available) { + debug_printf (1, " https\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + } else + debug_printf (1, " https -- SKIPPING\n"); + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + debug_printf (1, " http with proxy\n"); + do_one_connection_state_test (session, HTTP_SERVER); + + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); +} + +static void +do_connection_state_test (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_connection_state_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_connection_state_test_for_session (session); + soup_test_session_abort_unref (session); +} + + +static const char *event_names[] = { + "RESOLVING", "RESOLVED", "CONNECTING", "CONNECTED", + "PROXY_NEGOTIATING", "PROXY_NEGOTIATED", + "TLS_HANDSHAKING", "TLS_HANDSHAKED", "COMPLETE" +}; + +static const char event_abbrevs[] = { + 'r', 'R', 'c', 'C', 'p', 'P', 't', 'T', 'x', '\0' +}; + +static const char * +event_name_from_abbrev (char abbrev) +{ + int evt; + + for (evt = 0; event_abbrevs[evt]; evt++) { + if (event_abbrevs[evt] == abbrev) + return event_names[evt]; + } + return "???"; +} + +static void +network_event (SoupMessage *msg, GSocketClientEvent event, + GIOStream *connection, gpointer user_data) +{ + const char **events = user_data; + + debug_printf (2, " %s\n", event_name_from_abbrev (**events)); + soup_test_assert (**events == event_abbrevs[event], + "Unexpected event: %s (expected %s)\n", + event_names[event], + event_name_from_abbrev (**events)); + *events = *events + 1; +} + +static void +do_one_connection_event_test (SoupSession *session, const char *uri, + const char *events) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + g_signal_connect (msg, "network-event", + G_CALLBACK (network_event), + &events); + soup_session_send_message (session, msg); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + while (*events) { + soup_test_assert (!*events, + "Expected %s", + event_name_from_abbrev (*events)); + events++; + } + + g_object_unref (msg); + soup_session_abort (session); +} + +static void +do_connection_event_test_for_session (SoupSession *session) +{ + SoupURI *proxy_uri; + + debug_printf (1, " http\n"); + do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); + + if (tls_available) { + debug_printf (1, " https\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx"); + } else + debug_printf (1, " https -- SKIPPING\n"); + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + debug_printf (1, " http with proxy\n"); + do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); + + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx"); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); +} + +static void +do_connection_event_test (void) +{ + SoupSession *session; + + SOUP_TEST_SKIP_IF_NO_APACHE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_connection_event_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_connection_event_test_for_session (session); + soup_test_session_abort_unref (session); +} + int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); + apache_init (); server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, "http", NULL); base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - do_content_length_framing_test (); - do_persistent_connection_timeout_test (); - do_max_conns_test (); - do_non_persistent_connection_test (); - do_non_idempotent_connection_test (); + g_test_add_func ("/connection/content-length-framing", do_content_length_framing_test); + g_test_add_func ("/connection/persistent-connection-timeout", do_persistent_connection_timeout_test); + g_test_add_func ("/connection/max-conns", do_max_conns_test); + g_test_add_func ("/connection/non-persistent", do_non_persistent_connection_test); + g_test_add_func ("/connection/non-idempotent", do_non_idempotent_connection_test); + g_test_add_func ("/connection/state", do_connection_state_test); + g_test_add_func ("/connection/event", do_connection_event_test); + + ret = g_test_run (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } |