Updating to 2.39.2
[profile/ivi/libsoup2.4.git] / tests / requester-test.c
index 0c71d0b..ae02451 100644 (file)
@@ -97,6 +97,11 @@ server_callback (SoupServer *server, SoupMessage *msg,
                soup_message_body_append_buffer (msg->response_body, response);
 }
 
+typedef struct {
+       GString *body;
+       gboolean cancel;
+} RequestData;
+
 static void
 stream_closed (GObject *source, GAsyncResult *res, gpointer user_data)
 {
@@ -116,7 +121,8 @@ static void
 test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data)
 {
        GInputStream *stream = G_INPUT_STREAM (source);
-       GString *body = user_data;
+       RequestData *data = user_data;
+       GString *body = data->body;
        GError *error = NULL;
        gsize nread;
 
@@ -125,6 +131,7 @@ test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data)
                debug_printf (1, "    read_async failed: %s", error->message);
                g_error_free (error);
                errors++;
+               g_input_stream_close (stream, NULL, NULL);
                g_object_unref (stream);
                g_main_loop_quit (loop);
                return;
@@ -138,13 +145,13 @@ test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data)
        g_string_append_len (body, buf, nread);
        g_input_stream_read_async (stream, buf, sizeof (buf),
                                   G_PRIORITY_DEFAULT, NULL,
-                                  test_read_ready, body);
+                                  test_read_ready, data);
 }
 
 static void
 auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
 {
-       GString *body = user_data;
+       RequestData *data = user_data;
        GInputStream *stream;
        GError *error = NULL;
        SoupMessage *msg;
@@ -177,35 +184,40 @@ auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
 
        g_input_stream_read_async (stream, buf, sizeof (buf),
                                   G_PRIORITY_DEFAULT, NULL,
-                                  test_read_ready, body);
+                                  test_read_ready, data);
 }
 
 static void
 test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
 {
-       GString *body = user_data;
+       RequestData *data = user_data;
        GInputStream *stream;
        GError *error = NULL;
-       SoupMessage *msg;
        const char *content_type;
 
        stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error);
-       if (!stream) {
-               debug_printf (1, "    send_async failed: %s\n", error->message);
-               errors++;
-               g_main_loop_quit (loop);
-               return;
-       }
-
-       msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source));
-       if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-               debug_printf (1, "    GET failed: %d %s\n", msg->status_code,
-                             msg->reason_phrase);
-               errors++;
+       if (data->cancel) {
+               if (stream) {
+                       debug_printf (1, "    send_async succeeded??\n");
+                       errors++;
+                       g_input_stream_close (stream, NULL, NULL);
+                       g_object_unref (stream);
+               } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+                       debug_printf (1, "    send_async failed with wrong error: %s\n", error->message);
+                       errors++;
+                       g_clear_error (&error);
+               }
                g_main_loop_quit (loop);
                return;
+       } else {
+               if (!stream) {
+                       debug_printf (1, "    send_async failed: %s\n", error->message);
+                       errors++;
+                       g_main_loop_quit (loop);
+                       g_clear_error (&error);
+                       return;
+               }
        }
-       g_object_unref (msg);
 
        content_type = soup_request_get_content_type (SOUP_REQUEST (source));
        if (g_strcmp0 (content_type, "text/plain") != 0) {
@@ -216,7 +228,13 @@ test_sent (GObject *source, GAsyncResult *res, gpointer user_data)
 
        g_input_stream_read_async (stream, buf, sizeof (buf),
                                   G_PRIORITY_DEFAULT, NULL,
-                                  test_read_ready, body);
+                                  test_read_ready, data);
+}
+
+static void
+cancel_message (SoupMessage *msg, gpointer session)
+{
+       soup_session_cancel_message (session, msg, SOUP_STATUS_FORBIDDEN);
 }
 
 static void
@@ -229,26 +247,35 @@ request_started (SoupSession *session, SoupMessage *msg,
 }
 
 static void
-do_one_test (SoupSession *session, SoupURI *uri,
-            GAsyncReadyCallback callback, SoupBuffer *expected_response,
-            gboolean persistent)
+do_async_test (SoupSession *session, SoupURI *uri,
+              GAsyncReadyCallback callback, guint expected_status,
+              SoupBuffer *expected_response,
+              gboolean persistent, gboolean cancel)
 {
        SoupRequester *requester;
        SoupRequest *request;
-       GString *body;
        guint started_id;
        SoupSocket *socket = NULL;
+       SoupMessage *msg;
+       RequestData data;
 
        requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER));
 
-       body = g_string_new (NULL);
+       data.body = g_string_new (NULL);
+       data.cancel = cancel;
        request = soup_requester_request_uri (requester, uri, NULL);
+       msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+
+       if (cancel) {
+               g_signal_connect (msg, "got-headers",
+                                 G_CALLBACK (cancel_message), session);
+       }
 
        started_id = g_signal_connect (session, "request-started",
                                       G_CALLBACK (request_started),
                                       &socket);
 
