1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007, 2008 Red Hat, Inc.
6 #include "test-utils.h"
9 const char *title, *name;
12 /* Both fields must be filled in */
16 /* Filled-in but empty is OK */
17 { "", "", "Hello, " },
18 { "", "Name", "Hello, Name" },
19 { "Mr.", "", "Hello, MR. " },
22 { "Mr.", "Name", "Hello, MR. Name" },
24 /* Encoding of spaces */
25 { "Mr.", "Full Name", "Hello, MR. Full Name" },
26 { "Mr. and Mrs.", "Full Name", "Hello, MR. AND MRS. Full Name" },
29 { "Mr.+Mrs.", "Full Name", "Hello, MR.+MRS. Full Name" },
31 /* Encoding of non-ASCII. */
32 { "Se\xC3\xB1or", "Nombre", "Hello, SE\xC3\xB1OR Nombre" },
35 { "Mr.", "Foo %2f Bar", "Hello, MR. Foo %2f Bar" },
39 do_hello_test (int n, gboolean extra, const char *uri)
42 char *title_arg = NULL, *name_arg = NULL;
43 char *str_stdout = NULL;
46 debug_printf (1, "%2d. '%s' '%s'%s: ", n * 2 + (extra ? 2 : 1),
47 tests[n].title ? tests[n].title : "(null)",
48 tests[n].name ? tests[n].name : "(null)",
49 extra ? " + extra" : "");
51 args = g_ptr_array_new ();
52 g_ptr_array_add (args, "curl");
53 g_ptr_array_add (args, "--noproxy");
54 g_ptr_array_add (args, "*");
55 g_ptr_array_add (args, "-G");
57 title_arg = soup_form_encode ("title", tests[n].title, NULL);
58 g_ptr_array_add (args, "-d");
59 g_ptr_array_add (args, title_arg);
62 name_arg = soup_form_encode ("n@me", tests[n].name, NULL);
63 g_ptr_array_add (args, "-d");
64 g_ptr_array_add (args, name_arg);
67 g_ptr_array_add (args, "-d");
68 g_ptr_array_add (args, "extra=something");
70 g_ptr_array_add (args, (char *)uri);
71 g_ptr_array_add (args, NULL);
73 if (g_spawn_sync (NULL, (char **)args->pdata, NULL,
74 G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
76 &str_stdout, NULL, NULL, &error)) {
77 g_assert_cmpstr (str_stdout, ==, tests[n].result);
80 g_assert_no_error (error);
83 g_ptr_array_free (args, TRUE);
89 do_hello_tests (gconstpointer uri)
94 g_test_skip ("/usr/bin/curl is not available");
98 for (n = 0; n < G_N_ELEMENTS (tests); n++) {
99 do_hello_test (n, FALSE, uri);
100 do_hello_test (n, TRUE, uri);
104 #define MD5_TEST_FILE (g_test_get_filename (G_TEST_DIST, "index.txt", NULL))
105 #define MD5_TEST_FILE_BASENAME "index.txt"
106 #define MD5_TEST_FILE_MIME_TYPE "text/plain"
109 get_md5_data (char **contents, gsize *length)
111 char *my_contents, *md5;
113 GError *error = NULL;
115 if (!g_file_get_contents (MD5_TEST_FILE, &my_contents, &my_length, &error)) {
116 g_assert_no_error (error);
117 g_error_free (error);
121 md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, my_contents, my_length);
124 *contents = my_contents;
126 g_free (my_contents);
134 do_md5_test_curl (gconstpointer data)
136 const char *uri = data;
139 char *file_arg, *str_stdout;
140 GError *error = NULL;
143 g_test_skip ("/usr/bin/curl is not available");
147 md5 = get_md5_data (NULL, NULL);
151 args = g_ptr_array_new ();
152 g_ptr_array_add (args, "curl");
153 g_ptr_array_add (args, "--noproxy");
154 g_ptr_array_add (args, "*");
155 g_ptr_array_add (args, "-L");
156 g_ptr_array_add (args, "-F");
157 file_arg = g_strdup_printf ("file=@%s", MD5_TEST_FILE);
158 g_ptr_array_add (args, file_arg);
159 g_ptr_array_add (args, "-F");
160 g_ptr_array_add (args, "fmt=txt");
161 g_ptr_array_add (args, (char *)uri);
162 g_ptr_array_add (args, NULL);
164 if (g_spawn_sync (NULL, (char **)args->pdata, NULL,
165 G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
167 &str_stdout, NULL, NULL, NULL)) {
168 g_assert_cmpstr (str_stdout, ==, md5);
171 g_assert_no_error (error);
172 g_error_free (error);
174 g_ptr_array_free (args, TRUE);
181 do_md5_test_libsoup (gconstpointer data)
183 const char *uri = data;
184 char *contents, *md5;
186 SoupMultipart *multipart;
189 SoupSession *session;
191 g_test_bug ("601640");
193 md5 = get_md5_data (&contents, &length);
197 multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
198 buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length);
199 soup_multipart_append_form_file (multipart, "file",
200 MD5_TEST_FILE_BASENAME,
201 MD5_TEST_FILE_MIME_TYPE,
203 soup_buffer_free (buffer);
204 soup_multipart_append_form_string (multipart, "fmt", "text");
206 msg = soup_form_request_new_from_multipart (uri, multipart);
207 soup_multipart_free (multipart);
209 session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
210 soup_session_send_message (session, msg);
212 soup_test_assert_message_status (msg, SOUP_STATUS_OK);
213 g_assert_cmpstr (msg->response_body->data, ==, md5);
215 g_object_unref (msg);
216 soup_test_session_abort_unref (session);
223 do_form_decode_test (void)
230 g_test_skip ("/usr/bin/curl is not available");
234 /* Test that the code handles multiple values with the same key. */
235 table = soup_form_decode ("foo=first&foo=second&foo=third");
237 /* Allocate some memory. We do this to test for a bug in
238 * soup_form_decode() that resulted in values from the hash
239 * table pointing to memory that is already released.
241 tmp = g_strdup ("other");
243 value = g_hash_table_lookup (table, "foo");
244 g_assert_cmpstr (value, ==, "third");
247 g_hash_table_destroy (table);
251 hello_callback (SoupServer *server, SoupMessage *msg,
252 const char *path, GHashTable *query,
253 SoupClientContext *context, gpointer data)
255 char *title, *name, *fmt;
256 const char *content_type;
259 if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_HEAD) {
260 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
265 title = g_hash_table_lookup (query, "title");
266 name = g_hash_table_lookup (query, "n@me");
267 fmt = g_hash_table_lookup (query, "fmt");
269 title = name = fmt = NULL;
271 buf = g_string_new (NULL);
272 if (!query || (fmt && !strcmp (fmt, "html"))) {
273 content_type = "text/html";
274 g_string_append (buf, "<html><head><title>forms-test: hello</title></head><body>\r\n");
276 /* mumble mumble html-escape... */
277 g_string_append_printf (buf, "<p>Hello, <b><em>%s</em> %s</b></p>\r\n",
280 g_string_append (buf, "<form action='/hello' method='get'>"
281 "<p>Title: <input name='title'></p>"
282 "<p>Name: <input name='n@me'></p>"
283 "<p><input type=hidden name='fmt' value='html'></p>"
284 "<p><input type=submit></p>"
286 g_string_append (buf, "</body></html>\r\n");
288 content_type = "text/plain";
290 char *uptitle = g_ascii_strup (title, -1);
291 g_string_append_printf (buf, "Hello, %s %s",
297 soup_message_set_response (msg, content_type,
300 g_string_free (buf, FALSE);
301 soup_message_set_status (msg, SOUP_STATUS_OK);
305 md5_get_callback (SoupServer *server, SoupMessage *msg,
306 const char *path, GHashTable *query,
307 SoupClientContext *context, gpointer data)
309 const char *file = NULL, *md5sum = NULL, *fmt;
310 const char *content_type;
314 file = g_hash_table_lookup (query, "file");
315 md5sum = g_hash_table_lookup (query, "md5sum");
316 fmt = g_hash_table_lookup (query, "fmt");
320 buf = g_string_new (NULL);
321 if (!strcmp (fmt, "html")) {
322 content_type = "text/html";
323 g_string_append (buf, "<html><head><title>forms-test: md5</title></head><body>\r\n");
324 if (file && md5sum) {
325 /* mumble mumble html-escape... */
326 g_string_append_printf (buf, "<p>File: %s<br>MD5: <b>%s</b></p>\r\n",
329 g_string_append (buf, "<form action='/md5' method='post' enctype='multipart/form-data'>"
330 "<p>File: <input type='file' name='file'></p>"
331 "<p><input type=hidden name='fmt' value='html'></p>"
332 "<p><input type=submit></p>"
334 g_string_append (buf, "</body></html>\r\n");
336 content_type = "text/plain";
338 g_string_append_printf (buf, "%s", md5sum);
341 soup_message_set_response (msg, content_type,
344 g_string_free (buf, FALSE);
345 soup_message_set_status (msg, SOUP_STATUS_OK);
349 md5_post_callback (SoupServer *server, SoupMessage *msg,
350 const char *path, GHashTable *query,
351 SoupClientContext *context, gpointer data)
353 const char *content_type;
356 char *filename, *md5sum, *redirect_uri;
360 content_type = soup_message_headers_get_content_type (msg->request_headers, NULL);
361 if (!content_type || strcmp (content_type, "multipart/form-data") != 0) {
362 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
366 params = soup_form_decode_multipart (msg, "file",
367 &filename, NULL, &file);
369 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
372 fmt = g_hash_table_lookup (params, "fmt");
374 md5sum = g_compute_checksum_for_data (G_CHECKSUM_MD5,
375 (gpointer)file->data,
377 soup_buffer_free (file);
379 uri = soup_uri_copy (soup_message_get_uri (msg));
380 soup_uri_set_query_from_fields (uri,
381 "file", filename ? filename : "",
383 "fmt", fmt ? fmt : "html",
385 redirect_uri = soup_uri_to_string (uri, FALSE);
387 soup_message_set_redirect (msg, SOUP_STATUS_SEE_OTHER, redirect_uri);
389 g_free (redirect_uri);
393 g_hash_table_destroy (params);
397 md5_callback (SoupServer *server, SoupMessage *msg,
398 const char *path, GHashTable *query,
399 SoupClientContext *context, gpointer data)
401 if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD)
402 md5_get_callback (server, msg, path, query, context, data);
403 else if (msg->method == SOUP_METHOD_POST)
404 md5_post_callback (server, msg, path, query, context, data);
406 soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);
409 static gboolean run_tests = TRUE;
411 static GOptionEntry no_test_entry[] = {
412 { "no-tests", 'n', G_OPTION_FLAG_REVERSE,
413 G_OPTION_ARG_NONE, &run_tests,
414 "Don't run tests, just run the test server", NULL },
419 main (int argc, char **argv)
427 test_init (argc, argv, no_test_entry);
429 server = soup_test_server_new (TRUE);
430 soup_server_add_handler (server, "/hello",
431 hello_callback, NULL, NULL);
432 soup_server_add_handler (server, "/md5",
433 md5_callback, NULL, NULL);
434 port = soup_server_get_port (server);
436 loop = g_main_loop_new (NULL, TRUE);
439 uri_str = g_strdup_printf ("http://127.0.0.1:%u/hello", port);
440 g_test_add_data_func_full ("/forms/hello", uri_str, do_hello_tests, g_free);
442 uri_str = g_strdup_printf ("http://127.0.0.1:%u/md5", port);
443 g_test_add_data_func_full ("/forms/md5/curl", g_strdup (uri_str), do_md5_test_curl, g_free);
444 g_test_add_data_func_full ("/forms/md5/libsoup", g_strdup (uri_str), do_md5_test_libsoup, g_free);
447 g_test_add_func ("/forms/decode", do_form_decode_test);
451 g_print ("Listening on port %d\n", port);
452 g_main_loop_run (loop);
455 g_main_loop_unref (loop);
457 soup_test_server_quit_unref (server);