uri-test.c revision 8df27c8dd5cf7ca192d64373fb15b5c63dc510b6
1/* GLIB - Library of useful routines for C programming 2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 * Boston, MA 02111-1307, USA. 18 */ 19 20/* 21 * Modified by the GLib Team and others 1997-2000. See the AUTHORS 22 * file for a list of people on the GLib Team. See the ChangeLog 23 * files for a list of changes. These files are distributed with 24 * GLib at ftp://ftp.gtk.org/pub/gtk/. 25 */ 26 27#undef G_DISABLE_ASSERT 28#undef G_LOG_DOMAIN 29 30#include <config.h> 31 32#include <glib.h> 33#include <stdio.h> 34#include <string.h> 35#include <stdlib.h> 36 37typedef struct 38{ 39 char *filename; 40 char *hostname; 41 char *expected_result; 42 GConvertError expected_error; /* If failed */ 43} ToUriTest; 44 45ToUriTest 46to_uri_tests[] = { 47 { "/etc", NULL, "file:///etc"}, 48 { "/etc", "", "file:///etc"}, 49 { "/etc", "otherhost", "file://otherhost/etc"}, 50#ifdef G_OS_WIN32 51 { "/etc", "localhost", "file:///etc"}, 52 { "c:\\windows", NULL, "file:///c:/windows"}, 53 { "c:\\windows", "localhost", "file:///c:/windows"}, 54 { "c:\\windows", "otherhost", "file://otherhost/c:/windows"}, 55 { "\\\\server\\share\\dir", NULL, "file:////server/share/dir"}, 56 { "\\\\server\\share\\dir", "localhost", "file:////server/share/dir"}, 57#else 58 { "/etc", "localhost", "file://localhost/etc"}, 59 { "c:\\windows", NULL, NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, /* it's important to get this error on Unix */ 60 { "c:\\windows", "localhost", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 61 { "c:\\windows", "otherhost", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 62#endif 63 { "etc", "localhost", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 64#ifndef G_PLATFORM_WIN32 65 { "/etc/\xE5\xE4\xF6", NULL, "file:///etc/%E5%E4%F6" }, 66 { "/etc/\xC3\xB6\xC3\xA4\xC3\xA5", NULL, "file:///etc/%C3%B6%C3%A4%C3%A5"}, 67#endif 68 { "/etc", "\xC3\xB6\xC3\xA4\xC3\xA5", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 69 { "/etc", "\xE5\xE4\xF6", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 70 { "/etc/file with #%", NULL, "file:///etc/file%20with%20%23%25"}, 71 { "", NULL, NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 72 { "", "", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 73 { "", "localhost", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 74 { "", "otherhost", NULL, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH}, 75 { "/0123456789", NULL, "file:///0123456789"}, 76 { "/ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL, "file:///ABCDEFGHIJKLMNOPQRSTUVWXYZ"}, 77 { "/abcdefghijklmnopqrstuvwxyz", NULL, "file:///abcdefghijklmnopqrstuvwxyz"}, 78 { "/-_.!~*'()", NULL, "file:///-_.!~*'()"}, 79#ifdef G_OS_WIN32 80 /* As '\\' is a path separator on Win32, it gets turned into '/' in the URI */ 81 { "/\"#%<>[\\]^`{|}\x7F", NULL, "file:///%22%23%25%3C%3E%5B/%5D%5E%60%7B%7C%7D%7F"}, 82#else 83 /* On Unix, '\\' is a normal character in the file name */ 84 { "/\"#%<>[\\]^`{|}\x7F", NULL, "file:///%22%23%25%3C%3E%5B%5C%5D%5E%60%7B%7C%7D%7F"}, 85#endif 86 { "/;@+$,", NULL, "file:///%3B@+$,"}, 87 /* This and some of the following are of course as such illegal file names on Windows, 88 * and would not occur in real life. 89 */ 90 { "/:", NULL, "file:///:"}, 91 { "/?&=", NULL, "file:///%3F&="}, 92 { "/", "0123456789-", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 93 { "/", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "file://ABCDEFGHIJKLMNOPQRSTUVWXYZ/"}, 94 { "/", "abcdefghijklmnopqrstuvwxyz", "file://abcdefghijklmnopqrstuvwxyz/"}, 95 { "/", "_.!~*'()", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 96 { "/", "\"#%<>[\\]^`{|}\x7F", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 97 { "/", ";?&=+$,", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 98 { "/", "/", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 99 { "/", "@:", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 100 { "/", "\x80\xFF", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 101 { "/", "\xC3\x80\xC3\xBF", NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE}, 102}; 103 104 105typedef struct 106{ 107 char *uri; 108 char *expected_filename; 109 char *expected_hostname; 110 GConvertError expected_error; /* If failed */ 111} FromUriTest; 112 113FromUriTest 114from_uri_tests[] = { 115 { "file:///etc", "/etc"}, 116 { "file:/etc", "/etc"}, 117#ifdef G_OS_WIN32 118 /* On Win32 we don't return "localhost" hostames, just in case 119 * it isn't recognized anyway. 120 */ 121 { "file://localhost/etc", "/etc", NULL}, 122 { "file://localhost/etc/%23%25%20file", "/etc/#% file", NULL}, 123#else 124 { "file://localhost/etc", "/etc", "localhost"}, 125 { "file://localhost/etc/%23%25%20file", "/etc/#% file", "localhost"}, 126#endif 127 { "file://otherhost/etc", "/etc", "otherhost"}, 128 { "file://otherhost/etc/%23%25%20file", "/etc/#% file", "otherhost"}, 129 { "file://%C3%B6%C3%A4%C3%A5/etc", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 130 { "file:////etc/%C3%B6%C3%C3%C3%A5", "//etc/\xc3\xb6\xc3\xc3\xc3\xa5", NULL}, 131 { "file://localhost/\xE5\xE4\xF6", "/\xe5\xe4\xf6", "localhost"}, 132 { "file://\xE5\xE4\xF6/etc", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 133 { "file://localhost/%E5%E4%F6", "/\xe5\xe4\xf6", "localhost"}, 134 { "file://%E5%E4%F6/etc", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 135 { "file:///some/file#bad", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 136 { "file://some", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 137 { "", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 138 { "file:test", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 139 { "http://www.yahoo.com/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 140 { "file:////etc", "//etc"}, 141 { "file://///etc", "///etc"}, 142#ifdef G_OS_WIN32 143 /* URIs with backslashes come from some nonstandard application, but accept them anyhow */ 144 { "file:///c:\\foo", "c:\\foo"}, 145 { "file:///c:/foo\\bar", "c:\\foo\\bar"}, 146 /* Accept also the old Netscape drive-letter-and-vertical bar convention */ 147 { "file:///c|/foo", "c:\\foo"}, 148 { "file:////server/share/dir", "\\\\server\\share\\dir"}, 149 { "file://localhost//server/share/foo", "\\\\server\\share\\foo"}, 150 { "file://otherhost//server/share/foo", "\\\\server\\share\\foo", "otherhost"}, 151#else 152 { "file:///c:\\foo", "/c:\\foo"}, 153 { "file:///c:/foo", "/c:/foo"}, 154 { "file:////c:/foo", "//c:/foo"}, 155#endif 156 { "file://0123456789/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 157 { "file://ABCDEFGHIJKLMNOPQRSTUVWXYZ/", "/", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"}, 158 { "file://abcdefghijklmnopqrstuvwxyz/", "/", "abcdefghijklmnopqrstuvwxyz"}, 159 { "file://-_.!~*'()/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 160 { "file://\"<>[\\]^`{|}\x7F/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 161 { "file://;?&=+$,/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 162 { "file://%C3%80%C3%BF/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 163 { "file://@/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 164 { "file://:/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 165 { "file://#/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 166 { "file://%23/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 167 { "file://%2F/", NULL, NULL, G_CONVERT_ERROR_BAD_URI}, 168}; 169 170 171static gboolean any_failed = FALSE; 172 173static void 174run_to_uri_tests (void) 175{ 176 int i; 177 gchar *res; 178 GError *error; 179 180 for (i = 0; i < G_N_ELEMENTS (to_uri_tests); i++) 181 { 182 error = NULL; 183 res = g_filename_to_uri (to_uri_tests[i].filename, 184 to_uri_tests[i].hostname, 185 &error); 186 187 if (to_uri_tests[i].expected_result == NULL) 188 { 189 if (res != NULL) 190 { 191 g_print ("\ng_filename_to_uri() test %d failed, expected to return NULL, actual result: %s\n", i, res); 192 any_failed = TRUE; 193 } 194 else 195 { 196 if (error == NULL) 197 { 198 g_print ("\ng_filename_to_uri() test %d failed, returned NULL, but didn't set error\n", i); 199 any_failed = TRUE; 200 } 201 else if (error->domain != G_CONVERT_ERROR) 202 { 203 g_print ("\ng_filename_to_uri() test %d failed, returned NULL, set non G_CONVERT_ERROR error\n", i); 204 any_failed = TRUE; 205 } 206 else if (error->code != to_uri_tests[i].expected_error) 207 { 208 g_print ("\ng_filename_to_uri() test %d failed as expected, but set wrong errorcode %d instead of expected %d \n", 209 i, error->code, to_uri_tests[i].expected_error); 210 any_failed = TRUE; 211 } 212 } 213 } 214 else if (res == NULL || strcmp (res, to_uri_tests[i].expected_result) != 0) 215 { 216 g_print ("\ng_filename_to_uri() test %d failed, expected result: %s, actual result: %s\n", 217 i, to_uri_tests[i].expected_result, (res) ? res : "NULL"); 218 if (error) 219 g_print ("Error message: %s\n", error->message); 220 any_failed = TRUE; 221 } 222 223 /* Give some output */ 224 g_print ("."); 225 } 226} 227 228static void 229run_from_uri_tests (void) 230{ 231 int i; 232 gchar *res; 233 gchar *hostname; 234 GError *error; 235 236 for (i = 0; i < G_N_ELEMENTS (from_uri_tests); i++) 237 { 238 error = NULL; 239 res = g_filename_from_uri (from_uri_tests[i].uri, 240 &hostname, 241 &error); 242 243 if (from_uri_tests[i].expected_filename == NULL) 244 { 245 if (res != NULL) 246 { 247 g_print ("\ng_filename_from_uri() test %d failed, expected to return NULL, actual result: %s\n", i, res); 248 any_failed = TRUE; 249 } 250 else 251 { 252 if (error == NULL) 253 { 254 g_print ("\ng_filename_from_uri() test %d failed, returned NULL, but didn't set error\n", i); 255 any_failed = TRUE; 256 } 257 else if (error->domain != G_CONVERT_ERROR) 258 { 259 g_print ("\ng_filename_from_uri() test %d failed, returned NULL, set non G_CONVERT_ERROR error\n", i); 260 any_failed = TRUE; 261 } 262 else if (error->code != from_uri_tests[i].expected_error) 263 { 264 g_print ("\ng_filename_from_uri() test %d failed as expected, but set wrong errorcode %d instead of expected %d \n", 265 i, error->code, from_uri_tests[i].expected_error); 266 any_failed = TRUE; 267 } 268 } 269 } 270 else 271 { 272#ifdef G_OS_WIN32 273 gchar *slash, *p; 274 275 p = from_uri_tests[i].expected_filename = g_strdup (from_uri_tests[i].expected_filename); 276 while ((slash = strchr (p, '/')) != NULL) 277 { 278 *slash = '\\'; 279 p = slash + 1; 280 } 281#endif 282 if (res == NULL || strcmp (res, from_uri_tests[i].expected_filename) != 0) 283 { 284 g_print ("\ng_filename_from_uri() test %d failed, expected result: %s, actual result: %s\n", 285 i, from_uri_tests[i].expected_filename, (res) ? res : "NULL"); 286 any_failed = TRUE; 287 } 288 289 if (from_uri_tests[i].expected_hostname == NULL) 290 { 291 if (hostname != NULL) 292 { 293 g_print ("\ng_filename_from_uri() test %d failed, expected no hostname, got: %s\n", 294 i, hostname); 295 any_failed = TRUE; 296 } 297 } 298 else if (hostname == NULL || 299 strcmp (hostname, from_uri_tests[i].expected_hostname) != 0) 300 { 301 g_print ("\ng_filename_from_uri() test %d failed, expected hostname: %s, actual result: %s\n", 302 i, from_uri_tests[i].expected_hostname, (hostname) ? hostname : "NULL"); 303 any_failed = TRUE; 304 } 305 } 306 307 /* Give some output */ 308 g_print ("."); 309 } 310} 311 312static gint 313safe_strcmp (const gchar *a, const gchar *b) 314{ 315 return strcmp (a ? a : "", b ? b : ""); 316} 317 318static void 319run_roundtrip_tests (void) 320{ 321 int i; 322 gchar *uri, *hostname, *res; 323 GError *error; 324 325 for (i = 0; i < G_N_ELEMENTS (to_uri_tests); i++) 326 { 327 if (to_uri_tests[i].expected_error != 0) 328 continue; 329 330 error = NULL; 331 uri = g_filename_to_uri (to_uri_tests[i].filename, 332 to_uri_tests[i].hostname, 333 &error); 334 335 if (error != NULL) 336 { 337 g_print ("g_filename_to_uri failed unexpectedly: %s\n", 338 error->message); 339 any_failed = TRUE; 340 continue; 341 } 342 343 error = NULL; 344 res = g_filename_from_uri (uri, &hostname, &error); 345 if (error != NULL) 346 { 347 g_print ("g_filename_from_uri failed unexpectedly: %s\n", 348 error->message); 349 any_failed = TRUE; 350 continue; 351 } 352 353 if (safe_strcmp (to_uri_tests[i].filename, res)) 354 { 355 g_print ("roundtrip test %d failed, filename modified: " 356 " expected \"%s\", but got \"%s\"\n", 357 i, to_uri_tests[i].filename, res); 358 any_failed = TRUE; 359 } 360 361 if (safe_strcmp (to_uri_tests[i].hostname, hostname)) 362 { 363 g_print ("roundtrip test %d failed, hostname modified: " 364 " expected \"%s\", but got \"%s\"\n", 365 i, to_uri_tests[i].hostname, hostname); 366 any_failed = TRUE; 367 } 368 369 /* Give some output */ 370 g_print ("."); 371 } 372 g_print ("\n"); 373} 374 375static void 376run_uri_list_tests (void) 377{ 378 /* straight from the RFC */ 379 gchar *list = 380 "# urn:isbn:0-201-08372-8\r\n" 381 "http://www.huh.org/books/foo.html\r\n" 382 "http://www.huh.org/books/foo.pdf \r\n" 383 " ftp://ftp.foo.org/books/foo.txt\r\n"; 384 gchar *expected_uris[] = { 385 "http://www.huh.org/books/foo.html", 386 "http://www.huh.org/books/foo.pdf", 387 "ftp://ftp.foo.org/books/foo.txt" 388 }; 389 390 gchar **uris; 391 gint j; 392 393 uris = g_uri_list_extract_uris (list); 394 395 if (g_strv_length (uris) != 3) 396 { 397 g_print ("uri list test failed: " 398 " expected %d uris, but got %d\n", 399 3, g_strv_length (uris)); 400 any_failed = TRUE; 401 } 402 403 for (j = 0; j < 3; j++) 404 { 405 if (safe_strcmp (uris[j], expected_uris[j])) 406 { 407 g_print ("uri list test failed: " 408 " expected \"%s\", but got \"%s\"\n", 409 expected_uris[j], uris[j]); 410 any_failed = TRUE; 411 } 412 } 413 414 g_strfreev (uris); 415 416 uris = g_uri_list_extract_uris ("# just hot air\r\n# more hot air"); 417 if (g_strv_length (uris) != 0) 418 { 419 g_print ("uri list test 2 failed: " 420 " expected %d uris, but got %d (first is \"%s\")\n", 421 0, g_strv_length (uris), uris[0]); 422 any_failed = TRUE; 423 } 424 425} 426 427int 428main (int argc, 429 char *argv[]) 430{ 431#ifdef G_OS_UNIX 432# ifdef HAVE_UNSETENV 433 unsetenv ("G_BROKEN_FILENAMES"); 434# else 435 /* putenv with no = isn't standard, but works to unset the variable 436 * on some systems 437 */ 438 putenv ("G_BROKEN_FILENAMES"); 439# endif 440#endif 441 442 run_to_uri_tests (); 443 run_from_uri_tests (); 444 run_roundtrip_tests (); 445 run_uri_list_tests (); 446 447 return any_failed ? 1 : 0; 448} 449