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 #include <sys/stat.h> 28 29 #define DEFAULT_TEST_DIR "testdir_live-g-file" 30 31 #define PATTERN_FILE_SIZE 0x10000 32 #define TEST_HANDLE_SPECIAL TRUE 33 34 enum StructureExtraFlags 35 { 36 TEST_DELETE_NORMAL = 1 << 0, 37 TEST_DELETE_TRASH = 1 << 1, 38 TEST_DELETE_NON_EMPTY = 1 << 2, 39 TEST_DELETE_FAILURE = 1 << 3, 40 TEST_NOT_EXISTS = 1 << 4, 41 TEST_ENUMERATE_FILE = 1 << 5, 42 TEST_NO_ACCESS = 1 << 6, 43 TEST_COPY = 1 << 7, 44 TEST_MOVE = 1 << 8, 45 TEST_COPY_ERROR_RECURSE = 1 << 9, 46 TEST_ALREADY_EXISTS = 1 << 10, 47 TEST_TARGET_IS_FILE = 1 << 11, 48 TEST_CREATE = 1 << 12, 49 TEST_REPLACE = 1 << 13, 50 TEST_APPEND = 1 << 14, 51 TEST_OPEN = 1 << 15, 52 TEST_OVERWRITE = 1 << 16, 53 TEST_INVALID_SYMLINK = 1 << 17, 54 }; 55 56 struct StructureItem 57 { 58 const char *filename; 59 const char *link_to; 60 GFileType file_type; 61 GFileCreateFlags create_flags; 62 guint32 mode; 63 gboolean handle_special; 64 enum StructureExtraFlags extra_flags; 65 }; 66 67 #define TEST_DIR_NO_ACCESS "dir_no-access" 68 #define TEST_DIR_NO_WRITE "dir_no-write" 69 #define TEST_DIR_TARGET "dir-target" 70 #define TEST_NAME_NOT_EXISTS "not_exists" 71 #define TEST_TARGET_FILE "target-file" 72 73 74 static const struct StructureItem sample_struct[] = { 75 /* filename link file_type create_flags mode | handle_special | extra_flags */ 76 {"dir1", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_DELETE_NON_EMPTY | TEST_REPLACE | TEST_OPEN}, 77 {"dir1/subdir", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_COPY_ERROR_RECURSE | TEST_APPEND}, 78 {"dir2", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_MOVE | TEST_CREATE}, 79 {TEST_DIR_TARGET, NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_COPY_ERROR_RECURSE}, 80 {TEST_DIR_NO_ACCESS, NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_PRIVATE, S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP + S_IROTH + S_IWOTH, 0, TEST_NO_ACCESS | TEST_OPEN}, 81 {TEST_DIR_NO_WRITE, NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_PRIVATE, S_IRUSR + S_IXUSR + S_IRGRP + S_IXGRP + S_IROTH + S_IXOTH, 0, 0}, 82 {TEST_TARGET_FILE, NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OPEN}, 83 {"normal_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_CREATE | TEST_OVERWRITE}, 84 {"normal_file-symlink", "normal_file", G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_COPY | TEST_OPEN}, 85 {"executable_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, S_IRWXU + S_IRWXG + S_IRWXO, 0, TEST_DELETE_TRASH | TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_REPLACE}, 86 {"private_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_PRIVATE, 0, 0, TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_APPEND}, 87 {"normal_file2", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OVERWRITE | TEST_REPLACE}, 88 {"readonly_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, S_IRUSR + S_IRGRP + S_IROTH, 0, TEST_DELETE_NORMAL | TEST_OPEN}, 89 {"UTF_pr\xcc\x8ci\xcc\x81lis\xcc\x8c z", 90 NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_CREATE | TEST_OPEN | TEST_OVERWRITE}, 91 {"dir_pr\xcc\x8ci\xcc\x81lis\xcc\x8c z", 92 NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_CREATE}, 93 {"pattern_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_COPY | TEST_OPEN | TEST_APPEND}, 94 {TEST_NAME_NOT_EXISTS, NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_NORMAL | TEST_NOT_EXISTS | TEST_COPY | TEST_OPEN}, 95 {TEST_NAME_NOT_EXISTS, NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_TRASH | TEST_NOT_EXISTS | TEST_MOVE}, 96 {"not_exists2", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_CREATE}, 97 {"not_exists3", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_REPLACE}, 98 {"not_exists4", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_APPEND}, 99 {"dir_no-execute/file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_DELETE_NORMAL | TEST_DELETE_FAILURE | TEST_NOT_EXISTS | TEST_OPEN}, 100 {"lost_symlink", "nowhere", G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_DELETE_NORMAL | TEST_OPEN | TEST_INVALID_SYMLINK}, 101 }; 102 103 static gboolean write_test; 104 static gboolean verbose; 105 static gboolean posix_compat; 106 107 #ifdef G_HAVE_ISO_VARARGS 108 #define log(...) if (verbose) g_print (__VA_ARGS__) 109 #elif defined(G_HAVE_GNUC_VARARGS) 110 #define log(msg...) if (verbose) g_print (msg) 111 #else /* no varargs macros */ 112 static void log (const g_char *format, ...) 113 { 114 va_list args; 115 va_start (args, format); 116 if (verbose) g_print (format, args); 117 va_end (args); 118 } 119 #endif 120 121 static GFile * 122 create_empty_file (GFile * parent, const char *filename, 123 GFileCreateFlags create_flags) 124 { 125 GFile *child; 126 gboolean res; 127 GError *error; 128 GFileOutputStream *outs; 129 130 child = g_file_get_child (parent, filename); 131 g_assert (child != NULL); 132 133 error = NULL; 134 outs = g_file_replace (child, NULL, FALSE, create_flags, NULL, &error); 135 g_assert_no_error (error); 136 g_assert (outs != NULL); 137 error = NULL; 138 res = g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error); 139 g_object_unref (outs); 140 return child; 141 } 142 143 static GFile * 144 create_empty_dir (GFile * parent, const char *filename) 145 { 146 GFile *child; 147 gboolean res; 148 GError *error; 149 150 child = g_file_get_child (parent, filename); 151 g_assert (child != NULL); 152 error = NULL; 153 res = g_file_make_directory (child, NULL, &error); 154 g_assert_cmpint (res, ==, TRUE); 155 g_assert_no_error (error); 156 return child; 157 } 158 159 static GFile * 160 create_symlink (GFile * parent, const char *filename, const char *points_to) 161 { 162 GFile *child; 163 gboolean res; 164 GError *error; 165 166 child = g_file_get_child (parent, filename); 167 g_assert (child != NULL); 168 error = NULL; 169 res = g_file_make_symbolic_link (child, points_to, NULL, &error); 170 g_assert_cmpint (res, ==, TRUE); 171 g_assert_no_error (error); 172 return child; 173 } 174 175 static void 176 test_create_structure (gconstpointer test_data) 177 { 178 GFile *root; 179 GFile *child; 180 gboolean res; 181 GError *error; 182 GFileOutputStream *outs; 183 GDataOutputStream *outds; 184 int i; 185 struct StructureItem item; 186 187 g_assert (test_data != NULL); 188 log ("\n Going to create testing structure in '%s'...\n", 189 (char *) test_data); 190 191 root = g_file_new_for_commandline_arg ((char *) test_data); 192 g_assert (root != NULL); 193 194 /* create root directory */ 195 res = g_file_make_directory (root, NULL, NULL); 196 /* don't care about errors here */ 197 198 /* create any other items */ 199 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 200 { 201 item = sample_struct[i]; 202 if ((item.handle_special) 203 || ((!posix_compat) 204 && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))) 205 continue; 206 207 child = NULL; 208 switch (item.file_type) 209 { 210 case G_FILE_TYPE_REGULAR: 211 log (" Creating file '%s'...\n", item.filename); 212 child = create_empty_file (root, item.filename, item.create_flags); 213 break; 214 case G_FILE_TYPE_DIRECTORY: 215 log (" Creating directory '%s'...\n", item.filename); 216 child = create_empty_dir (root, item.filename); 217 break; 218 case G_FILE_TYPE_SYMBOLIC_LINK: 219 log (" Creating symlink '%s' --> '%s'...\n", item.filename, 220 item.link_to); 221 child = create_symlink (root, item.filename, item.link_to); 222 break; 223 default: 224 break; 225 } 226 g_assert (child != NULL); 227 228 if ((item.mode > 0) && (posix_compat)) 229 { 230 error = NULL; 231 res = 232 g_file_set_attribute_uint32 (child, G_FILE_ATTRIBUTE_UNIX_MODE, 233 item.mode, 234 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 235 NULL, &error); 236 g_assert_cmpint (res, ==, TRUE); 237 g_assert_no_error (error); 238 } 239 240 g_object_unref (child); 241 } 242 243 /* create a pattern file */ 244 log (" Creating pattern file..."); 245 child = g_file_get_child (root, "pattern_file"); 246 g_assert (child != NULL); 247 248 error = NULL; 249 outs = 250 g_file_replace (child, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error); 251 g_assert_no_error (error); 252 253 g_assert (outs != NULL); 254 outds = g_data_output_stream_new (G_OUTPUT_STREAM (outs)); 255 g_assert (outds != NULL); 256 for (i = 0; i < PATTERN_FILE_SIZE; i++) 257 { 258 error = NULL; 259 res = g_data_output_stream_put_byte (outds, i % 256, NULL, &error); 260 g_assert_no_error (error); 261 } 262 error = NULL; 263 res = g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error); 264 g_assert_no_error (error); 265 g_object_unref (outds); 266 g_object_unref (outs); 267 g_object_unref (child); 268 log (" done.\n"); 269 270 g_object_unref (root); 271 } 272 273 static GFile * 274 file_exists (GFile * parent, const char *filename, gboolean * result) 275 { 276 GFile *child; 277 gboolean res; 278 279 if (result) 280 *result = FALSE; 281 282 child = g_file_get_child (parent, filename); 283 g_assert (child != NULL); 284 res = g_file_query_exists (child, NULL); 285 if (result) 286 *result = res; 287 288 return child; 289 } 290 291 static void 292 test_attributes (struct StructureItem item, GFileInfo * info) 293 { 294 GFileType ftype; 295 guint32 mode; 296 const char *name, *display_name, *edit_name, *copy_name, *symlink_target; 297 gboolean utf8_valid; 298 gboolean has_attr; 299 gboolean is_symlink; 300 gboolean can_read, can_write; 301 302 /* standard::type */ 303 has_attr = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE); 304 g_assert_cmpint (has_attr, ==, TRUE); 305 ftype = g_file_info_get_file_type (info); 306 g_assert_cmpint (ftype, !=, G_FILE_TYPE_UNKNOWN); 307 g_assert_cmpint (ftype, ==, item.file_type); 308 309 /* unix::mode */ 310 if ((item.mode > 0) && (posix_compat)) 311 { 312 mode = 313 g_file_info_get_attribute_uint32 (info, 314 G_FILE_ATTRIBUTE_UNIX_MODE) & 0xFFF; 315 g_assert_cmpint (mode, ==, item.mode); 316 } 317 318 /* access::can-read */ 319 if (item.file_type != G_FILE_TYPE_SYMBOLIC_LINK) 320 { 321 can_read = 322 g_file_info_get_attribute_boolean (info, 323 G_FILE_ATTRIBUTE_ACCESS_CAN_READ); 324 g_assert_cmpint (can_read, ==, TRUE); 325 } 326 327 /* access::can-write */ 328 if ((write_test) && ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE)) 329 { 330 can_write = 331 g_file_info_get_attribute_boolean (info, 332 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); 333 g_assert_cmpint (can_write, ==, TRUE); 334 } 335 336 /* standard::name */ 337 name = g_file_info_get_name (info); 338 g_assert (name != NULL); 339 340 /* standard::display-name */ 341 display_name = g_file_info_get_display_name (info); 342 g_assert (display_name != NULL); 343 utf8_valid = g_utf8_validate (display_name, -1, NULL); 344 g_assert_cmpint (utf8_valid, ==, TRUE); 345 346 /* standard::edit-name */ 347 edit_name = g_file_info_get_edit_name (info); 348 if (edit_name) 349 { 350 utf8_valid = g_utf8_validate (edit_name, -1, NULL); 351 g_assert_cmpint (utf8_valid, ==, TRUE); 352 } 353 354 /* standard::copy-name */ 355 copy_name = 356 g_file_info_get_attribute_string (info, 357 G_FILE_ATTRIBUTE_STANDARD_COPY_NAME); 358 if (copy_name) 359 { 360 utf8_valid = g_utf8_validate (copy_name, -1, NULL); 361 g_assert_cmpint (utf8_valid, ==, TRUE); 362 } 363 364 /* standard::is-symlink */ 365 if (posix_compat) 366 { 367 is_symlink = g_file_info_get_is_symlink (info); 368 g_assert_cmpint (is_symlink, ==, 369 item.file_type == G_FILE_TYPE_SYMBOLIC_LINK); 370 } 371 372 /* standard::symlink-target */ 373 if ((item.file_type == G_FILE_TYPE_SYMBOLIC_LINK) && (posix_compat)) 374 { 375 symlink_target = g_file_info_get_symlink_target (info); 376 g_assert_cmpstr (symlink_target, ==, item.link_to); 377 } 378 } 379 380 static void 381 test_initial_structure (gconstpointer test_data) 382 { 383 GFile *root; 384 GFile *child; 385 gboolean res; 386 GError *error; 387 GFileInputStream *ins; 388 int i; 389 GFileInfo *info; 390 guint32 size; 391 guchar *buffer; 392 gssize read, total_read; 393 struct StructureItem item; 394 395 396 g_assert (test_data != NULL); 397 log ("\n Testing sample structure in '%s'...\n", (char *) test_data); 398 399 root = g_file_new_for_commandline_arg ((char *) test_data); 400 g_assert (root != NULL); 401 res = g_file_query_exists (root, NULL); 402 g_assert_cmpint (res, ==, TRUE); 403 404 /* test the structure */ 405 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 406 { 407 item = sample_struct[i]; 408 if (((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)) 409 || (item.handle_special)) 410 continue; 411 412 log (" Testing file '%s'...\n", item.filename); 413 414 child = file_exists (root, item.filename, &res); 415 g_assert (child != NULL); 416 g_assert_cmpint (res, ==, TRUE); 417 418 error = NULL; 419 info = 420 g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 421 NULL, &error); 422 g_assert_no_error (error); 423 g_assert (info != NULL); 424 425 test_attributes (item, info); 426 427 g_object_unref (child); 428 } 429 430 /* read and test the pattern file */ 431 log (" Testing pattern file...\n"); 432 child = file_exists (root, "pattern_file", &res); 433 g_assert (child != NULL); 434 g_assert_cmpint (res, ==, TRUE); 435 436 error = NULL; 437 info = 438 g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, 439 &error); 440 g_assert_no_error (error); 441 g_assert (info != NULL); 442 size = g_file_info_get_size (info); 443 g_assert_cmpint (size, ==, PATTERN_FILE_SIZE); 444 445 error = NULL; 446 ins = g_file_read (child, NULL, &error); 447 g_assert (ins != NULL); 448 g_assert_no_error (error); 449 450 buffer = g_malloc (PATTERN_FILE_SIZE); 451 total_read = 0; 452 453 while (total_read < PATTERN_FILE_SIZE) 454 { 455 error = NULL; 456 read = 457 g_input_stream_read (G_INPUT_STREAM (ins), buffer + total_read, 458 PATTERN_FILE_SIZE, NULL, &error); 459 g_assert_no_error (error); 460 total_read += read; 461 log (" read %d bytes, total = %d of %d.\n", read, total_read, 462 PATTERN_FILE_SIZE); 463 } 464 g_assert_cmpint (total_read, ==, PATTERN_FILE_SIZE); 465 466 error = NULL; 467 res = g_input_stream_close (G_INPUT_STREAM (ins), NULL, &error); 468 g_assert_no_error (error); 469 g_assert_cmpint (res, ==, TRUE); 470 471 for (i = 0; i < PATTERN_FILE_SIZE; i++) 472 g_assert_cmpint (*(buffer + i), ==, i % 256); 473 474 g_object_unref (ins); 475 g_object_unref (child); 476 g_free (buffer); 477 g_object_unref (root); 478 } 479 480 static void 481 traverse_recurse_dirs (GFile * parent, GFile * root) 482 { 483 gboolean res; 484 GError *error; 485 GFileEnumerator *enumerator; 486 GFileInfo *info; 487 GFile *descend; 488 char *relative_path; 489 int i; 490 gboolean found; 491 492 g_assert (root != NULL); 493 494 error = NULL; 495 enumerator = 496 g_file_enumerate_children (parent, "*", 497 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, 498 &error); 499 g_assert (enumerator != NULL); 500 g_assert_no_error (error); 501 502 error = NULL; 503 info = g_file_enumerator_next_file (enumerator, NULL, &error); 504 while ((info) && (!error)) 505 { 506 descend = g_file_get_child (parent, g_file_info_get_name (info)); 507 g_assert (descend != NULL); 508 relative_path = g_file_get_relative_path (root, descend); 509 g_assert (relative_path != NULL); 510 511 found = FALSE; 512 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 513 { 514 if (strcmp (sample_struct[i].filename, relative_path) == 0) 515 { 516 /* test the attributes again */ 517 test_attributes (sample_struct[i], info); 518 519 found = TRUE; 520 break; 521 } 522 } 523 g_assert_cmpint (found, ==, TRUE); 524 525 log (" Found file %s, relative to root: %s\n", 526 g_file_info_get_display_name (info), relative_path); 527 528 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) 529 traverse_recurse_dirs (descend, root); 530 531 g_object_unref (descend); 532 error = NULL; 533 info = g_file_enumerator_next_file (enumerator, NULL, &error); 534 } 535 g_assert_no_error (error); 536 537 error = NULL; 538 res = g_file_enumerator_close (enumerator, NULL, &error); 539 g_assert_cmpint (res, ==, TRUE); 540 g_assert_no_error (error); 541 } 542 543 static void 544 test_traverse_structure (gconstpointer test_data) 545 { 546 GFile *root; 547 gboolean res; 548 549 g_assert (test_data != NULL); 550 log ("\n Traversing through the sample structure in '%s'...\n", 551 (char *) test_data); 552 553 root = g_file_new_for_commandline_arg ((char *) test_data); 554 g_assert (root != NULL); 555 res = g_file_query_exists (root, NULL); 556 g_assert_cmpint (res, ==, TRUE); 557 558 traverse_recurse_dirs (root, root); 559 560 g_object_unref (root); 561 } 562 563 564 565 566 static void 567 test_enumerate (gconstpointer test_data) 568 { 569 GFile *root, *child; 570 gboolean res; 571 GError *error; 572 GFileEnumerator *enumerator; 573 GFileInfo *info; 574 int i; 575 struct StructureItem item; 576 577 578 g_assert (test_data != NULL); 579 log ("\n Test enumerate '%s'...\n", (char *) test_data); 580 581 root = g_file_new_for_commandline_arg ((char *) test_data); 582 g_assert (root != NULL); 583 res = g_file_query_exists (root, NULL); 584 g_assert_cmpint (res, ==, TRUE); 585 586 587 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 588 { 589 item = sample_struct[i]; 590 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)) 591 continue; 592 593 if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) || 594 (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) 595 && posix_compat) 596 || ((item.extra_flags & TEST_ENUMERATE_FILE) == 597 TEST_ENUMERATE_FILE)) 598 { 599 log (" Testing file '%s'\n", item.filename); 600 child = g_file_get_child (root, item.filename); 601 g_assert (child != NULL); 602 error = NULL; 603 enumerator = 604 g_file_enumerate_children (child, "*", 605 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 606 NULL, &error); 607 608 if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) 609 { 610 g_assert (enumerator == NULL); 611 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); 612 } 613 if ((item.extra_flags & TEST_ENUMERATE_FILE) == TEST_ENUMERATE_FILE) 614 { 615 g_assert (enumerator == NULL); 616 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY); 617 } 618 if ((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) 619 { 620 g_assert (enumerator != NULL); 621 622 error = NULL; 623 info = g_file_enumerator_next_file (enumerator, NULL, &error); 624 g_assert (info == NULL); 625 g_assert_no_error (error); 626 /* no items should be found, no error should be logged */ 627 } 628 629 if (error) 630 g_error_free (error); 631 632 if (enumerator) 633 { 634 error = NULL; 635 res = g_file_enumerator_close (enumerator, NULL, &error); 636 g_assert_cmpint (res, ==, TRUE); 637 g_assert_no_error (error); 638 } 639 g_object_unref (child); 640 } 641 } 642 g_object_unref (root); 643 } 644 645 static void 646 do_copy_move (GFile * root, struct StructureItem item, const char *target_dir, 647 enum StructureExtraFlags extra_flags) 648 { 649 GFile *dst_dir, *src_file, *dst_file; 650 gboolean res; 651 GError *error; 652 653 log (" do_copy_move: '%s' --> '%s'\n", item.filename, target_dir); 654 655 dst_dir = g_file_get_child (root, target_dir); 656 g_assert (dst_dir != NULL); 657 src_file = g_file_get_child (root, item.filename); 658 g_assert (src_file != NULL); 659 dst_file = g_file_get_child (dst_dir, item.filename); 660 g_assert (dst_file != NULL); 661 662 error = NULL; 663 if ((item.extra_flags & TEST_COPY) == TEST_COPY) 664 res = 665 g_file_copy (src_file, dst_file, 666 G_FILE_COPY_NOFOLLOW_SYMLINKS | 667 ((extra_flags == 668 TEST_OVERWRITE) ? G_FILE_COPY_OVERWRITE : 669 G_FILE_COPY_NONE), NULL, NULL, NULL, &error); 670 else 671 res = 672 g_file_move (src_file, dst_file, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, 673 NULL, NULL, &error); 674 675 if (error) 676 log (" res = %d, error code %d = %s\n", res, error->code, 677 error->message); 678 679 /* copying file/directory to itself (".") */ 680 if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) && 681 (extra_flags == TEST_ALREADY_EXISTS)) 682 { 683 g_assert_cmpint (res, ==, FALSE); 684 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); 685 } 686 /* target file is a file, overwrite is not set */ 687 else if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) && 688 (extra_flags == TEST_TARGET_IS_FILE)) 689 { 690 g_assert_cmpint (res, ==, FALSE); 691 if (item.file_type == G_FILE_TYPE_DIRECTORY) 692 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE); 693 else 694 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY); 695 } 696 /* source file is directory */ 697 else if ((item.extra_flags & TEST_COPY_ERROR_RECURSE) == 698 TEST_COPY_ERROR_RECURSE) 699 { 700 g_assert_cmpint (res, ==, FALSE); 701 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE); 702 } 703 /* source or target path doesn't exist */ 704 else if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) || 705 (extra_flags == TEST_NOT_EXISTS)) 706 { 707 g_assert_cmpint (res, ==, FALSE); 708 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); 709 } 710 /* source or target path permission denied */ 711 else if (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) || 712 (extra_flags == TEST_NO_ACCESS)) 713 { 714 g_assert_cmpint (res, ==, FALSE); 715 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED); 716 } 717 /* no error should be found, all exceptions defined above */ 718 else 719 { 720 g_assert_cmpint (res, ==, TRUE); 721 g_assert_no_error (error); 722 } 723 724 if (error) 725 g_error_free (error); 726 727 728 g_object_unref (dst_dir); 729 g_object_unref (src_file); 730 g_object_unref (dst_file); 731 } 732 733 static void 734 test_copy_move (gconstpointer test_data) 735 { 736 GFile *root; 737 gboolean res; 738 int i; 739 struct StructureItem item; 740 741 log ("\n"); 742 743 g_assert (test_data != NULL); 744 root = g_file_new_for_commandline_arg ((char *) test_data); 745 g_assert (root != NULL); 746 res = g_file_query_exists (root, NULL); 747 g_assert_cmpint (res, ==, TRUE); 748 749 750 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 751 { 752 item = sample_struct[i]; 753 754 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)) 755 continue; 756 757 if (((item.extra_flags & TEST_COPY) == TEST_COPY) || 758 ((item.extra_flags & TEST_MOVE) == TEST_MOVE)) 759 { 760 /* test copy/move to a directory, expecting no errors if source files exist */ 761 do_copy_move (root, item, TEST_DIR_TARGET, 0); 762 763 /* some files have been already moved so we can't count with them in the tests */ 764 if ((item.extra_flags & TEST_COPY) == TEST_COPY) 765 { 766 /* test overwrite for flagged files */ 767 if ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE) 768 { 769 do_copy_move (root, item, TEST_DIR_TARGET, TEST_OVERWRITE); 770 } 771 /* source = target, should return G_IO_ERROR_EXISTS */ 772 do_copy_move (root, item, ".", TEST_ALREADY_EXISTS); 773 /* target is file */ 774 do_copy_move (root, item, TEST_TARGET_FILE, 775 TEST_TARGET_IS_FILE); 776 /* target path is invalid */ 777 do_copy_move (root, item, TEST_NAME_NOT_EXISTS, 778 TEST_NOT_EXISTS); 779 780 /* tests on POSIX-compatible filesystems */ 781 if (posix_compat) 782 { 783 /* target directory is not accessible (no execute flag) */ 784 do_copy_move (root, item, TEST_DIR_NO_ACCESS, 785 TEST_NO_ACCESS); 786 /* target directory is readonly */ 787 do_copy_move (root, item, TEST_DIR_NO_WRITE, 788 TEST_NO_ACCESS); 789 } 790 } 791 } 792 } 793 g_object_unref (root); 794 } 795 796 static void 797 test_create (gconstpointer test_data) 798 { 799 GFile *root, *child; 800 gboolean res; 801 GError *error; 802 int i; 803 struct StructureItem item; 804 GFileOutputStream *os; 805 806 g_assert (test_data != NULL); 807 log ("\n"); 808 809 root = g_file_new_for_commandline_arg ((char *) test_data); 810 g_assert (root != NULL); 811 res = g_file_query_exists (root, NULL); 812 g_assert_cmpint (res, ==, TRUE); 813 814 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 815 { 816 item = sample_struct[i]; 817 818 if (((item.extra_flags & TEST_CREATE) == TEST_CREATE) || 819 ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE) || 820 ((item.extra_flags & TEST_APPEND) == TEST_APPEND)) 821 { 822 log (" test_create: '%s'\n", item.filename); 823 824 child = g_file_get_child (root, item.filename); 825 g_assert (child != NULL); 826 error = NULL; 827 os = NULL; 828 829 if ((item.extra_flags & TEST_CREATE) == TEST_CREATE) 830 os = g_file_create (child, item.create_flags, NULL, &error); 831 else if ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE) 832 os = 833 g_file_replace (child, NULL, TRUE, item.create_flags, NULL, 834 &error); 835 else if ((item.extra_flags & TEST_APPEND) == TEST_APPEND) 836 os = g_file_append_to (child, item.create_flags, NULL, &error); 837 838 839 if (error) 840 log (" error code %d = %s\n", error->code, error->message); 841 842 if (((item.extra_flags & TEST_NOT_EXISTS) == 0) && 843 ((item.extra_flags & TEST_CREATE) == TEST_CREATE)) 844 { 845 g_assert (os == NULL); 846 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); 847 } 848 else if (item.file_type == G_FILE_TYPE_DIRECTORY) 849 { 850 g_assert (os == NULL); 851 if ((item.extra_flags & TEST_CREATE) == TEST_CREATE) 852 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); 853 else 854 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY); 855 } 856 else 857 { 858 g_assert (os != NULL); 859 g_assert_no_error (error); 860 } 861 862 if (error) 863 g_error_free (error); 864 865 if (os) 866 { 867 error = NULL; 868 res = 869 g_output_stream_close (G_OUTPUT_STREAM (os), NULL, &error); 870 if (error) 871 log (" g_output_stream_close: error %d = %s\n", 872 error->code, error->message); 873 g_assert_cmpint (res, ==, TRUE); 874 g_assert_no_error (error); 875 } 876 g_object_unref (child); 877 } 878 } 879 g_object_unref (root); 880 } 881 882 static void 883 test_open (gconstpointer test_data) 884 { 885 GFile *root, *child; 886 gboolean res; 887 GError *error; 888 int i; 889 struct StructureItem item; 890 GFileInputStream *input_stream; 891 892 g_assert (test_data != NULL); 893 log ("\n"); 894 895 root = g_file_new_for_commandline_arg ((char *) test_data); 896 g_assert (root != NULL); 897 res = g_file_query_exists (root, NULL); 898 g_assert_cmpint (res, ==, TRUE); 899 900 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 901 { 902 item = sample_struct[i]; 903 904 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)) 905 continue; 906 907 if ((item.extra_flags & TEST_OPEN) == TEST_OPEN) 908 { 909 log (" test_open: '%s'\n", item.filename); 910 911 child = g_file_get_child (root, item.filename); 912 g_assert (child != NULL); 913 error = NULL; 914 input_stream = g_file_read (child, NULL, &error); 915 916 if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) || 917 ((item.extra_flags & TEST_INVALID_SYMLINK) == 918 TEST_INVALID_SYMLINK)) 919 { 920 g_assert (input_stream == NULL); 921 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); 922 } 923 else if (item.file_type == G_FILE_TYPE_DIRECTORY) 924 { 925 g_assert (input_stream == NULL); 926 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY); 927 } 928 else 929 { 930 g_assert (input_stream != NULL); 931 g_assert_no_error (error); 932 } 933 934 if (error) 935 g_error_free (error); 936 937 if (input_stream) 938 { 939 error = NULL; 940 res = 941 g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, 942 &error); 943 g_assert_cmpint (res, ==, TRUE); 944 g_assert_no_error (error); 945 } 946 g_object_unref (child); 947 } 948 } 949 g_object_unref (root); 950 } 951 952 static void 953 test_delete (gconstpointer test_data) 954 { 955 GFile *root; 956 GFile *child; 957 gboolean res; 958 GError *error; 959 int i; 960 struct StructureItem item; 961 962 g_assert (test_data != NULL); 963 log ("\n"); 964 965 root = g_file_new_for_commandline_arg ((char *) test_data); 966 g_assert (root != NULL); 967 res = g_file_query_exists (root, NULL); 968 g_assert_cmpint (res, ==, TRUE); 969 970 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++) 971 { 972 item = sample_struct[i]; 973 974 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)) 975 continue; 976 977 if (((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL) || 978 ((item.extra_flags & TEST_DELETE_TRASH) == TEST_DELETE_TRASH)) 979 { 980 child = file_exists (root, item.filename, &res); 981 g_assert (child != NULL); 982 /* we don't care about result here */ 983 984 log (" Deleting %s, path = %s\n", item.filename, 985 g_file_get_path (child)); 986 error = NULL; 987 if ((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL) 988 res = g_file_delete (child, NULL, &error); 989 else 990 res = g_file_trash (child, NULL, &error); 991 992 if ((item.extra_flags & TEST_DELETE_NON_EMPTY) == 993 TEST_DELETE_NON_EMPTY) 994 { 995 g_assert_cmpint (res, ==, FALSE); 996 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY); 997 } 998 if ((item.extra_flags & TEST_DELETE_FAILURE) == TEST_DELETE_FAILURE) 999 { 1000 g_assert_cmpint (res, ==, FALSE); 1001 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); 1002 } 1003 if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) 1004 { 1005 g_assert_cmpint (res, ==, FALSE); 1006 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); 1007 } 1008 1009 if (error) 1010 { 1011 log (" result = %d, error = %s\n", res, error->message); 1012 g_error_free (error); 1013 } 1014 1015 g_object_unref (child); 1016 } 1017 } 1018 g_object_unref (root); 1019 } 1020 1021 1022 static void 1023 cleanup_dir_recurse (GFile *parent, GFile *root) 1024 { 1025 gboolean res; 1026 GError *error; 1027 GFileEnumerator *enumerator; 1028 GFileInfo *info; 1029 GFile *descend; 1030 char *relative_path; 1031 1032 g_assert (root != NULL); 1033 1034 error = NULL; 1035 enumerator = 1036 g_file_enumerate_children (parent, "*", 1037 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, 1038 &error); 1039 if (! enumerator) 1040 return; 1041 1042 error = NULL; 1043 info = g_file_enumerator_next_file (enumerator, NULL, &error); 1044 while ((info) && (!error)) 1045 { 1046 descend = g_file_get_child (parent, g_file_info_get_name (info)); 1047 g_assert (descend != NULL); 1048 relative_path = g_file_get_relative_path (root, descend); 1049 g_assert (relative_path != NULL); 1050 1051 log (" deleting '%s'\n", g_file_info_get_display_name (info)); 1052 1053 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) 1054 cleanup_dir_recurse (descend, root); 1055 1056 error = NULL; 1057 res = g_file_delete (descend, NULL, &error); 1058 g_assert_cmpint (res, ==, TRUE); 1059 1060 g_object_unref (descend); 1061 error = NULL; 1062 info = g_file_enumerator_next_file (enumerator, NULL, &error); 1063 } 1064 g_assert_no_error (error); 1065 1066 error = NULL; 1067 res = g_file_enumerator_close (enumerator, NULL, &error); 1068 g_assert_cmpint (res, ==, TRUE); 1069 g_assert_no_error (error); 1070 } 1071 1072 static void 1073 prep_clean_structure (gconstpointer test_data) 1074 { 1075 GFile *root; 1076 1077 g_assert (test_data != NULL); 1078 log ("\n Cleaning target testing structure in '%s'...\n", 1079 (char *) test_data); 1080 1081 root = g_file_new_for_commandline_arg ((char *) test_data); 1082 g_assert (root != NULL); 1083 1084 cleanup_dir_recurse (root, root); 1085 1086 g_file_delete (root, NULL, NULL); 1087 1088 g_object_unref (root); 1089 } 1090 1091 int 1092 main (int argc, char *argv[]) 1093 { 1094 static gboolean only_create_struct; 1095 static char *target_path; 1096 GError *error; 1097 GOptionContext *context; 1098 1099 static GOptionEntry cmd_entries[] = { 1100 {"read-write", 'w', 0, G_OPTION_ARG_NONE, &write_test, 1101 "Perform write tests (incl. structure creation)", NULL}, 1102 {"create-struct", 'c', 0, G_OPTION_ARG_NONE, &only_create_struct, 1103 "Only create testing structure (no tests)", NULL}, 1104 {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL}, 1105 {"posix", 'x', 0, G_OPTION_ARG_NONE, &posix_compat, 1106 "Test POSIX-specific features (unix permissions, symlinks)", NULL}, 1107 {NULL} 1108 }; 1109 1110 verbose = FALSE; 1111 write_test = FALSE; 1112 only_create_struct = FALSE; 1113 target_path = NULL; 1114 posix_compat = FALSE; 1115 1116 /* strip all gtester-specific args */ 1117 g_type_init (); 1118 g_test_init (&argc, &argv, NULL); 1119 1120 /* no extra parameters specified, assume we're executed from glib test suite */ 1121 if (argc < 2) 1122 { 1123 verbose = TRUE; 1124 write_test = TRUE; 1125 only_create_struct = FALSE; 1126 target_path = DEFAULT_TEST_DIR; 1127 #ifdef G_PLATFORM_WIN32 1128 posix_compat = FALSE; 1129 #else 1130 posix_compat = TRUE; 1131 #endif 1132 } 1133 1134 /* add trailing args */ 1135 error = NULL; 1136 context = g_option_context_new ("target_path"); 1137 g_option_context_add_main_entries (context, cmd_entries, NULL); 1138 if (!g_option_context_parse (context, &argc, &argv, &error)) 1139 { 1140 g_print ("option parsing failed: %s\n", error->message); 1141 return g_test_run (); 1142 } 1143 1144 /* remaining arg should is the target path; we don't care of the extra args here */ 1145 if (argc >= 2) 1146 target_path = strdup (argv[1]); 1147 1148 if (! target_path) 1149 { 1150 g_print ("error: target path was not specified\n"); 1151 g_print ("%s", g_option_context_get_help (context, TRUE, NULL)); 1152 return g_test_run (); 1153 } 1154 1155 1156 /* Write test - clean target directory first */ 1157 /* this can be also considered as a test - enumerate + delete */ 1158 if (write_test || only_create_struct) 1159 g_test_add_data_func ("/live-g-file/prep_clean_structure", target_path, 1160 prep_clean_structure); 1161 1162 /* Write test - create new testing structure */ 1163 if (write_test || only_create_struct) 1164 g_test_add_data_func ("/live-g-file/create_structure", target_path, 1165 test_create_structure); 1166 1167 /* Read test - test the sample structure - expect defined attributes to be there */ 1168 if (!only_create_struct) 1169 g_test_add_data_func ("/live-g-file/test_initial_structure", target_path, 1170 test_initial_structure); 1171 1172 /* Read test - test traverse the structure - no special file should appear */ 1173 if (!only_create_struct) 1174 g_test_add_data_func ("/live-g-file/test_traverse_structure", target_path, 1175 test_traverse_structure); 1176 1177 /* Read test - enumerate */ 1178 if (!only_create_struct) 1179 g_test_add_data_func ("/live-g-file/test_enumerate", target_path, 1180 test_enumerate); 1181 1182 /* Read test - open (g_file_read()) */ 1183 if (!only_create_struct) 1184 g_test_add_data_func ("/live-g-file/test_open", target_path, test_open); 1185 1186 /* Write test - create */ 1187 if (write_test && (!only_create_struct)) 1188 g_test_add_data_func ("/live-g-file/test_create", target_path, 1189 test_create); 1190 1191 /* Write test - copy, move */ 1192 if (write_test && (!only_create_struct)) 1193 g_test_add_data_func ("/live-g-file/test_copy_move", target_path, 1194 test_copy_move); 1195 1196 /* Write test - delete, trash */ 1197 if (write_test && (!only_create_struct)) 1198 g_test_add_data_func ("/live-g-file/test_delete", target_path, 1199 test_delete); 1200 1201 if (write_test || only_create_struct) 1202 g_test_add_data_func ("/live-g-file/final_clean", target_path, 1203 prep_clean_structure); 1204 1205 return g_test_run (); 1206 1207 } 1208