diff options
Diffstat (limited to 'tests/redirect-test.c')
-rw-r--r-- | tests/redirect-test.c | 416 |
1 files changed, 137 insertions, 279 deletions
diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 59a2f077..ad8dabaa 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -5,7 +5,9 @@ #include "test-utils.h" +SoupURI *base_uri; char *server2_uri; +SoupSession *async_session, *sync_session; typedef struct { const char *method; @@ -14,104 +16,106 @@ typedef struct { gboolean repeat; } TestRequest; -static struct { +typedef struct { TestRequest requests[3]; guint final_status; - guint request_api_final_status; -} tests[] = { + const char *bugref; +} TestCase; + +static TestCase tests[] = { /* A redirecty response to a GET or HEAD should cause a redirect */ { { { "GET", "/301", 301 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "GET", "/302", 302 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "GET", "/303", 303 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "GET", "/307", 307 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "HEAD", "/301", 301 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "551190" }, { { { "HEAD", "/302", 302 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "551190" }, /* 303 is a nonsensical response to HEAD, but some sites do * it anyway. :-/ */ { { { "HEAD", "/303", 303 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "600830" }, { { { "HEAD", "/307", 307 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "551190" }, /* A non-redirecty response to a GET or HEAD should not */ { { { "GET", "/300", 300 }, - { NULL } }, 300 }, + { NULL } }, 300, NULL }, { { { "GET", "/304", 304 }, - { NULL } }, 304 }, + { NULL } }, 304, NULL }, { { { "GET", "/305", 305 }, - { NULL } }, 305 }, + { NULL } }, 305, NULL }, { { { "GET", "/306", 306 }, - { NULL } }, 306 }, + { NULL } }, 306, NULL }, { { { "GET", "/308", 308 }, - { NULL } }, 308 }, + { NULL } }, 308, NULL }, { { { "HEAD", "/300", 300 }, - { NULL } }, 300 }, + { NULL } }, 300, "551190" }, { { { "HEAD", "/304", 304 }, - { NULL } }, 304 }, + { NULL } }, 304, "551190" }, { { { "HEAD", "/305", 305 }, - { NULL } }, 305 }, + { NULL } }, 305, "551190" }, { { { "HEAD", "/306", 306 }, - { NULL } }, 306 }, + { NULL } }, 306, "551190" }, { { { "HEAD", "/308", 308 }, - { NULL } }, 308 }, + { NULL } }, 308, "551190" }, /* Test double-redirect */ { { { "GET", "/301/302", 301 }, { "GET", "/302", 302 }, - { "GET", "/", 200 } }, 200 }, + { "GET", "/", 200 } }, 200, NULL }, { { { "HEAD", "/301/302", 301 }, { "HEAD", "/302", 302 }, - { "HEAD", "/", 200 } }, 200 }, + { "HEAD", "/", 200 } }, 200, "551190" }, /* POST should only automatically redirect on 301, 302 and 303 */ { { { "POST", "/301", 301 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "586692" }, { { { "POST", "/302", 302 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "POST", "/303", 303 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "POST", "/307", 307 }, - { NULL } }, 307 }, + { NULL } }, 307, NULL }, /* Test behavior with recoverably-bad Location header */ { { { "GET", "/bad", 302 }, { "GET", "/bad%20with%20spaces", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "566530" }, /* Test behavior with irrecoverably-bad Location header */ { { { "GET", "/bad-no-host", 302 }, - { NULL } }, SOUP_STATUS_MALFORMED, 302 }, + { NULL } }, SOUP_STATUS_MALFORMED, "528882" }, /* Test infinite redirection */ { { { "GET", "/bad-recursive", 302, TRUE }, - { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS }, + { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS, "604383" }, /* Test redirection to a different server */ { { { "GET", "/server2", 302 }, { "GET", "/on-server2", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, }; static const int n_tests = G_N_ELEMENTS (tests); @@ -131,11 +135,7 @@ got_headers (SoupMessage *msg, gpointer user_data) if (!(*treq)->method) return; - if (msg->status_code != (*treq)->status_code) { - debug_printf (1, " - Expected %d !\n", - (*treq)->status_code); - errors++; - } + soup_test_assert_message_status (msg, (*treq)->status_code); } static void @@ -149,35 +149,25 @@ restarted (SoupMessage *msg, gpointer user_data) if ((*treq)->method && !(*treq)->repeat) (*treq)++; - if (!(*treq)->method) { - debug_printf (1, " - Expected to be done!\n"); - errors++; - return; - } + soup_test_assert ((*treq)->method, + "Expected to be done"); - if (strcmp (msg->method, (*treq)->method) != 0) { - debug_printf (1, " - Expected %s !\n", (*treq)->method); - errors++; - } - if (strcmp (uri->path, (*treq)->path) != 0) { - debug_printf (1, " - Expected %s !\n", (*treq)->path); - errors++; - } + g_assert_cmpstr (msg->method, ==, (*treq)->method); + g_assert_cmpstr (uri->path, ==, (*treq)->path); } static void -do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) +do_message_api_test (SoupSession *session, TestCase *test) { SoupURI *uri; SoupMessage *msg; TestRequest *treq; - debug_printf (1, "%2d. %s %s\n", n + 1, - tests[n].requests[0].method, - tests[n].requests[0].path); + if (test->bugref) + g_test_bug (test->bugref); - uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path); - msg = soup_message_new_from_uri (tests[n].requests[0].method, uri); + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); + msg = soup_message_new_from_uri (test->requests[0].method, uri); soup_uri_free (uri); if (msg->method == SOUP_METHOD_POST) { @@ -187,7 +177,7 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) strlen ("post body")); } - treq = &tests[n].requests[0]; + treq = &test->requests[0]; g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), &treq); g_signal_connect (msg, "restarted", @@ -195,53 +185,36 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) soup_session_send_message (session, msg); - if (msg->status_code != tests[n].final_status) { - debug_printf (1, " - Expected final status of %d, got %d !\n", - tests[n].final_status, msg->status_code); - errors++; - } + soup_test_assert_message_status (msg, test->final_status); g_object_unref (msg); - debug_printf (2, "\n"); } static void -do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) +do_request_api_test (SoupSession *session, TestCase *test) { - SoupRequester *requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); SoupURI *uri; - SoupRequest *req; + SoupRequestHTTP *reqh; SoupMessage *msg; TestRequest *treq; GInputStream *stream; GError *error = NULL; - guint final_status; - - debug_printf (1, "%2d. %s %s\n", n + 1, - tests[n].requests[0].method, - tests[n].requests[0].path); - final_status = tests[n].request_api_final_status; - if (!final_status) - final_status = tests[n].final_status; + if (test->bugref) + g_test_bug (test->bugref); - uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path); - req = soup_requester_request_uri (requester, uri, &error); + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); + reqh = soup_session_request_http_uri (session, + test->requests[0].method, + uri, &error); soup_uri_free (uri); - if (!req) { - debug_printf (1, " could not create request: %s\n", - error->message); + g_assert_no_error (error); + if (error) { g_error_free (error); - errors++; - debug_printf (2, "\n"); return; } - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - g_object_set (G_OBJECT (msg), - SOUP_MESSAGE_METHOD, tests[n].requests[0].method, - NULL); - + msg = soup_request_http_get_message (reqh); if (msg->method == SOUP_METHOD_POST) { soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC, @@ -249,208 +222,75 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) strlen ("post body")); } - treq = &tests[n].requests[0]; + treq = &test->requests[0]; g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), &treq); g_signal_connect (msg, "restarted", G_CALLBACK (restarted), &treq); - 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 (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) { - if (stream) { - debug_printf (1, " expected failure (%s) but succeeded", - soup_status_get_phrase (final_status)); - errors++; - g_object_unref (stream); - } - if (error->domain != SOUP_HTTP_ERROR || - error->code != final_status) { - debug_printf (1, " expected '%s' but got '%s'", - soup_status_get_phrase (final_status), - error->message); - errors++; - } + stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); - g_error_free (error); - g_object_unref (req); - debug_printf (2, "\n"); - return; - } else if (!stream) { - debug_printf (1, " could not send request: %s\n", - error->message); - g_error_free (error); - g_object_unref (req); - errors++; - debug_printf (2, "\n"); + if (SOUP_STATUS_IS_TRANSPORT_ERROR (test->final_status) && + test->final_status != SOUP_STATUS_MALFORMED) { + g_assert_error (error, SOUP_HTTP_ERROR, test->final_status); + g_clear_error (&error); + + g_assert_null (stream); + g_clear_object (&stream); + + g_object_unref (msg); + g_object_unref (reqh); return; } - if (SOUP_IS_SESSION_SYNC (session)) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + g_assert_no_error (error); if (error) { - debug_printf (1, " could not close stream: %s\n", - error->message); g_error_free (error); - errors++; + g_object_unref (msg); + g_object_unref (reqh); + return; } - if (msg->status_code != final_status) { - debug_printf (1, " - Expected final status of %d, got %d !\n", - final_status, msg->status_code); - errors++; - } + soup_test_request_read_all (SOUP_REQUEST (reqh), stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); - g_object_unref (req); - debug_printf (2, "\n"); -} + soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); + g_object_unref (stream); -static void -do_redirect_tests (SoupURI *base_uri) -{ - SoupSession *session; - int n; - - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, - SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - NULL); - debug_printf (1, "Async session, SoupMessage\n"); - for (n = 0; n < n_tests; n++) - do_message_api_test (session, base_uri, n); - debug_printf (1, "\nAsync session, SoupRequest\n"); - for (n = 0; n < n_tests; n++) - do_request_api_test (session, base_uri, n); - soup_test_session_abort_unref (session); - - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, - NULL); - debug_printf (1, "\nSync session, SoupMessage\n"); - for (n = 0; n < n_tests; n++) - do_message_api_test (session, base_uri, n); - debug_printf (1, "\nSync session, SoupRequest\n"); - for (n = 0; n < n_tests; n++) - do_request_api_test (session, base_uri, n); - soup_test_session_abort_unref (session); -} - -typedef struct { - SoupSession *session; - SoupMessage *msg1, *msg2; - SoupURI *uri1, *uri2; - SoupSocket *sock1, *sock2; -} ConnectionTestData; + if (test->final_status == SOUP_STATUS_MALFORMED) + g_assert_cmpint (msg->status_code, ==, test->requests[0].status_code); + else + g_assert_cmpint (msg->status_code, ==, test->final_status); -static void -msg2_finished (SoupSession *session, SoupMessage *msg2, gpointer user_data) -{ - if (!SOUP_STATUS_IS_SUCCESSFUL (msg2->status_code)) { - debug_printf (1, " msg2 failed: %d %s\n", - msg2->status_code, msg2->reason_phrase); - errors++; - } + g_object_unref (msg); + g_object_unref (reqh); } static void -unpause_msg1 (SoupMessage *msg2, gpointer user_data) +do_async_msg_api_test (gconstpointer test) { - ConnectionTestData *data = user_data; - - if (!data->sock1) { - debug_printf (1, " msg1 has no connection?\n"); - errors++; - } else if (!data->sock2) { - debug_printf (1, " msg2 has no connection?\n"); - errors++; - } else if (data->sock1 == data->sock2) { - debug_printf (1, " Both messages sharing the same connection\n"); - errors++; - } - - soup_session_unpause_message (data->session, data->msg1); -} - -static gboolean -msg1_just_restarted (gpointer user_data) -{ - ConnectionTestData *data = user_data; - - soup_session_pause_message (data->session, data->msg1); - - data->msg2 = soup_message_new_from_uri ("GET", data->uri2); - - g_signal_connect (data->msg2, "got_body", - G_CALLBACK (unpause_msg1), data); - - soup_session_queue_message (data->session, data->msg2, msg2_finished, data); - return FALSE; + do_message_api_test (async_session, (TestCase *)test); } static void -msg1_about_to_restart (SoupMessage *msg1, gpointer user_data) +do_async_req_api_test (gconstpointer test) { - ConnectionTestData *data = user_data; - - /* Do nothing when loading the redirected-to resource */ - if (!SOUP_STATUS_IS_REDIRECTION (data->msg1->status_code)) - return; - - /* We have to pause msg1 after the I/O finishes, but before - * the queue runs again. - */ - g_idle_add_full (G_PRIORITY_HIGH, msg1_just_restarted, data, NULL); + do_request_api_test (async_session, (TestCase *)test); } static void -request_started (SoupSession *session, SoupMessage *msg, - SoupSocket *socket, gpointer user_data) +do_sync_msg_api_test (gconstpointer test) { - ConnectionTestData *data = user_data; - - if (msg == data->msg1) - data->sock1 = socket; - else if (msg == data->msg2) - data->sock2 = socket; - else - g_warn_if_reached (); + do_message_api_test (sync_session, (TestCase *)test); } static void -do_connection_test (SoupURI *base_uri) +do_sync_req_api_test (gconstpointer test) { - ConnectionTestData data; - - debug_printf (1, "\nConnection reuse\n"); - memset (&data, 0, sizeof (data)); - - data.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - g_signal_connect (data.session, "request-started", - G_CALLBACK (request_started), &data); - - data.uri1 = soup_uri_new_with_base (base_uri, "/301"); - data.uri2 = soup_uri_new_with_base (base_uri, "/"); - data.msg1 = soup_message_new_from_uri ("GET", data.uri1); - - g_signal_connect (data.msg1, "got-body", - G_CALLBACK (msg1_about_to_restart), &data); - soup_session_send_message (data.session, data.msg1); - - if (!SOUP_STATUS_IS_SUCCESSFUL (data.msg1->status_code)) { - debug_printf (1, " msg1 failed: %d %s\n", - data.msg1->status_code, data.msg1->reason_phrase); - errors++; - } - g_object_unref (data.msg1); - soup_uri_free (data.uri1); - soup_uri_free (data.uri2); - - soup_test_session_abort_unref (data.session); + do_request_api_test (sync_session, (TestCase *)test); } static void @@ -550,29 +390,23 @@ server2_callback (SoupServer *server, SoupMessage *msg, soup_message_set_status (msg, SOUP_STATUS_OK); } -static gboolean run_tests = TRUE; - -static GOptionEntry no_test_entry[] = { - { "no-tests", 'n', G_OPTION_FLAG_REVERSE, - G_OPTION_ARG_NONE, &run_tests, - "Don't run tests, just run the test server", NULL }, - { NULL } -}; - int main (int argc, char **argv) { GMainLoop *loop; SoupServer *server, *server2; guint port; - SoupURI *base_uri; + char *path; + int n, ret; - test_init (argc, argv, no_test_entry); + test_init (argc, argv, NULL); server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); port = soup_server_get_port (server); + base_uri = soup_uri_new ("http://127.0.0.1"); + soup_uri_set_port (base_uri, port); server2 = soup_test_server_new (TRUE); soup_server_add_handler (server2, NULL, @@ -582,23 +416,47 @@ main (int argc, char **argv) loop = g_main_loop_new (NULL, TRUE); - if (run_tests) { - base_uri = soup_uri_new ("http://127.0.0.1"); - soup_uri_set_port (base_uri, port); - do_redirect_tests (base_uri); - do_connection_test (base_uri); - soup_uri_free (base_uri); - } else { - g_print ("Listening on port %d\n", port); - g_main_loop_run (loop); + async_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + sync_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + for (n = 0; n < n_tests; n++) { + path = g_strdup_printf ("/redirect/async/msg/%d-%s-%d", n + , tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_async_msg_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/async/req/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_async_req_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/sync/msg/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_sync_msg_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/sync/req/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_sync_req_api_test); + g_free (path); } + ret = g_test_run (); + g_main_loop_unref (loop); - g_free (server2_uri); + soup_uri_free (base_uri); soup_test_server_quit_unref (server); + g_free (server2_uri); soup_test_server_quit_unref (server2); - if (run_tests) - test_cleanup (); - return errors != 0; + soup_test_session_abort_unref (async_session); + soup_test_session_abort_unref (sync_session); + + return ret; } |