-       soup_request_send_async (request, NULL, callback, body);
+       soup_request_send_async (request, NULL, callback, &data);
        g_object_unref (request);
 
        loop = g_main_loop_new (soup_session_get_async_context (session), TRUE);
@@ -257,11 +284,27 @@ do_one_test (SoupSession *session, SoupURI *uri,
 
        g_signal_handler_disconnect (session, started_id);
 
-       if (body->len != expected_response->length) {
+       if (msg->status_code != expected_status) {
+               debug_printf (1, "    GET failed: %d %s (expected %d)\n",
+                             msg->status_code, msg->reason_phrase,
+                             expected_status);
+               g_object_unref (msg);
+               errors++;
+               return;
+       }
+       g_object_unref (msg);
+
+       if (!expected_response) {
+               if (data.body->len) {
+                       debug_printf (1, "    body length mismatch: expected 0, got %d\n",
+                                     (int)data.body->len);
+                       errors++;
+               }
+       } else if (data.body->len != expected_response->length) {
                debug_printf (1, "    body length mismatch: expected %d, got %d\n",
-                             (int)expected_response->length, (int)body->len);
+                             (int)expected_response->length, (int)data.body->len);
                errors++;
-       } else if (memcmp (body->str, expected_response->data,
+       } else if (memcmp (data.body->str, expected_response->data,
                           expected_response->length) != 0) {
                debug_printf (1, "    body data mismatch\n");
                errors++;
@@ -280,7 +323,7 @@ do_one_test (SoupSession *session, SoupURI *uri,
        }
        g_object_unref (socket);
 
-       g_string_free (body, TRUE);
+       g_string_free (data.body, TRUE);
 }
 
 static void
@@ -296,25 +339,41 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri)
 
        debug_printf (1, "  basic test\n");
        uri = soup_uri_new (base_uri);
-       do_one_test (session, uri, test_sent, response, TRUE);
+       do_async_test (session, uri, test_sent,
+                      SOUP_STATUS_OK, response,
+                      TRUE, FALSE);
        soup_uri_free (uri);
 
        debug_printf (1, "  chunked test\n");
        uri = soup_uri_new (base_uri);
        soup_uri_set_path (uri, "/chunked");
-       do_one_test (session, uri, test_sent, response, TRUE);
+       do_async_test (session, uri, test_sent,
+                      SOUP_STATUS_OK, response,
+                      TRUE, FALSE);
        soup_uri_free (uri);
 
        debug_printf (1, "  auth test\n");
        uri = soup_uri_new (base_uri);
        soup_uri_set_path (uri, "/auth");
-       do_one_test (session, uri, auth_test_sent, auth_response, TRUE);
+       do_async_test (session, uri, auth_test_sent,
+                      SOUP_STATUS_UNAUTHORIZED, auth_response,
+                      TRUE, FALSE);
        soup_uri_free (uri);
 
        debug_printf (1, "  non-persistent test\n");
        uri = soup_uri_new (base_uri);
        soup_uri_set_path (uri, "/non-persistent");
-       do_one_test (session, uri, test_sent, response, FALSE);
+       do_async_test (session, uri, test_sent,
+                      SOUP_STATUS_OK, response,
+                      FALSE, FALSE);
+       soup_uri_free (uri);
+
+       debug_printf (1, "  cancellation test\n");
+       uri = soup_uri_new (base_uri);
+       soup_uri_set_path (uri, "/");
+       do_async_test (session, uri, test_sent,
+                      SOUP_STATUS_FORBIDDEN, NULL,
+                      FALSE, TRUE);
        soup_uri_free (uri);
 }
 
@@ -325,7 +384,9 @@ do_simple_test (const char *uri)
 
        debug_printf (1, "Simple streaming test\n");
 
-       session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+       session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
+                                        SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
+                                        NULL);
        do_test_for_thread_and_context (session, uri);
        soup_test_session_abort_unref (session);
 }
@@ -341,6 +402,7 @@ do_test_with_context (const char *uri)
 
        session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
                                         SOUP_SESSION_ASYNC_CONTEXT, async_context,
+                                        SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
                                         NULL);
 
        do_test_for_thread_and_context (session, uri);
@@ -371,6 +433,177 @@ do_thread_test (const char *uri)
        g_thread_join (thread);
 }
 
