1 /* GLib testing framework examples and tests 2 * Copyright (C) 2008 Red Hat, Inc. 3 * Authors: Tomas Bzatek <tbzatek (at) redhat.com> 4 * 5 * This work is provided "as is"; redistribution and modification 6 * in whole or in part, in any medium, physical or electronic is 7 * permitted without restriction. 8 * 9 * This work 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. 12 * 13 * In no event shall the authors or contributors be liable for any 14 * direct, indirect, incidental, special, exemplary, or consequential 15 * damages (including, but not limited to, procurement of substitute 16 * goods or services; loss of use, data, or profits; or business 17 * interruption) however caused and on any theory of liability, whether 18 * in contract, strict liability, or tort (including negligence or 19 * otherwise) arising in any way out of the use of this software, even 20 * if advised of the possibility of such damage. 21 */ 22 23 #include <glib/glib.h> 24 #include <gio/gio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 struct TestPathsWithOper { 29 const char *path1; 30 gboolean equal; 31 gboolean use_uri; 32 const char *path2; 33 const char *path3; 34 }; 35 36 37 38 /* TODO: 39 * - test on Windows 40 * 41 **/ 42 43 static void 44 test_g_file_new_null (void) 45 { 46 const char *paths[] = {"/", 47 "/tmp///", 48 "/non-existent-file", 49 "/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 50 NULL 51 }; 52 const char *uris[] = {"file:///", 53 "file:///tmp///", 54 "non-existent-uri:///some-dir/", 55 "file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", 56 NULL 57 }; 58 59 GFile *file = NULL; 60 61 int i = 0; 62 while (paths[i]) 63 { 64 file = g_file_new_for_path (paths[i++]); 65 g_assert (file != NULL); 66 g_object_unref (file); 67 } 68 69 i = 0; 70 while (uris[i]) 71 { 72 file = g_file_new_for_uri (uris[i++]); 73 g_assert (file != NULL); 74 g_object_unref(file); 75 } 76 } 77 78 79 80 static gboolean 81 compare_two_files (const gboolean use_uri, const char *path1, const char *path2) 82 { 83 GFile *file1 = NULL; 84 GFile *file2 = NULL; 85 gboolean equal; 86 87 if (use_uri) 88 { 89 file1 = g_file_new_for_uri (path1); 90 file2 = g_file_new_for_uri (path2); 91 } 92 else 93 { 94 file1 = g_file_new_for_path (path1); 95 file2 = g_file_new_for_path (path2); 96 } 97 98 g_assert (file1 != NULL); 99 g_assert (file2 != NULL); 100 101 equal = g_file_equal (file1, file2); 102 103 g_object_unref (file1); 104 g_object_unref (file2); 105 106 return equal; 107 } 108 109 static void 110 test_g_file_new_for_path (void) 111 { 112 const struct TestPathsWithOper cmp_paths[] = 113 { 114 {"/", TRUE, 0, "/./"}, 115 {"//", TRUE, 0, "//"}, 116 {"//", TRUE, 0, "//./"}, 117 {"/", TRUE, 0, "/.//"}, 118 {"/", TRUE, 0, "/././"}, 119 {"/tmp", TRUE, 0, "/tmp/d/../"}, 120 {"/", TRUE, 0, "/somedir/../"}, 121 {"/", FALSE, 0, "/somedir/.../"}, 122 {"//tmp/dir1", TRUE, 0, "//tmp/dir1"}, 123 {"/tmp/dir1", TRUE, 0, "///tmp/dir1"}, 124 {"/tmp/dir1", TRUE, 0, "////tmp/dir1"}, 125 {"/tmp/dir1", TRUE, 0, "/tmp/./dir1"}, 126 {"/tmp/dir1", TRUE, 0, "/tmp//dir1"}, 127 {"/tmp/dir1", TRUE, 0, "/tmp///dir1///"}, 128 {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", TRUE, 0, "/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/"} 129 }; 130 131 int i; 132 for (i = 0; i < G_N_ELEMENTS (cmp_paths); i++) 133 { 134 gboolean equal = compare_two_files (FALSE, cmp_paths[i].path1, cmp_paths[i].path2); 135 g_assert_cmpint (equal, ==, cmp_paths[i].equal); 136 } 137 } 138 139 140 141 static void 142 test_g_file_new_for_uri (void) 143 { 144 const struct TestPathsWithOper cmp_uris[] = { 145 {"file:///", TRUE, 0, "file:///./"}, 146 {"file:////", TRUE, 0, "file:////"}, 147 {"file:////", TRUE, 0, "file:////./"}, 148 {"file:///", TRUE, 0, "file:///.//"}, 149 {"file:///", TRUE, 0, "file:///././"}, 150 {"file:///tmp", TRUE, 0, "file:///tmp/d/../"}, 151 {"file:///", TRUE, 0, "file:///somedir/../"}, 152 {"file:///", FALSE, 0, "file:///somedir/.../"}, 153 {"file:////tmp/dir1", TRUE, 0, "file:////tmp/dir1"}, 154 {"file:///tmp/dir1", TRUE, 0, "file:///tmp/./dir1"}, 155 {"file:///tmp/dir1", TRUE, 0, "file:///tmp//dir1"}, 156 {"file:///tmp/dir1", TRUE, 0, "file:///tmp///dir1///"}, 157 {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", TRUE, 0, "file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/"} 158 }; 159 160 int i; 161 for (i = 0; i < G_N_ELEMENTS (cmp_uris); i++) 162 { 163 gboolean equal = compare_two_files (TRUE, cmp_uris[i].path1, cmp_uris[i].path2); 164 g_assert_cmpint (equal, ==, cmp_uris[i].equal); 165 } 166 } 167 168 169 170 static gboolean 171 dup_equals (const gboolean use_uri, const char *path) 172 { 173 GFile *file1 = NULL; 174 GFile *file2 = NULL; 175 gboolean equal; 176 177 if (use_uri) 178 file1 = g_file_new_for_uri (path); 179 else 180 file1 = g_file_new_for_path (path); 181 182 g_assert (file1 != NULL); 183 184 file2 = g_file_dup (file1); 185 186 g_assert (file2 != NULL); 187 188 equal = g_file_equal (file1, file2); 189 190 g_object_unref (file1); 191 g_object_unref (file2); 192 193 return equal; 194 } 195 196 static void 197 test_g_file_dup (void) 198 { 199 const struct TestPathsWithOper dup_paths[] = 200 { 201 {"/", 0, FALSE, ""}, 202 {"file:///", 0, TRUE, ""}, 203 {"totalnonsense", 0, FALSE, ""}, 204 {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, ""}, 205 {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", 0, TRUE, ""}, 206 }; 207 208 int i; 209 for (i = 0; i < G_N_ELEMENTS (dup_paths); i++) 210 { 211 gboolean equal = dup_equals (dup_paths[i].use_uri, dup_paths[i].path1); 212 g_assert (equal == TRUE); 213 } 214 } 215 216 217 218 static gboolean 219 parse_check_utf8 (const gboolean use_uri, const char *path, const char *result_parse_name) 220 { 221 GFile *file1 = NULL; 222 GFile *file2 = NULL; 223 char *parsed_name; 224 gboolean is_utf8_valid; 225 gboolean equal; 226 227 if (use_uri) 228 file1 = g_file_new_for_uri (path); 229 else 230 file1 = g_file_new_for_path (path); 231 232 g_assert (file1 != NULL); 233 234 parsed_name = g_file_get_parse_name (file1); 235 236 g_assert (parsed_name != NULL); 237 238 /* UTF-8 validation */ 239 is_utf8_valid = g_utf8_validate (parsed_name, -1, NULL); 240 g_assert (is_utf8_valid == TRUE); 241 242 if (result_parse_name) 243 g_assert_cmpstr (parsed_name, ==, result_parse_name); 244 245 file2 = g_file_parse_name (parsed_name); 246 247 g_assert (file2 != NULL); 248 249 equal = g_file_equal (file1, file2); 250 251 g_object_unref (file1); 252 g_object_unref (file2); 253 254 g_free (parsed_name); 255 256 return equal; 257 } 258 259 static void 260 test_g_file_get_parse_name_utf8 (void) 261 { 262 const struct TestPathsWithOper strings[] = 263 { 264 {"/", 0, FALSE, "/"}, 265 {"file:///", 0, TRUE, "/"}, 266 {"totalnonsense", 0, FALSE, NULL}, 267 {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, NULL /* Depends on local file encoding */}, 268 {"file:///invalid%08/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, TRUE, "file:///invalid%08/UTF-8%20p\xc5\x99\xc3\xadli\xc5\xa1%20\xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd%20k\xc5\xaf\xc5\x88"}, 269 }; 270 271 int i; 272 for (i = 0; i < G_N_ELEMENTS (strings); i++) 273 { 274 gboolean equal = parse_check_utf8 (strings[i].use_uri, strings[i].path1, strings[i].path2); 275 g_assert (equal == TRUE); 276 } 277 } 278 279 static char * 280 resolve_arg (const gboolean is_uri_only, const char *arg) 281 { 282 GFile *file1 = NULL; 283 char *uri = NULL; 284 char *path = NULL; 285 char *s = NULL; 286 287 file1 = g_file_new_for_commandline_arg (arg); 288 g_assert (file1 != NULL); 289 290 /* Test if we get URI string */ 291 uri = g_file_get_uri (file1); 292 g_assert_cmpstr (uri, !=, NULL); 293 g_print ("%s\n",uri); 294 295 /* Test if we get correct value of the local path */ 296 path = g_file_get_path (file1); 297 if (is_uri_only) 298 g_assert_cmpstr (path, ==, NULL); 299 else 300 g_assert (g_path_is_absolute (path) == TRUE); 301 302 /* Get the URI scheme and compare it with expected one */ 303 s = g_file_get_uri_scheme (file1); 304 305 g_object_unref (file1); 306 g_free (uri); 307 g_free (path); 308 309 return s; 310 } 311 312 static void 313 test_g_file_new_for_commandline_arg (void) 314 { 315 /* TestPathsWithOper.use_uri represents IsURIOnly here */ 316 const struct TestPathsWithOper arg_data[] = 317 { 318 {"./", 0, FALSE, "file"}, 319 {"../", 0, FALSE, "file"}, 320 {"/tmp", 0, FALSE, "file"}, 321 {"//UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, "file"}, 322 {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, FALSE, "file"}, 323 #if 0 324 {"http://www.gtk.org/", 0, TRUE, "http"}, 325 {"ftp://user:pass@ftp.gimp.org/", 0, TRUE, "ftp"}, 326 #endif 327 }; 328 GFile *file; 329 char *resolved; 330 char *cwd; 331 int i; 332 333 for (i = 0; i < G_N_ELEMENTS (arg_data); i++) 334 { 335 char *s = resolve_arg (arg_data[i].use_uri, arg_data[i].path1); 336 g_assert_cmpstr (s, ==, arg_data[i].path2); 337 g_free (s); 338 } 339 340 /* Manual test for getting correct cwd */ 341 file = g_file_new_for_commandline_arg ("./"); 342 resolved = g_file_get_path (file); 343 cwd = g_get_current_dir (); 344 g_assert_cmpstr (resolved, ==, cwd); 345 g_object_unref (file); 346 g_free (resolved); 347 g_free (cwd); 348 } 349 350 static char* 351 get_relative_path (const gboolean use_uri, const gboolean should_have_prefix, const char *dir1, const char *dir2) 352 { 353 GFile *file1 = NULL; 354 GFile *file2 = NULL; 355 GFile *file3 = NULL; 356 gboolean has_prefix = FALSE; 357 char *relative_path = NULL; 358 359 if (use_uri) 360 { 361 file1 = g_file_new_for_uri (dir1); 362 file2 = g_file_new_for_uri (dir2); 363 } 364 else 365 { 366 file1 = g_file_new_for_path (dir1); 367 file2 = g_file_new_for_path (dir2); 368 } 369 370 g_assert (file1 != NULL); 371 g_assert (file2 != NULL); 372 373 has_prefix = g_file_has_prefix (file2, file1); 374 g_print ("%s %s\n", dir1, dir2); 375 g_assert (has_prefix == should_have_prefix); 376 377 relative_path = g_file_get_relative_path (file1, file2); 378 if (should_have_prefix) 379 { 380 g_assert (relative_path != NULL); 381 382 file3 = g_file_resolve_relative_path (file1, relative_path); 383 g_assert (g_file_equal (file2, file3) == TRUE); 384 } 385 386 if (file1) 387 g_object_unref (file1); 388 if (file2) 389 g_object_unref (file2); 390 if (file3) 391 g_object_unref (file3); 392 393 return relative_path; 394 } 395 396 static void 397 test_g_file_has_prefix (void) 398 { 399 /* TestPathsWithOper.equal represents here if the dir belongs to the directory structure */ 400 const struct TestPathsWithOper dirs[] = 401 { 402 /* path1 equal uri path2 path3 */ 403 {"/dir1", TRUE, FALSE, "/dir1/dir2/dir3/", "dir2/dir3"}, 404 {"/dir1/", TRUE, FALSE, "/dir1/dir2/dir3/", "dir2/dir3"}, 405 {"/dir1", TRUE, FALSE, "/dir1/dir2/dir3", "dir2/dir3"}, 406 {"/dir1/", TRUE, FALSE, "/dir1/dir2/dir3", "dir2/dir3"}, 407 {"/tmp/", FALSE, FALSE, "/something/", NULL}, 408 {"/dir1/dir2", FALSE, FALSE, "/dir1/", NULL}, 409 {"//dir1/new", TRUE, FALSE, "//dir1/new/dir2/dir3", "dir2/dir3"}, 410 {"/dir/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", TRUE, FALSE, "/dir/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/dir2", "dir2"}, 411 {"file:///dir1", TRUE, TRUE, "file:///dir1/dir2/dir3/", "dir2/dir3"}, 412 {"file:///dir1/", TRUE, TRUE, "file:///dir1/dir2/dir3/", "dir2/dir3"}, 413 {"file:///dir1", TRUE, TRUE, "file:///dir1/dir2/dir3", "dir2/dir3"}, 414 {"file:///dir1/", TRUE, TRUE, "file:///dir1/dir2/dir3", "dir2/dir3"}, 415 {"file:///tmp/", FALSE, TRUE, "file:///something/", NULL}, 416 {"file:///dir1/dir2", FALSE, TRUE, "file:///dir1/", NULL}, 417 {"file:////dir1/new", TRUE, TRUE, "file:////dir1/new/dir2/dir3", "dir2/dir3"}, 418 {"file:///dir/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", TRUE, TRUE, "file:///dir/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/dir2", "dir2"}, 419 #if 0 420 {"dav://www.gtk.org/plan/", TRUE, TRUE, "dav://www.gtk.org/plan/meetings/20071218.txt", "meetings/20071218.txt"}, 421 {"dav://www.gtk.org/plan/meetings", TRUE, TRUE, "dav://www.gtk.org/plan/meetings/20071218.txt", "20071218.txt"}, 422 #endif 423 }; 424 425 int i; 426 for (i = 0; i < G_N_ELEMENTS (dirs); i++) 427 { 428 char *s = get_relative_path (dirs[i].use_uri, dirs[i].equal, dirs[i].path1, dirs[i].path2); 429 if (dirs[i].equal) 430 g_assert_cmpstr (s, ==, dirs[i].path3); 431 g_free (s); 432 } 433 } 434 435 static void 436 roundtrip_parent_child (const gboolean use_uri, const gboolean under_root_descending, 437 const char *path, const char *dir_holder) 438 { 439 GFile *files[6] = {NULL}; 440 int i; 441 442 if (use_uri) 443 { 444 files[0] = g_file_new_for_uri (path); 445 files[1] = g_file_new_for_uri (path); 446 } 447 else 448 { 449 files[0] = g_file_new_for_path (path); 450 files[1] = g_file_new_for_path (path); 451 } 452 453 g_assert (files[0] != NULL); 454 g_assert (files[1] != NULL); 455 456 files[2] = g_file_get_child (files[1], dir_holder); 457 g_assert (files[2] != NULL); 458 459 files[3] = g_file_get_parent (files[2]); 460 g_assert (files[3] != NULL); 461 g_assert (g_file_equal (files[3], files[0]) == TRUE); 462 463 files[4] = g_file_get_parent (files[3]); 464 /* Don't go lower beyond the root */ 465 if (under_root_descending) 466 g_assert (files[4] == NULL); 467 else 468 { 469 g_assert (files[4] != NULL); 470 471 files[5] = g_file_get_child (files[4], dir_holder); 472 g_assert (files[5] != NULL); 473 g_assert (g_file_equal (files[5], files[0]) == TRUE); 474 } 475 476 for (i = 0; i < G_N_ELEMENTS (files); i++) 477 { 478 if (files[i]) 479 g_object_unref (files[i]); 480 } 481 } 482 483 static void 484 test_g_file_get_parent_child (void) 485 { 486 const struct TestPathsWithOper paths[] = 487 { 488 /* path root_desc uri dir_holder */ 489 {"/dir1/dir", FALSE, FALSE, "dir"}, 490 {"/dir", FALSE, FALSE, "dir"}, 491 {"/", TRUE, FALSE, "dir"}, 492 {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/", FALSE, FALSE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"}, 493 {"file:///dir1/dir", FALSE, TRUE, "dir"}, 494 {"file:///dir", FALSE, TRUE, "dir"}, 495 {"file:///", TRUE, TRUE, "dir"}, 496 {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", FALSE, TRUE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"}, 497 {"dav://www.gtk.org/plan/meetings", FALSE, TRUE, "meetings"}, 498 }; 499 500 int i; 501 for (i = 0; i < G_N_ELEMENTS (paths); i++) 502 roundtrip_parent_child (paths[i].use_uri, paths[i].equal, paths[i].path1, paths[i].path2); 503 } 504 505 int 506 main (int argc, 507 char *argv[]) 508 { 509 g_type_init (); 510 g_test_init (&argc, &argv, NULL); 511 512 513 /* Testing whether g_file_new_for_path() or g_file_new_for_uri() always returns non-NULL result */ 514 g_test_add_func ("/g-file/test_g_file_new_null", test_g_file_new_null); 515 516 /* Testing whether the g_file_new_for_path() correctly canonicalizes strings and two files equals (g_file_equal()) */ 517 g_test_add_func ("/g-file/test_g_file_new_for_path", test_g_file_new_for_path); 518 519 /* Testing whether the g_file_new_for_uri() correctly canonicalizes strings and two files equals (g_file_equal()) */ 520 g_test_add_func ("/g-file/test_g_file_new_for_uri", test_g_file_new_for_uri); 521 522 /* Testing g_file_dup() equals original file via g_file_equal() */ 523 g_test_add_func ("/g-file/test_g_file_dup", test_g_file_dup); 524 525 /* Testing g_file_get_parse_name() to return correct UTF-8 string */ 526 g_test_add_func ("/g-file/test_g_file_get_parse_name_utf8", test_g_file_get_parse_name_utf8); 527 528 /* Testing g_file_new_for_commandline_arg() for correct relavive path resolution and correct path/URI guess */ 529 g_test_add_func ("/g-file/test_g_file_new_for_commandline_arg", test_g_file_new_for_commandline_arg); 530 531 /* Testing g_file_has_prefix(), g_file_get_relative_path() and g_file_resolve_relative_path() to return and process correct relative paths */ 532 g_test_add_func ("/g-file/test_g_file_has_prefix", test_g_file_has_prefix); 533 534 /* Testing g_file_get_parent() and g_file_get_child() */ 535 g_test_add_func ("/g-file/test_g_file_get_parent_child", test_g_file_get_parent_child); 536 537 return g_test_run(); 538 } 539