libsoup r1056 - in trunk: . libsoup tests
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libsoup r1056 - in trunk: . libsoup tests
- Date: Sun, 27 Jan 2008 19:21:30 +0000 (GMT)
Author: danw
Date: Sun Jan 27 19:21:30 2008
New Revision: 1056
URL: http://svn.gnome.org/viewvc/libsoup?rev=1056&view=rev
Log:
* libsoup/soup-dns.c (resolver_thread): fix mutex use to avoid a
race condition
* libsoup/soup-xmlrpc.c (soup_xmlrpc_build_faultv):
(soup_xmlrpc_set_response, soup_xmlrpc_set_fault):
(soup_xmlrpc_parse_method_call): Fix misc server-side stuff
(soup_xmlrpc_parse_method_response): Fix fault parsing
* libsoup/soup-xmlrpc.h (SoupXMLRPCFault): add semi-standard fault
codes from
http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
* tests/xmlrpc-server.php (sum): return a <fault> if the arguments
are wrong (so that xmlrpc-test can test that case).
(dateChange): change to take two parameters, a date and a struct,
instead of putting the date in the struct, since we weren't
previously testing multiple parameter handling.
* tests/xmlrpc-test.c (main): Add a -u flag to specify an
alternate URL.
(do_xmlrpc): Remove level 3 debug output, which is now redundant
with the SoupLogger stuff.
(test_dateChange): update for dateChange prototype change
(test_fault_malformed, test_fault_method, test_fault_args): test
handling of faults
* tests/xmlrpc-server-test.c: Test the server-side XML-RPC API (by
implementing the same methods as xmlrpc-server.php and then
using xmlrpc-test)
Added:
trunk/tests/xmlrpc-server-test.c
Modified:
trunk/ChangeLog
trunk/libsoup/soup-dns.c
trunk/libsoup/soup-xmlrpc.c
trunk/libsoup/soup-xmlrpc.h
trunk/tests/ (props changed)
trunk/tests/Makefile.am
trunk/tests/libsoup.supp
trunk/tests/xmlrpc-server.php
trunk/tests/xmlrpc-test.c
Modified: trunk/libsoup/soup-dns.c
==============================================================================
--- trunk/libsoup/soup-dns.c (original)
+++ trunk/libsoup/soup-dns.c Sun Jan 27 19:21:30 2008
@@ -517,9 +517,9 @@
else if (entry->sockaddr == NULL)
resolve_address (entry);
+ g_mutex_lock (soup_dns_lock);
entry->resolver_thread = NULL;
- g_mutex_lock (soup_dns_lock);
async_lookups = entry->async_lookups;
entry->async_lookups = NULL;
g_mutex_unlock (soup_dns_lock);
Modified: trunk/libsoup/soup-xmlrpc.c
==============================================================================
--- trunk/libsoup/soup-xmlrpc.c (original)
+++ trunk/libsoup/soup-xmlrpc.c Sun Jan 27 19:21:30 2008
@@ -301,23 +301,23 @@
node = xmlNewDocNode (doc, NULL,
(const xmlChar *)"methodResponse", NULL);
xmlDocSetRootElement (doc, node);
- node = xmlNewDocNode (doc, NULL, (const xmlChar *)"fault", NULL);
- node = xmlNewDocNode (doc, NULL, (const xmlChar *)"value", NULL);
- node = xmlNewDocNode (doc, NULL, (const xmlChar *)"struct", NULL);
+ node = xmlNewChild (node, NULL, (const xmlChar *)"fault", NULL);
+ node = xmlNewChild (node, NULL, (const xmlChar *)"value", NULL);
+ node = xmlNewChild (node, NULL, (const xmlChar *)"struct", NULL);
memset (&value, 0, sizeof (value));
- member = xmlNewDocNode (doc, NULL, (const xmlChar *)"member", NULL);
- xmlNewDocNode (doc, NULL,
- (const xmlChar *)"name", (const xmlChar *)"faultCode");
+ member = xmlNewChild (node, NULL, (const xmlChar *)"member", NULL);
+ xmlNewChild (member, NULL,
+ (const xmlChar *)"name", (const xmlChar *)"faultCode");
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, fault_code);
insert_value (member, &value);
g_value_unset (&value);
- member = xmlNewDocNode (doc, NULL, (const xmlChar *)"member", NULL);
- xmlNewDocNode (doc, NULL,
- (const xmlChar *)"name", (const xmlChar *)"faultString");
+ member = xmlNewChild (node, NULL, (const xmlChar *)"member", NULL);
+ xmlNewChild (member, NULL,
+ (const xmlChar *)"name", (const xmlChar *)"faultString");
g_value_init (&value, G_TYPE_STRING);
g_value_take_string (&value, fault_string);
insert_value (member, &value);
@@ -373,14 +373,14 @@
char *body;
va_start (args, type);
- SOUP_VALUE_GETV (&value, type, args);
+ SOUP_VALUE_SETV (&value, type, args);
va_end (args);
body = soup_xmlrpc_build_method_response (&value);
g_value_unset (&value);
soup_message_set_status (msg, SOUP_STATUS_OK);
- soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
- body, strlen (body));
+ soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE,
+ body, strlen (body));
}
/**
@@ -406,8 +406,8 @@
va_end (args);
soup_message_set_status (msg, SOUP_STATUS_OK);
- soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
- body, strlen (body));
+ soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE,
+ body, strlen (body));
}
@@ -586,13 +586,15 @@
param = find_real_node (node->children);
while (param && !strcmp ((const char *)param->name, "param")) {
xval = find_real_node (param->children);
- if (!xval || !strcmp ((const char *)xval->name, "value") ||
+ if (!xval || strcmp ((const char *)xval->name, "value") != 0 ||
!parse_value (xval, &value)) {
g_value_array_free (*params);
goto fail;
}
g_value_array_append (*params, &value);
g_value_unset (&value);
+
+ param = find_real_node (param->next);
}
success = TRUE;
@@ -685,30 +687,32 @@
goto fail;
if (!strcmp ((const char *)node->name, "fault") && error) {
- int fault_code = -1;
- xmlChar *fault_string = NULL;
+ int fault_code;
+ char *fault_string;
+ GValue fault_val;
+ GHashTable *fault_hash;
- for (node = find_real_node (node->children);
- node;
- node = find_real_node (node->next)) {
- if (!strcmp ((const char *)node->name, "faultCode")) {
- xmlChar *content = xmlNodeGetContent (node);
- fault_code = atoi ((char *)content);
- xmlFree (content);
- } else if (!strcmp ((const char *)node->name, "faultString")) {
- fault_string = xmlNodeGetContent (node);
- } else {
- if (fault_string)
- xmlFree (fault_string);
- goto fail;
- }
+ node = find_real_node (node->children);
+ if (!node || strcmp ((const char *)node->name, "value") != 0)
+ goto fail;
+ if (!parse_value (node, &fault_val))
+ goto fail;
+ if (!G_VALUE_HOLDS (&fault_val, G_TYPE_HASH_TABLE)) {
+ g_value_unset (&fault_val);
+ goto fail;
}
- if (fault_code != -1 && fault_string != NULL) {
- g_set_error (error, SOUP_XMLRPC_FAULT,
- fault_code, "%s", fault_string);
+ fault_hash = g_value_get_boxed (&fault_val);
+ if (!soup_value_hash_lookup (fault_hash, "faultCode",
+ G_TYPE_INT, &fault_code) ||
+ !soup_value_hash_lookup (fault_hash, "faultString",
+ G_TYPE_STRING, &fault_string)) {
+ g_value_unset (&fault_val);
+ goto fail;
}
- if (fault_string)
- xmlFree (fault_string);
+
+ g_set_error (error, SOUP_XMLRPC_FAULT,
+ fault_code, "%s", fault_string);
+ g_value_unset (&fault_val);
} else if (!strcmp ((const char *)node->name, "params")) {
node = find_real_node (node->children);
if (!node || strcmp ((const char *)node->name, "param") != 0)
Modified: trunk/libsoup/soup-xmlrpc.h
==============================================================================
--- trunk/libsoup/soup-xmlrpc.h (original)
+++ trunk/libsoup/soup-xmlrpc.h Sun Jan 27 19:21:30 2008
@@ -61,6 +61,22 @@
#define SOUP_XMLRPC_FAULT soup_xmlrpc_fault_quark()
GQuark soup_xmlrpc_fault_quark (void);
+/* From http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
+ * These are an extension, not part of the XML-RPC spec; you can't
+ * assume servers will use them.
+ */
+typedef enum {
+ SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED = -32700,
+ SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING = -32701,
+ SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING = -32702,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC = -32600,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND = -32601,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS = -32602,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR = -32603,
+ SOUP_XMLRPC_FAULT_APPLICATION_ERROR = -32500,
+ SOUP_XMLRPC_FAULT_SYSTEM_ERROR = -32400,
+ SOUP_XMLRPC_FAULT_TRANSPORT_ERROR = -32300,
+} SoupXMLRPCFault;
G_END_DECLS
Modified: trunk/tests/Makefile.am
==============================================================================
--- trunk/tests/Makefile.am (original)
+++ trunk/tests/Makefile.am Sun Jan 27 19:21:30 2008
@@ -44,6 +44,7 @@
ssl_test_SOURCES = ssl-test.c $(TEST_SRCS)
uri_parsing_SOURCES = uri-parsing.c $(TEST_SRCS)
xmlrpc_test_SOURCES = xmlrpc-test.c $(TEST_SRCS)
+xmlrpc_server_test_SOURCES = xmlrpc-server-test.c $(TEST_SRCS)
if HAVE_APACHE
APACHE_TESTS = auth-test proxy-test pull-api
@@ -55,7 +56,7 @@
SSL_TESTS = ssl-test
endif
if HAVE_XMLRPC_EPI_PHP
-XMLRPC_TESTS = xmlrpc-test
+XMLRPC_TESTS = xmlrpc-test xmlrpc-server-test
endif
TESTS = \
Modified: trunk/tests/libsoup.supp
==============================================================================
--- trunk/tests/libsoup.supp (original)
+++ trunk/tests/libsoup.supp Sun Jan 27 19:21:30 2008
@@ -817,6 +817,17 @@
fun:g_child_watch_source_init_multi_threaded
fun:g_child_watch_source_init
}
+{
+ glib/childwatch2b
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:pthread_create@@GLIBC_2.2.5
+ fun:g_thread_create_posix_impl
+ fun:g_thread_create_full
+ fun:g_child_watch_source_init_multi_threaded
+ fun:g_child_watch_source_init
+}
{
Added: trunk/tests/xmlrpc-server-test.c
==============================================================================
--- (empty file)
+++ trunk/tests/xmlrpc-server-test.c Sun Jan 27 19:21:30 2008
@@ -0,0 +1,337 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#include <libsoup/soup.h>
+
+#include "test-utils.h"
+
+GMainLoop *loop;
+
+static void
+type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value)
+{
+ soup_xmlrpc_set_fault (msg,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
+ "Bad parameter #%d: expected %s, got %s",
+ bad_value + 1, g_type_name (expected),
+ g_type_name (G_VALUE_TYPE (¶ms->values[bad_value])));
+}
+
+static void
+args_error (SoupMessage *msg, GValueArray *params, int expected)
+{
+ soup_xmlrpc_set_fault (msg,
+ SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
+ "Wrong number of parameters: expected %d, got %d",
+ expected, params->n_values);
+}
+
+static void
+do_sum (SoupMessage *msg, GValueArray *params)
+{
+ int sum = 0, i, val;
+ GValueArray *nums;
+
+ if (params->n_values != 1) {
+ args_error (msg, params, 1);
+ return;
+ }
+ if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &nums)) {
+ type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ return;
+ }
+
+ for (i = 0; i < nums->n_values; i++) {
+ if (!soup_value_array_get_nth (nums, i, G_TYPE_INT, &val)) {
+ type_error (msg, G_TYPE_INT, nums, i);
+ return;
+ }
+ sum += val;
+ }
+
+ soup_xmlrpc_set_response (msg, G_TYPE_INT, sum);
+
+}
+
+static void
+do_countBools (SoupMessage *msg, GValueArray *params)
+{
+ int i, trues = 0, falses = 0;
+ GValueArray *bools;
+ GHashTable *ret = soup_value_hash_new ();
+ gboolean val;
+
+ if (params->n_values != 1) {
+ args_error (msg, params, 1);
+ return;
+ }
+ if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &bools)) {
+ type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ return;
+ }
+
+ for (i = 0; i < bools->n_values; i++) {
+ if (!soup_value_array_get_nth (bools, i, G_TYPE_BOOLEAN, &val)) {
+ type_error (msg, G_TYPE_BOOLEAN, params, i);
+ return;
+ }
+ if (val)
+ trues++;
+ else
+ falses++;
+ }
+
+ soup_value_hash_insert (ret, "true", G_TYPE_INT, trues);
+ soup_value_hash_insert (ret, "false", G_TYPE_INT, falses);
+ soup_xmlrpc_set_response (msg, G_TYPE_HASH_TABLE, ret);
+ g_hash_table_destroy (ret);
+
+}
+
+static void
+do_md5sum (SoupMessage *msg, GValueArray *params)
+{
+ GChecksum *checksum;
+ GByteArray *data, *digest;
+ gsize digest_len = 16;
+
+ if (params->n_values != 1) {
+ args_error (msg, params, 1);
+ return;
+ }
+
+ if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_BYTE_ARRAY, &data)) {
+ type_error (msg, SOUP_TYPE_BYTE_ARRAY, params, 0);
+ return;
+ }
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, data->data, data->len);
+ digest = g_byte_array_new ();
+ g_byte_array_set_size (digest, digest_len);
+ g_checksum_get_digest (checksum, digest->data, &digest_len);
+ g_checksum_free (checksum);
+
+ soup_xmlrpc_set_response (msg, SOUP_TYPE_BYTE_ARRAY, digest);
+ g_byte_array_free (digest, TRUE);
+}
+
+
+static void
+do_dateChange (SoupMessage *msg, GValueArray *params)
+{
+ GHashTable *arg;
+ SoupDate *date;
+ int val;
+
+ if (params->n_values != 2) {
+ args_error (msg, params, 2);
+ return;
+ }
+
+ if (!soup_value_array_get_nth (params, 0, SOUP_TYPE_DATE, &date)) {
+ type_error (msg, SOUP_TYPE_DATE, params, 0);
+ return;
+ }
+ if (!soup_value_array_get_nth (params, 1, G_TYPE_HASH_TABLE, &arg)) {
+ type_error (msg, G_TYPE_HASH_TABLE, params, 1);
+ return;
+ }
+
+ if (soup_value_hash_lookup (arg, "tm_year", G_TYPE_INT, &val))
+ date->year = val + 1900;
+ if (soup_value_hash_lookup (arg, "tm_mon", G_TYPE_INT, &val))
+ date->month = val + 1;
+ if (soup_value_hash_lookup (arg, "tm_mday", G_TYPE_INT, &val))
+ date->day = val;
+ if (soup_value_hash_lookup (arg, "tm_hour", G_TYPE_INT, &val))
+ date->hour = val;
+ if (soup_value_hash_lookup (arg, "tm_min", G_TYPE_INT, &val))
+ date->minute = val;
+ if (soup_value_hash_lookup (arg, "tm_sec", G_TYPE_INT, &val))
+ date->second = val;
+
+ soup_xmlrpc_set_response (msg, SOUP_TYPE_DATE, date);
+}
+
+static void
+do_echo (SoupMessage *msg, GValueArray *params)
+{
+ int i;
+ const char *val;
+ GValueArray *in, *out;
+
+ if (!soup_value_array_get_nth (params, 0, G_TYPE_VALUE_ARRAY, &in)) {
+ type_error (msg, G_TYPE_VALUE_ARRAY, params, 0);
+ return;
+ }
+
+ out = g_value_array_new (in->n_values);
+ for (i = 0; i < in->n_values; i++) {
+ if (!soup_value_array_get_nth (in, i, G_TYPE_STRING, &val)) {
+ type_error (msg, G_TYPE_STRING, in, i);
+ return;
+ }
+ soup_value_array_append (out, G_TYPE_STRING, val);
+ }
+
+ soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out);
+ g_value_array_free (out);
+
+}
+
+static void
+server_callback (SoupServer *server, SoupMessage *msg,
+ const char *path, GHashTable *query,
+ SoupClientContext *context, gpointer data)
+{
+ char *method_name;
+ GValueArray *params;
+
+ if (msg->method != SOUP_METHOD_POST) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+
+ if (!soup_xmlrpc_parse_method_call (msg->request_body->data,
+ msg->request_body->length,
+ &method_name, ¶ms)) {
+ soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
+ "Could not parse method call");
+ return;
+ }
+
+ if (!strcmp (method_name, "sum"))
+ do_sum (msg, params);
+ else if (!strcmp (method_name, "countBools"))
+ do_countBools (msg, params);
+ else if (!strcmp (method_name, "md5sum"))
+ do_md5sum (msg, params);
+ else if (!strcmp (method_name, "dateChange"))
+ do_dateChange (msg, params);
+ else if (!strcmp (method_name, "echo"))
+ do_echo (msg, params);
+ else {
+ soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND,
+ "Unknown method %s", method_name);
+ }
+
+ g_free (method_name);
+ g_value_array_free (params);
+}
+
+static void
+xmlrpc_test_exited (GPid pid, int status, gpointer data)
+{
+ errors = WIFEXITED (status) ? WEXITSTATUS (status) : 1;
+ g_main_loop_quit (loop);
+}
+
+static gboolean
+xmlrpc_test_print (GIOChannel *io, GIOCondition cond, gpointer data)
+{
+ char *line;
+ gsize len;
+ GIOStatus status;
+
+ if (!(cond & G_IO_IN))
+ return FALSE;
+
+ status = g_io_channel_read_line (io, &line, &len, NULL, NULL);
+ if (status == G_IO_STATUS_NORMAL) {
+ /* Don't print the exit status, just the debug stuff */
+ if (strncmp (line, "xmlrpc-test:", strlen ("xmlrpc-test:")) != 0)
+ printf ("%s", line);
+ g_free (line);
+ return TRUE;
+ } else if (status == G_IO_STATUS_AGAIN)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+do_xmlrpc_tests (SoupURI *uri)
+{
+ char *argv[7];
+ int arg, out;
+ gboolean ok;
+ GPid pid;
+ GError *error = NULL;
+ GIOChannel *child_out;
+
+ argv[0] = "./xmlrpc-test";
+ argv[1] = "-u";
+ argv[2] = soup_uri_to_string (uri, FALSE);
+
+ for (arg = 0; arg < debug_level && arg < 3; arg++)
+ argv[arg + 3] = "-d";
+ argv[arg + 3] = NULL;
+
+ ok = g_spawn_async_with_pipes (NULL, argv, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &pid,
+ NULL, &out, NULL,
+ &error);
+ g_free (argv[2]);
+
+ if (!ok) {
+ printf ("Could not run xmlrpc-test: %s\n", error->message);
+ errors++;
+ return;
+ }
+
+ g_child_watch_add (pid, xmlrpc_test_exited, NULL);
+ child_out = g_io_channel_unix_new (out);
+ g_io_add_watch (child_out, G_IO_IN | G_IO_ERR | G_IO_HUP,
+ xmlrpc_test_print, NULL);
+ g_io_channel_unref (child_out);
+}
+
+gboolean run_tests = TRUE;
+
+static GOptionEntry no_test_entry[] = {
+ { "no-tests", 'n', G_OPTION_FLAG_NO_ARG | 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)
+{
+ SoupServer *server;
+ SoupURI *uri;
+
+ test_init (argc, argv, no_test_entry);
+
+ server = soup_test_server_new (FALSE);
+ soup_server_add_handler (server, "/xmlrpc-server.php",
+ server_callback, NULL, NULL);
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ if (run_tests) {
+ uri = soup_uri_new ("http://localhost/xmlrpc-server.php");
+ soup_uri_set_port (uri, soup_server_get_port (server));
+ do_xmlrpc_tests (uri);
+ soup_uri_free (uri);
+ } else
+ printf ("Listening on port %d\n", soup_server_get_port (server));
+
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ if (run_tests)
+ test_cleanup ();
+ return errors != 0;
+}
Modified: trunk/tests/xmlrpc-server.php
==============================================================================
Binary files. No diff available.
Modified: trunk/tests/xmlrpc-test.c
==============================================================================
--- trunk/tests/xmlrpc-test.c (original)
+++ trunk/tests/xmlrpc-test.c Sun Jan 27 19:21:30 2008
@@ -13,7 +13,8 @@
#include "test-utils.h"
SoupSession *session;
-static const char *uri = "http://localhost:47524/xmlrpc-server.php";
+static const char *default_uri = "http://localhost:47524/xmlrpc-server.php";
+const char *uri = NULL;
static const char *const value_type[] = {
"BAD",
@@ -51,13 +52,6 @@
body, strlen (body));
soup_session_send_message (session, msg);
- if (debug_level >= 3) {
- debug_printf (3, "\n%s\n%d %s\n%s\n",
- msg->request_body->data,
- msg->status_code, msg->reason_phrase,
- msg->response_body->data);
- }
-
if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
debug_printf (1, "ERROR: %d %s\n", msg->status_code,
msg->reason_phrase);
@@ -231,9 +225,7 @@
GValue retval;
gboolean ok;
- debug_printf (1, "dateChange (struct of time and ints -> time): ");
-
- structval = soup_value_hash_new ();
+ debug_printf (1, "dateChange (date, struct of ints -> time): ");
date = soup_date_new (1970 + (rand () % 50),
1 + rand () % 12,
@@ -241,54 +233,55 @@
rand () % 24,
rand () % 60,
rand () % 60);
- soup_value_hash_insert (structval, "date", SOUP_TYPE_DATE, date);
-
if (debug_level >= 2) {
timestamp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
- debug_printf (2, "{ date: %s", timestamp);
+ debug_printf (2, "date: %s, {", timestamp);
g_free (timestamp);
}
+ structval = soup_value_hash_new ();
+
if (rand () % 3) {
date->year = 1970 + (rand () % 50);
- debug_printf (2, ", tm_year: %d", date->year - 1900);
+ debug_printf (2, "tm_year: %d, ", date->year - 1900);
soup_value_hash_insert (structval, "tm_year",
G_TYPE_INT, date->year - 1900);
}
if (rand () % 3) {
date->month = 1 + rand () % 12;
- debug_printf (2, ", tm_mon: %d", date->month - 1);
+ debug_printf (2, "tm_mon: %d, ", date->month - 1);
soup_value_hash_insert (structval, "tm_mon",
G_TYPE_INT, date->month - 1);
}
if (rand () % 3) {
date->day = 1 + rand () % 28;
- debug_printf (2, ", tm_mday: %d", date->day);
+ debug_printf (2, "tm_mday: %d, ", date->day);
soup_value_hash_insert (structval, "tm_mday",
G_TYPE_INT, date->day);
}
if (rand () % 3) {
date->hour = rand () % 24;
- debug_printf (2, ", tm_hour: %d", date->hour);
+ debug_printf (2, "tm_hour: %d, ", date->hour);
soup_value_hash_insert (structval, "tm_hour",
G_TYPE_INT, date->hour);
}
if (rand () % 3) {
date->minute = rand () % 60;
- debug_printf (2, ", tm_min: %d", date->minute);
+ debug_printf (2, "tm_min: %d, ", date->minute);
soup_value_hash_insert (structval, "tm_min",
G_TYPE_INT, date->minute);
}
if (rand () % 3) {
date->second = rand () % 60;
- debug_printf (2, ", tm_sec: %d", date->second);
+ debug_printf (2, "tm_sec: %d, ", date->second);
soup_value_hash_insert (structval, "tm_sec",
G_TYPE_INT, date->second);
}
- debug_printf (2, " } -> ");
+ debug_printf (2, "} -> ");
ok = (do_xmlrpc ("dateChange", &retval,
+ SOUP_TYPE_DATE, date,
G_TYPE_HASH_TABLE, structval,
G_TYPE_INVALID) &&
check_xmlrpc (&retval, SOUP_TYPE_DATE, &result));
@@ -377,11 +370,82 @@
return TRUE;
}
+static gboolean
+do_bad_xmlrpc (const char *body)
+{
+ SoupMessage *msg;
+ GError *err = NULL;
+ GValue retval;
+
+ msg = soup_message_new ("POST", uri);
+ soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
+ body, strlen (body));
+ soup_session_send_message (session, msg);
+
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+ debug_printf (1, "ERROR: %d %s\n", msg->status_code,
+ msg->reason_phrase);
+ g_object_unref (msg);
+ return FALSE;
+ }
+
+ if (!soup_xmlrpc_parse_method_response (msg->response_body->data,
+ msg->response_body->length,
+ &retval, &err)) {
+ if (err) {
+ debug_printf (1, "FAULT: %d %s (OK!)\n",
+ err->code, err->message);
+ g_error_free (err);
+ g_object_unref (msg);
+ return TRUE;
+ } else
+ debug_printf (1, "ERROR: could not parse response\n");
+ } else
+ debug_printf (1, "Unexpectedly got successful response!\n");
+
+ g_object_unref (msg);
+ return FALSE;
+}
+
+static gboolean
+test_fault_malformed (void)
+{
+ debug_printf (1, "malformed request: ");
+
+ return do_bad_xmlrpc ("<methodCall/>");
+}
+
+static gboolean
+test_fault_method (void)
+{
+ debug_printf (1, "request to non-existent method: ");
+
+ return do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
+}
+
+static gboolean
+test_fault_args (void)
+{
+ debug_printf (1, "request with invalid args: ");
+
+ return do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
+}
+
+static GOptionEntry uri_entry[] = {
+ { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri,
+ "Alternate URI for server", NULL },
+ { NULL }
+};
+
int
main (int argc, char **argv)
{
- test_init (argc, argv, NULL);
- apache_init ();
+ test_init (argc, argv, uri_entry);
+
+ if (!uri) {
+ apache_init ();
+ uri = default_uri;
+ }
srand (time (NULL));
@@ -397,10 +461,16 @@
errors++;
if (!test_echo ())
errors++;
+ if (!test_fault_malformed ())
+ errors++;
+ if (!test_fault_method ())
+ errors++;
+ if (!test_fault_args ())
+ errors++;
soup_session_abort (session);
g_object_unref (session);
test_cleanup ();
- return errors = 0;
+ return errors != 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]