/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2007, 2008 Red Hat, Inc. */ #include "test-utils.h" static struct { const char *title, *name; const char *result; } tests[] = { /* Both fields must be filled in */ { NULL, "Name", "" }, { "Mr.", NULL, "" }, /* Filled-in but empty is OK */ { "", "", "Hello, " }, { "", "Name", "Hello, Name" }, { "Mr.", "", "Hello, MR. " }, /* Simple */ { "Mr.", "Name", "Hello, MR. Name" }, /* Encoding of spaces */ { "Mr.", "Full Name", "Hello, MR. Full Name" }, { "Mr. and Mrs.", "Full Name", "Hello, MR. AND MRS. Full Name" }, /* Encoding of "+" */ { "Mr.+Mrs.", "Full Name", "Hello, MR.+MRS. Full Name" }, /* Encoding of non-ASCII. */ { "Se\xC3\xB1or", "Nombre", "Hello, SE\xC3\xB1OR Nombre" }, /* Encoding of '%' */ { "Mr.", "Foo %2f Bar", "Hello, MR. Foo %2f Bar" }, }; static void do_hello_test (int n, gboolean extra, const char *uri) { GPtrArray *args; char *title_arg = NULL, *name_arg = NULL; char *str_stdout = NULL; debug_printf (1, "%2d. '%s' '%s'%s: ", n * 2 + (extra ? 2 : 1), tests[n].title ? tests[n].title : "(null)", tests[n].name ? tests[n].name : "(null)", extra ? " + extra" : ""); args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); g_ptr_array_add (args, "-G"); if (tests[n].title) { title_arg = soup_form_encode ("title", tests[n].title, NULL); g_ptr_array_add (args, "-d"); g_ptr_array_add (args, title_arg); } if (tests[n].name) { name_arg = soup_form_encode ("n@me", tests[n].name, NULL); g_ptr_array_add (args, "-d"); g_ptr_array_add (args, name_arg); } if (extra) { g_ptr_array_add (args, "-d"); g_ptr_array_add (args, "extra=something"); } g_ptr_array_add (args, (char *)uri); g_ptr_array_add (args, NULL); if (g_spawn_sync (NULL, (char **)args->pdata, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &str_stdout, NULL, NULL, NULL)) { if (str_stdout && !strcmp (str_stdout, tests[n].result)) debug_printf (1, "OK!\n"); else { debug_printf (1, "WRONG!\n"); debug_printf (1, " expected '%s', got '%s'\n", tests[n].result, str_stdout ? str_stdout : "(error)"); errors++; } g_free (str_stdout); } else { debug_printf (1, "ERROR!\n"); errors++; } g_ptr_array_free (args, TRUE); g_free (title_arg); g_free (name_arg); } static void do_hello_tests (const char *uri) { int n; debug_printf (1, "Hello tests (GET, application/x-www-form-urlencoded)\n"); for (n = 0; n < G_N_ELEMENTS (tests); n++) { do_hello_test (n, FALSE, uri); do_hello_test (n, TRUE, uri); } } static void do_md5_test_curl (const char *uri, const char *file, const char *md5) { GPtrArray *args; char *file_arg, *str_stdout; debug_printf (1, " via curl: "); args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); g_ptr_array_add (args, "-L"); g_ptr_array_add (args, "-F"); file_arg = g_strdup_printf ("file=@%s", file); g_ptr_array_add (args, file_arg); g_ptr_array_add (args, "-F"); g_ptr_array_add (args, "fmt=txt"); g_ptr_array_add (args, (char *)uri); g_ptr_array_add (args, NULL); if (g_spawn_sync (NULL, (char **)args->pdata, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &str_stdout, NULL, NULL, NULL)) { if (str_stdout && !strcmp (str_stdout, md5)) debug_printf (1, "OK!\n"); else { debug_printf (1, "WRONG!\n"); debug_printf (1, " expected '%s', got '%s'\n", md5, str_stdout ? str_stdout : "(error)"); errors++; } g_free (str_stdout); } else { debug_printf (1, "ERROR!\n"); errors++; } g_ptr_array_free (args, TRUE); g_free (file_arg); } #define MD5_TEST_FILE SRCDIR "/resources/home.gif" #define MD5_TEST_FILE_BASENAME "home.gif" #define MD5_TEST_FILE_MIME_TYPE "image/gif" static void do_md5_test_libsoup (const char *uri, const char *contents, gsize length, const char *md5) { SoupMultipart *multipart; SoupBuffer *buffer; SoupMessage *msg; SoupSession *session; debug_printf (1, " via libsoup: "); multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART); buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length); soup_multipart_append_form_file (multipart, "file", MD5_TEST_FILE_BASENAME, MD5_TEST_FILE_MIME_TYPE, buffer); soup_buffer_free (buffer); soup_multipart_append_form_string (multipart, "fmt", "text"); msg = soup_form_request_new_from_multipart (uri, multipart); soup_multipart_free (multipart); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); soup_session_send_message (session, msg); if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { debug_printf (1, "ERROR: Unexpected status %d %s\n", msg->status_code, msg->reason_phrase); errors++; } else if (strcmp (msg->response_body->data, md5) != 0) { debug_printf (1, "ERROR: Incorrect response: expected '%s' got '%s'\n", md5, msg->response_body->data); errors++; } else debug_printf (1, "OK!\n"); g_object_unref (msg); soup_test_session_abort_unref (session); } static void do_md5_tests (const char *uri) { char *contents, *md5; gsize length; GError *error = NULL; debug_printf (1, "\nMD5 tests (POST, multipart/form-data)\n"); if (!g_file_get_contents (MD5_TEST_FILE, &contents, &length, &error)) { debug_printf (1, " ERROR: Could not read " MD5_TEST_FILE ": %s\n", error->message); g_error_free (error); errors++; return; } md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, contents, length); do_md5_test_curl (uri, MD5_TEST_FILE, md5); do_md5_test_libsoup (uri, contents, length, md5); g_free (contents); g_free (md5); } static void do_form_decode_test (void) { GHashTable *table; const gchar *value; gchar *tmp; debug_printf (1, "\nDecode tests\n"); /* Test that the code handles multiple values with the same key. */ table = soup_form_decode ("foo=first&foo=second&foo=third"); /* Allocate some memory. We do this to test for a bug in * soup_form_decode() that resulted in values from the hash * table pointing to memory that is already released. */ tmp = g_strdup ("other"); value = g_hash_table_lookup (table, "foo"); if (g_strcmp0 (value, "third") != 0) { debug_printf (1, " ERROR: expected '%s', got '%s'\n", "third", value ? value : "(null)"); errors++; } g_free (tmp); g_hash_table_destroy (table); } static void hello_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *context, gpointer data) { char *title, *name, *fmt; const char *content_type; GString *buf; if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_HEAD) { soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); return; } if (query) { title = g_hash_table_lookup (query, "title"); name = g_hash_table_lookup (query, "n@me"); fmt = g_hash_table_lookup (query, "fmt"); } else title = name = fmt = NULL; buf = g_string_new (NULL); if (!query || (fmt && !strcmp (fmt, "html"))) { content_type = "text/html"; g_string_append (buf, "
Hello, %s %s
\r\n", title, name); } g_string_append (buf, "\r\n"); g_string_append (buf, "\r\n"); } else { content_type = "text/plain"; if (title && name) { char *uptitle = g_ascii_strup (title, -1); g_string_append_printf (buf, "Hello, %s %s", uptitle, name); g_free (uptitle); } } soup_message_set_response (msg, content_type, SOUP_MEMORY_TAKE, buf->str, buf->len); g_string_free (buf, FALSE); soup_message_set_status (msg, SOUP_STATUS_OK); } static void md5_get_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *context, gpointer data) { const char *file = NULL, *md5sum = NULL, *fmt; const char *content_type; GString *buf; if (query) { file = g_hash_table_lookup (query, "file"); md5sum = g_hash_table_lookup (query, "md5sum"); fmt = g_hash_table_lookup (query, "fmt"); } else fmt = "html"; buf = g_string_new (NULL); if (!strcmp (fmt, "html")) { content_type = "text/html"; g_string_append (buf, "File: %s
MD5: %s