summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2022-09-27 12:40:19 +0200
committerCarlos Garcia Campos <cgarcia@igalia.com>2022-09-27 12:41:38 +0200
commitc526a853cc8dd104844ef0059b3d1a1e50413760 (patch)
treefbd1b3633ed8059b94e4e72c62670ea1ee62e690
parent0fae143dc8b0e668b7a35a9c1364009e7cf06d0f (diff)
downloadlibsoup-c526a853cc8dd104844ef0059b3d1a1e50413760.tar.gz
tests: add new test to check new request on got-body reuses the connection
And not in the case of got-headers as the documentation says. See #303
-rw-r--r--tests/misc-test.c157
1 files changed, 156 insertions, 1 deletions
diff --git a/tests/misc-test.c b/tests/misc-test.c
index 9bb5e8da..55c34ac3 100644
--- a/tests/misc-test.c
+++ b/tests/misc-test.c
@@ -35,7 +35,7 @@ server_callback (SoupServer *server,
const char *method = soup_server_message_get_method (msg);
GUri *uri = soup_server_message_get_uri (msg);
- if (method != SOUP_METHOD_GET && method != SOUP_METHOD_POST) {
+ if (method != SOUP_METHOD_GET && method != SOUP_METHOD_POST && method != SOUP_METHOD_PUT) {
soup_server_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED, NULL);
return;
}
@@ -45,6 +45,25 @@ server_callback (SoupServer *server,
return;
}
+ if (!strcmp (path, "/session")) {
+ SoupMessageHeaders *request_headers;
+ const char *session_id;
+
+ request_headers = soup_server_message_get_request_headers (msg);
+ session_id = soup_message_headers_get_one (request_headers, "X-SoupTest-Session-Id");
+ if (!session_id) {
+ SoupMessageHeaders *response_headers;
+
+ response_headers = soup_server_message_get_response_headers (msg);
+ soup_message_headers_replace (response_headers, "X-SoupTest-Session-Id", "session-1");
+ soup_server_message_set_status (msg, SOUP_STATUS_CONFLICT, NULL);
+ } else {
+ soup_server_message_set_status (msg, SOUP_STATUS_CREATED, NULL);
+ }
+
+ return;
+ }
+
if (!strcmp (path, "/slow")) {
GSource *timeout;
soup_server_message_pause (msg);
@@ -868,6 +887,141 @@ do_new_request_on_redirect_test (void)
soup_test_session_abort_unref (session);
}
+typedef struct {
+ SoupSession *session;
+ GCancellable *cancellable;
+ GBytes *body;
+ guint64 connections[2];
+ gboolean done;
+} ConflictTestData;
+
+static void
+conflict_test_send_ready_cb (SoupSession *session,
+ GAsyncResult *result,
+ ConflictTestData *data)
+{
+ GInputStream *stream;
+ SoupMessage *msg = soup_session_get_async_result_message (session, result);
+ GError *error = NULL;
+
+ stream = soup_session_send_finish (session, result, &error);
+ if (stream) {
+ guint status = soup_message_get_status (msg);
+
+ soup_test_request_read_all (stream, NULL, NULL);
+ g_object_unref (stream);
+
+ if (status != SOUP_STATUS_CONFLICT) {
+ g_assert_cmpuint (status, ==, SOUP_STATUS_CREATED);
+ data->connections[1] = soup_message_get_connection_id (msg);
+ data->done = TRUE;
+ }
+ } else {
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_error_free (error);
+ }
+}
+
+static void
+conflict_test_on_conflict_cb (SoupMessage *msg,
+ ConflictTestData *data)
+{
+ SoupMessageHeaders *response_headers;
+ SoupMessageHeaders *request_headers;
+ const gchar *session_id;
+ SoupMessage *new_msg;
+
+ g_cancellable_cancel (data->cancellable);
+ g_clear_object (&data->cancellable);
+
+ data->connections[0] = soup_message_get_connection_id (msg);
+ response_headers = soup_message_get_response_headers (msg);
+ session_id = soup_message_headers_get_one (response_headers, "X-SoupTest-Session-Id");
+ new_msg = soup_message_new_from_uri (SOUP_METHOD_PUT, soup_message_get_uri (msg));
+ request_headers = soup_message_get_request_headers (new_msg);
+ soup_message_headers_replace (request_headers, "X-SoupTest-Session-Id", session_id);
+
+ data->cancellable = g_cancellable_new ();
+ soup_message_set_request_body_from_bytes (new_msg, "text/plain", data->body);
+ soup_session_send_async (data->session, new_msg, G_PRIORITY_DEFAULT, data->cancellable,
+ (GAsyncReadyCallback)conflict_test_send_ready_cb, data);
+ g_object_unref (new_msg);
+}
+
+static void
+conflict_test_on_got_body_cb (SoupMessage *msg,
+ ConflictTestData *data)
+{
+ if (soup_message_get_status (msg) == SOUP_STATUS_CONFLICT)
+ conflict_test_on_conflict_cb (msg, data);
+}
+
+static void
+do_new_request_on_conflict_test (void)
+{
+ GUri *uri;
+ SoupMessage *msg;
+ ConflictTestData data;
+ static const char *body = "conflict test body";
+
+ data.session = soup_test_session_new (NULL);
+ data.cancellable = g_cancellable_new ();
+ data.body = g_bytes_new_static (body, strlen (body));
+ data.connections[0] = data.connections[1] = 0;
+ data.done = FALSE;
+
+ /* First try with restarting on got-headers */
+ uri = g_uri_parse_relative (base_uri, "/session", SOUP_HTTP_URI_FLAGS, NULL);
+ msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
+ soup_message_set_request_body_from_bytes (msg, "text/plain", data.body);
+ soup_message_add_status_code_handler (msg, "got-headers", SOUP_STATUS_CONFLICT,
+ G_CALLBACK (conflict_test_on_conflict_cb),
+ &data);
+ soup_session_send_async (data.session, msg, G_PRIORITY_DEFAULT, data.cancellable,
+ (GAsyncReadyCallback)conflict_test_send_ready_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.connections[0], >, 0);
+ g_assert_cmpuint (data.connections[1], >, 0);
+ g_assert_cmpuint (data.connections[0], !=, data.connections[1]);
+
+ g_object_unref (msg);
+ g_object_unref (data.cancellable);
+
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, FALSE);
+
+ data.cancellable = g_cancellable_new ();
+ data.connections[0] = data.connections[1] = 0;
+ data.done = FALSE;
+
+ /* Now try with the restarting on got-body */
+ msg = soup_message_new_from_uri (SOUP_METHOD_PUT, uri);
+ soup_message_set_request_body_from_bytes (msg, "text/plain", data.body);
+ g_signal_connect (msg, "got-body", G_CALLBACK (conflict_test_on_got_body_cb), &data);
+ soup_session_send_async (data.session, msg, G_PRIORITY_DEFAULT, data.cancellable,
+ (GAsyncReadyCallback)conflict_test_send_ready_cb, &data);
+
+ while (!data.done)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_assert_cmpuint (data.connections[0], >, 0);
+ g_assert_cmpuint (data.connections[1], >, 0);
+ g_assert_cmpuint (data.connections[0], ==, data.connections[1]);
+
+ g_object_unref (msg);
+ g_object_unref (data.cancellable);
+
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration (NULL, FALSE);
+
+ g_uri_unref (uri);
+ g_bytes_unref (data.body);
+ soup_test_session_abort_unref (data.session);
+}
+
static void
wrote_informational_check_content_length (SoupServerMessage *msg,
gpointer user_data)
@@ -1003,6 +1157,7 @@ main (int argc, char **argv)
g_test_add_func ("/misc/connection-id", do_connection_id_test);
g_test_add_func ("/misc/remote-address", do_remote_address_test);
g_test_add_func ("/misc/new-request-on-redirect", do_new_request_on_redirect_test);
+ g_test_add_func ("/misc/new-request-on-conflict", do_new_request_on_conflict_test);
g_test_add_func ("/misc/response/informational/content-length", do_response_informational_content_length_test);
g_test_add_func ("/misc/invalid-utf8-headers", do_invalid_utf8_headers_test);