[libgdata/offline-testing] tests: UNFINISHED more changes to mock server
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata/offline-testing] tests: UNFINISHED more changes to mock server
- Date: Wed, 31 Jul 2013 07:21:49 +0000 (UTC)
commit f911d9d086b9ef1a785ae98d680bcd3f0a59ccd9
Author: Philip Withnall <philip tecnocode co uk>
Date: Tue Jul 30 17:43:25 2013 +0200
tests: UNFINISHED more changes to mock server
gdata/tests/common.c | 22 ++++---
gdata/tests/mock-server.c | 145 +++++++++++++++++++++++++++++++++++++--------
2 files changed, 131 insertions(+), 36 deletions(-)
---
diff --git a/gdata/tests/common.c b/gdata/tests/common.c
index 0d05a61..727128a 100644
--- a/gdata/tests/common.c
+++ b/gdata/tests/common.c
@@ -797,16 +797,18 @@ gdata_test_mock_server_start_trace (GDataMockServer *server, const gchar *trace_
gdata_mock_server_start_trace (server, trace_filename);
gdata_test_set_https_port (server);
- /* Set up the expected domain names here. This should technically be split up between
- * the different unit test suites, but that's too much effort. */
- ip_address = soup_address_get_physical (gdata_mock_server_get_address (server));
- resolver = gdata_mock_server_get_resolver (server);
-
- gdata_mock_resolver_add_A (resolver, "www.google.com", ip_address);
- gdata_mock_resolver_add_A (resolver, "gdata.youtube.com", ip_address);
- gdata_mock_resolver_add_A (resolver, "uploads.gdata.youtube.com", ip_address);
- gdata_mock_resolver_add_A (resolver, "picasaweb.google.com", ip_address);
- gdata_mock_resolver_add_A (resolver, "docs.google.com", ip_address);
+ if (gdata_mock_server_get_enable_online (server) == FALSE) {
+ /* Set up the expected domain names here. This should technically be split up between
+ * the different unit test suites, but that's too much effort. */
+ ip_address = soup_address_get_physical (gdata_mock_server_get_address (server));
+ resolver = gdata_mock_server_get_resolver (server);
+
+ gdata_mock_resolver_add_A (resolver, "www.google.com", ip_address);
+ gdata_mock_resolver_add_A (resolver, "gdata.youtube.com", ip_address);
+ gdata_mock_resolver_add_A (resolver, "uploads.gdata.youtube.com", ip_address);
+ gdata_mock_resolver_add_A (resolver, "picasaweb.google.com", ip_address);
+ gdata_mock_resolver_add_A (resolver, "docs.google.com", ip_address);
+ }
}
/**
diff --git a/gdata/tests/mock-server.c b/gdata/tests/mock-server.c
index e6bb10c..5e7f634 100644
--- a/gdata/tests/mock-server.c
+++ b/gdata/tests/mock-server.c
@@ -84,7 +84,13 @@ struct _GDataMockServerPrivate {
gboolean enable_logging;
GString *comparison_message;
- gboolean comparison_message_seen_request;
+ enum {
+ UNKNOWN,
+ REQUEST_DATA,
+ REQUEST_TERMINATOR,
+ RESPONSE_DATA,
+ RESPONSE_TERMINATOR,
+ } received_message_state;
};
enum {
@@ -241,6 +247,7 @@ gdata_mock_server_dispose (GObject *object)
if (priv->comparison_message != NULL) {
g_string_free (priv->comparison_message, TRUE);
+ priv->comparison_message = NULL;
}
/* Chain up to the parent class */
@@ -380,6 +387,7 @@ server_process_message (GDataMockServer *self, SoupMessage *message, SoupClientC
{
GDataMockServerPrivate *priv = self->priv;
SoupBuffer *message_body;
+ goffset expected_content_length;
g_assert (priv->next_message != NULL);
@@ -408,6 +416,17 @@ server_process_message (GDataMockServer *self, SoupMessage *message, SoupClientC
if (message_body->length > 0) {
soup_message_body_append_buffer (message->response_body, message_body);
}
+
+ /* If the log file doesn't contain the full response body (e.g. because it's a huge binary file
containing a nul byte somewhere),
+ * make one up (all zeros). */
+ expected_content_length = soup_message_headers_get_content_length (message->response_headers);
+ if (expected_content_length > 0 && message_body->length < (guint64) expected_content_length) {
+ guint8 *buf;
+
+ buf = g_malloc0 (expected_content_length - message_body->length);
+ soup_message_body_append_take (message->response_body, buf, expected_content_length -
message_body->length);
+ }
+
soup_buffer_free (message_body);
soup_message_body_complete (message->response_body);
@@ -808,33 +827,58 @@ load_message_half (GFileInputStream *input_stream, GString *current_message, gch
return TRUE;
}
+/* Returns TRUE iff the given message from a trace file should be ignored and not used by the mock server. */
+static gboolean
+should_ignore_soup_message (SoupMessage *message)
+{
+ switch (message->status_code) {
+ case SOUP_STATUS_NONE:
+ case SOUP_STATUS_CANCELLED:
+ case SOUP_STATUS_CANT_RESOLVE:
+ case SOUP_STATUS_CANT_RESOLVE_PROXY:
+ case SOUP_STATUS_CANT_CONNECT:
+ case SOUP_STATUS_CANT_CONNECT_PROXY:
+ case SOUP_STATUS_SSL_FAILED:
+ case SOUP_STATUS_IO_ERROR:
+ case SOUP_STATUS_MALFORMED:
+ case SOUP_STATUS_TRY_AGAIN:
+ case SOUP_STATUS_TOO_MANY_REDIRECTS:
+ case SOUP_STATUS_TLS_FAILED:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
static SoupMessage *
load_file_iteration (GFileInputStream *input_stream, SoupURI *base_uri, GCancellable *cancellable, GError
**error)
{
SoupMessage *output_message = NULL;
GString *current_message = NULL;
- /* Start loading from the stream. */
current_message = g_string_new (NULL);
- /* We should be at the start of a request (>). Search for the start of the response (<), then for the
start of the next request (>). */
- if (load_message_half (input_stream, current_message, '<', cancellable, error) == FALSE ||
- load_message_half (input_stream, current_message, '>', cancellable, error) == FALSE) {
- goto done;
- }
+ do {
+ /* Start loading from the stream. */
+ g_string_truncate (current_message, 0);
- if (current_message->len > 0) {
- output_message = trace_to_soup_message (current_message->str, base_uri);
- } else {
- /* Reached the end of the file. */
- output_message = NULL;
- }
+ /* We should be at the start of a request (>). Search for the start of the response (<), then
for the start of the next request (>). */
+ if (load_message_half (input_stream, current_message, '<', cancellable, error) == FALSE ||
+ load_message_half (input_stream, current_message, '>', cancellable, error) == FALSE) {
+ goto done;
+ }
+
+ if (current_message->len > 0) {
+ output_message = trace_to_soup_message (current_message->str, base_uri);
+ } else {
+ /* Reached the end of the file. */
+ output_message = NULL;
+ }
+ } while (output_message != NULL && should_ignore_soup_message (output_message) == TRUE);
done:
/* Tidy up. */
- if (current_message != NULL) {
- g_string_free (current_message, TRUE);
- }
+ g_string_free (current_message, TRUE);
/* Postcondition: (output_message != NULL) => (*error == NULL). */
g_assert (output_message == NULL || (error == NULL || *error == NULL));
@@ -900,9 +944,12 @@ gdata_mock_server_unload_trace (GDataMockServer *self)
g_clear_object (&priv->input_stream);
g_clear_object (&priv->trace_file);
- g_string_free (priv->comparison_message, TRUE);
- priv->comparison_message = NULL;
- priv->comparison_message_seen_request = FALSE;
+ if (priv->comparison_message != NULL) {
+ g_string_free (priv->comparison_message, TRUE);
+ priv->comparison_message = NULL;
+ }
+
+ priv->received_message_state = UNKNOWN;
}
/**
@@ -942,7 +989,7 @@ gdata_mock_server_load_trace (GDataMockServer *self, GFile *trace_file, GCancell
priv->next_message = load_file_iteration (priv->input_stream, base_uri, cancellable,
&child_error);
priv->comparison_message = g_string_new (NULL);
- priv->comparison_message_seen_request = FALSE;
+ priv->received_message_state = UNKNOWN;
if (child_error != NULL) {
g_clear_object (&priv->trace_file);
@@ -1050,7 +1097,7 @@ gdata_mock_server_load_trace_finish (GDataMockServer *self, GAsyncResult *result
self->priv->next_message = g_task_propagate_pointer (G_TASK (result), error);
self->priv->comparison_message = g_string_new (NULL);
- self->priv->comparison_message_seen_request = FALSE;
+ self->priv->received_message_state = UNKNOWN;
}
static gpointer
@@ -1431,6 +1478,55 @@ gdata_mock_server_received_message_chunk (GDataMockServer *self, const gchar *me
return;
}
+ /* Simple state machine to track where we are in the soup log format. */
+ switch (priv->received_message_state) {
+ case UNKNOWN:
+ if (strncmp (message_chunk, "> ", 2) == 0) {
+ priv->received_message_state = REQUEST_DATA;
+ }
+ break;
+ case REQUEST_DATA:
+ if (strcmp (message_chunk, " ") == 0) {
+ priv->received_message_state = REQUEST_TERMINATOR;
+ } else if (strncmp (message_chunk, "> ", 2) != 0) {
+ priv->received_message_state = UNKNOWN;
+ }
+ break;
+ case REQUEST_TERMINATOR:
+ if (strncmp (message_chunk, "< ", 2) == 0) {
+ priv->received_message_state = RESPONSE_DATA;
+ } else {
+ priv->received_message_state = UNKNOWN;
+ }
+ break;
+ case RESPONSE_DATA:
+ if (strcmp (message_chunk, " ") == 0) {
+ priv->received_message_state = RESPONSE_TERMINATOR;
+ } else if (strncmp (message_chunk, "< ", 2) != 0) {
+ priv->received_message_state = UNKNOWN;
+ }
+ break;
+ case RESPONSE_TERMINATOR:
+ if (strncmp (message_chunk, "> ", 2) == 0) {
+ priv->received_message_state = REQUEST_DATA;
+ } else {
+ priv->received_message_state = UNKNOWN;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Silently ignore responses outputted by libsoup before the requests. This can happen when a
SoupMessage is cancelled part-way through
+ * sending the request; in which case libsoup logs only a response of the form:
+ * < HTTP/1.1 1 Cancelled
+ * < Soup-Debug-Timestamp: 1375190963
+ * < Soup-Debug: SoupMessage 0 (0x7fffe00261c0)
+ */
+ if (priv->received_message_state == UNKNOWN) {
+ return;
+ }
+
/* Append to the trace file. */
if (priv->enable_logging == TRUE &&
(g_output_stream_write_all (G_OUTPUT_STREAM (priv->output_stream), message_chunk, strlen
(message_chunk), NULL, NULL, &child_error) == FALSE ||
@@ -1450,10 +1546,7 @@ gdata_mock_server_received_message_chunk (GDataMockServer *self, const gchar *me
g_string_append (priv->comparison_message, message_chunk);
g_string_append_c (priv->comparison_message, '\n');
- if (strcmp (message_chunk, " ") == 0 && priv->comparison_message_seen_request == FALSE) {
- /* Need to capture both the request and the response before processing; both are
terminated by a single “ ” chunk. */
- priv->comparison_message_seen_request = TRUE;
- } else if (strcmp (message_chunk, " ") == 0) {
+ if (strcmp (message_chunk, " ") == 0) {
/* Received the last chunk of the response, so compare the message from the trace
file and that from online. */
SoupMessage *online_message;
SoupURI *base_uri;
@@ -1464,7 +1557,7 @@ gdata_mock_server_received_message_chunk (GDataMockServer *self, const gchar *me
soup_uri_free (base_uri);
g_string_truncate (priv->comparison_message, 0);
- priv->comparison_message_seen_request = FALSE;
+ priv->received_message_state = UNKNOWN;
g_assert (priv->next_message != NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]