+static void
+do_sync_request (SoupSession *session, SoupRequest *request,
+                guint expected_status, SoupBuffer *expected_response,
+                gboolean persistent, gboolean cancel)
+{
+       GInputStream *in;
+       SoupMessage *msg;
+       GError *error = NULL;
+       GString *body;
+       char buf[1024];
+       gssize nread;
+       guint started_id;
+       SoupSocket *socket = NULL;
+
+       msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request));
+       if (cancel) {
+               g_signal_connect (msg, "got-headers",
+                                 G_CALLBACK (cancel_message), session);
+       }
+
+       started_id = g_signal_connect (session, "request-started",
+                                      G_CALLBACK (request_started),
+                                      &socket);
+
+       in = soup_request_send (request, NULL, &error);
+       g_signal_handler_disconnect (session, started_id);
+       if (cancel) {
+               if (in) {
+                       debug_printf (1, "    send succeeded??\n");
+                       errors++;
+                       g_input_stream_close (in, NULL, NULL);
+                       g_object_unref (in);
+               } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+                       debug_printf (1, "    send failed with wrong error: %s\n", error->message);
+                       errors++;
+                       g_clear_error (&error);
+               }
+               g_object_unref (msg);
+               return;
+       } else if (!in) {
+               debug_printf (1, "    soup_request_send failed: %s\n",
+                             error->message);
+               g_object_unref (msg);
+               g_clear_error (&error);
+               errors++;
+               return;
+       }
+
+       if (msg->status_code != expected_status) {
+               debug_printf (1, "    GET failed: %d %s\n", msg->status_code,
+                             msg->reason_phrase);
+               g_object_unref (msg);
+               g_object_unref (in);
+               errors++;
+               return;
+       }
+       g_object_unref (msg);
+
+       body = g_string_new (NULL);
+       do {
+               nread = g_input_stream_read (in, buf, sizeof (buf),
+                                            NULL, &error);
+               if (nread == -1) {
+                       debug_printf (1, "    g_input_stream_read failed: %s\n",
+                                     error->message);
+                       g_clear_error (&error);
+                       errors++;
+                       break;
+               }
+               g_string_append_len (body, buf, nread);
+       } while (nread > 0);
+
+       if (!g_input_stream_close (in, NULL, &error)) {
+               debug_printf (1, "    g_input_stream_close failed: %s\n",
+                             error->message);
+               g_clear_error (&error);
+               errors++;
+       }
+       g_object_unref (in);
+
+       if (!expected_response) {
+               if (body->len) {
+                       debug_printf (1, "    body length mismatch: expected 0, got %d\n",
+                                     (int)body->len);
+                       errors++;
+               }
+       } else if (body->len != expected_response->length) {
+               debug_printf (1, "    body length mismatch: expected %d, got %d\n",
+                             (int)expected_response->length, (int)body->len);
+               errors++;
+       } else if (memcmp (body->str, expected_response->data, body->len) != 0) {
+               debug_printf (1, "    body data mismatch\n");
+               errors++;
+       }
+
+       if (persistent) {
+               if (!soup_socket_is_connected (socket)) {
+                       debug_printf (1, "    socket not still connected!\n");
+                       errors++;
+               }
+       } else {
+               if (soup_socket_is_connected (socket)) {
+                       debug_printf (1, "    socket still connected!\n");
+                       errors++;
+               }
+       }
+       g_object_unref (socket);
+
+       g_string_free (body, TRUE);
+}
+
+static void
+do_sync_test (const char *uri_string)
+{
+       SoupSession *session;
+       SoupRequester *requester;
+       SoupRequest *request;
+       SoupURI *uri;
+
+       debug_printf (1, "Sync streaming\n");
+
+       session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
+       requester = soup_requester_new ();
+       soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester));
+       g_object_unref (requester);
+
+       uri = soup_uri_new (uri_string);
+
+       debug_printf (1, "  basic test\n");
+       request = soup_requester_request_uri (requester, uri, NULL);
+       do_sync_request (session, request,
+                        SOUP_STATUS_OK, response,
+                        TRUE, FALSE);
+       g_object_unref (request);
+
+       debug_printf (1, "  chunked test\n");
+       soup_uri_set_path (uri, "/chunked");
+       request = soup_requester_request_uri (requester, uri, NULL);
+       do_sync_request (session, request,
+                        SOUP_STATUS_OK, response,
+                        TRUE, FALSE);
+       g_object_unref (request);
+
+       debug_printf (1, "  auth test\n");
+       soup_uri_set_path (uri, "/auth");
+       request = soup_requester_request_uri (requester, uri, NULL);
+       do_sync_request (session, request,
+                        SOUP_STATUS_UNAUTHORIZED, auth_response,
+                        TRUE, FALSE);
+       g_object_unref (request);
+
+       debug_printf (1, "  non-persistent test\n");
+       soup_uri_set_path (uri, "/non-persistent");
+       request = soup_requester_request_uri (requester, uri, NULL);
+       do_sync_request (session, request,
+                        SOUP_STATUS_OK, response,
+                        FALSE, FALSE);
+       g_object_unref (request);
+
+       debug_printf (1, "  cancel test\n");
+       soup_uri_set_path (uri, "/");
+       request = soup_requester_request_uri (requester, uri, NULL);
+       do_sync_request (session, request,
+                        SOUP_STATUS_FORBIDDEN, NULL,
+                        TRUE, TRUE);
+       g_object_unref (request);
+
+       soup_test_session_abort_unref (session);
+       soup_uri_free (uri);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -387,9 +620,11 @@ main (int argc, char **argv)
        do_simple_test (uri);
        do_thread_test (uri);
        do_context_test (uri);
+       do_sync_test (uri);
 
        g_free (uri);
        soup_buffer_free (response);
+       soup_buffer_free (auth_response);
        soup_test_server_quit_unref (server);
 
        test_cleanup ();