1 /* GLib testing framework examples and tests
2 * Copyright (C) 2008 Red Hat, Inc.
3 * Authors: Tomas Bzatek <tbzatek@redhat.com>
5 * SPDX-License-Identifier: LicenseRef-old-glib-tests
7 * This work is provided "as is"; redistribution and modification
8 * in whole or in part, in any medium, physical or electronic is
9 * permitted without restriction.
11 * This work is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * In no event shall the authors or contributors be liable for any
16 * direct, indirect, incidental, special, exemplary, or consequential
17 * damages (including, but not limited to, procurement of substitute
18 * goods or services; loss of use, data, or profits; or business
19 * interruption) however caused and on any theory of liability, whether
20 * in contract, strict liability, or tort (including negligence or
21 * otherwise) arising in any way out of the use of this software, even
22 * if advised of the possibility of such damage.
25 #include <glib/glib.h>
31 #include <sys/types.h>
35 #define DEFAULT_TEST_DIR "testdir_live-g-file"
37 #define PATTERN_FILE_SIZE 0x10000
38 #define TEST_HANDLE_SPECIAL TRUE
40 enum StructureExtraFlags
42 TEST_DELETE_NORMAL = 1 << 0,
43 TEST_DELETE_TRASH = 1 << 1,
44 TEST_DELETE_NON_EMPTY = 1 << 2,
45 TEST_DELETE_FAILURE = 1 << 3,
46 TEST_NOT_EXISTS = 1 << 4,
47 TEST_ENUMERATE_FILE = 1 << 5,
48 TEST_NO_ACCESS = 1 << 6,
51 TEST_COPY_ERROR_RECURSE = 1 << 9,
52 TEST_ALREADY_EXISTS = 1 << 10,
53 TEST_TARGET_IS_FILE = 1 << 11,
54 TEST_CREATE = 1 << 12,
55 TEST_REPLACE = 1 << 13,
56 TEST_APPEND = 1 << 14,
58 TEST_OVERWRITE = 1 << 16,
59 TEST_INVALID_SYMLINK = 1 << 17,
60 TEST_HIDDEN = 1 << 18,
61 TEST_DOT_HIDDEN = 1 << 19,
69 GFileCreateFlags create_flags;
71 gboolean handle_special;
72 enum StructureExtraFlags extra_flags;
75 #define TEST_DIR_NO_ACCESS "dir_no-access"
76 #define TEST_DIR_NO_WRITE "dir_no-write"
77 #define TEST_DIR_TARGET "dir-target"
78 #define TEST_NAME_NOT_EXISTS "not_exists"
79 #define TEST_TARGET_FILE "target-file"
82 static const struct StructureItem sample_struct[] = {
83 /* filename link file_type create_flags mode | handle_special | extra_flags */
84 {"dir1", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_DELETE_NON_EMPTY | TEST_REPLACE | TEST_OPEN},
85 {"dir1/subdir", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_COPY_ERROR_RECURSE | TEST_APPEND},
86 {"dir2", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_MOVE | TEST_CREATE},
87 {TEST_DIR_TARGET, NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_COPY_ERROR_RECURSE},
88 {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},
89 {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},
90 {TEST_TARGET_FILE, NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OPEN},
91 {"normal_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_CREATE | TEST_OVERWRITE},
92 {"normal_file-symlink", "normal_file", G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_ENUMERATE_FILE | TEST_COPY | TEST_OPEN},
93 {"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},
94 {"private_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_PRIVATE, 0, 0, TEST_COPY | TEST_OPEN | TEST_OVERWRITE | TEST_APPEND},
95 {"normal_file2", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_OVERWRITE | TEST_REPLACE},
96 {"readonly_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, S_IRUSR + S_IRGRP + S_IROTH, 0, TEST_DELETE_NORMAL | TEST_OPEN},
97 {"UTF_pr\xcc\x8ci\xcc\x81lis\xcc\x8c z",
98 NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_CREATE | TEST_OPEN | TEST_OVERWRITE},
99 {"dir_pr\xcc\x8ci\xcc\x81lis\xcc\x8c z",
100 NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, TEST_DELETE_NORMAL | TEST_CREATE},
101 {"pattern_file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_COPY | TEST_OPEN | TEST_APPEND},
102 {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},
103 {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},
104 {"not_exists2", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_CREATE},
105 {"not_exists3", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_REPLACE},
106 {"not_exists4", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, TEST_NOT_EXISTS | TEST_APPEND},
107 {"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},
108 {"lost_symlink", "nowhere", G_FILE_TYPE_SYMBOLIC_LINK, G_FILE_CREATE_NONE, 0, 0, TEST_COPY | TEST_DELETE_NORMAL | TEST_OPEN | TEST_INVALID_SYMLINK},
109 {"dir_hidden", NULL, G_FILE_TYPE_DIRECTORY, G_FILE_CREATE_NONE, 0, 0, 0},
110 {"dir_hidden/.hidden", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, TEST_HANDLE_SPECIAL, 0},
111 {"dir_hidden/.a-hidden-file", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_HIDDEN},
112 {"dir_hidden/file-in-.hidden1", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_HIDDEN | TEST_DOT_HIDDEN},
113 {"dir_hidden/file-in-.hidden2", NULL, G_FILE_TYPE_REGULAR, G_FILE_CREATE_NONE, 0, 0, TEST_HIDDEN | TEST_DOT_HIDDEN},
116 static gboolean test_suite;
117 static gboolean write_test;
118 static gboolean verbose;
119 static gboolean posix_compat;
123 * check_cap_dac_override:
124 * @tmpdir: A temporary directory in which we can create and delete files
126 * Check whether the current process can bypass DAC permissions.
128 * Traditionally, "privileged" processes (those with effective uid 0)
129 * could do this (and bypass many other checks), and "unprivileged"
130 * processes could not.
132 * In Linux, the special powers of euid 0 are divided into many
133 * capabilities: see `capabilities(7)`. The one we are interested in
134 * here is `CAP_DAC_OVERRIDE`.
136 * We do this generically instead of actually looking at the capability
137 * bits, so that the right thing will happen on non-Linux Unix
138 * implementations, in particular if they have something equivalent to
139 * but not identical to Linux permissions.
141 * Returns: %TRUE if we have Linux `CAP_DAC_OVERRIDE` or equivalent
145 check_cap_dac_override (const char *tmpdir)
147 gchar *dac_denies_write;
151 dac_denies_write = g_build_filename (tmpdir, "dac-denies-write", NULL);
152 inside = g_build_filename (dac_denies_write, "inside", NULL);
154 g_assert_no_errno (mkdir (dac_denies_write, S_IRWXU));
155 g_assert_no_errno (chmod (dac_denies_write, 0));
157 if (mkdir (inside, S_IRWXU) == 0)
159 g_test_message ("Looks like we have CAP_DAC_OVERRIDE or equivalent");
160 g_assert_no_errno (rmdir (inside));
165 int saved_errno = errno;
167 g_test_message ("We do not have CAP_DAC_OVERRIDE or equivalent");
168 g_assert_cmpint (saved_errno, ==, EACCES);
172 g_assert_no_errno (chmod (dac_denies_write, S_IRWXU));
173 g_assert_no_errno (rmdir (dac_denies_write));
174 g_free (dac_denies_write);
181 create_empty_file (GFile * parent, const char *filename,
182 GFileCreateFlags create_flags)
186 GFileOutputStream *outs;
188 child = g_file_get_child (parent, filename);
189 g_assert_nonnull (child);
192 outs = g_file_replace (child, NULL, FALSE, create_flags, NULL, &error);
193 g_assert_no_error (error);
194 g_assert_nonnull (outs);
196 g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error);
197 g_object_unref (outs);
202 create_empty_dir (GFile * parent, const char *filename)
208 child = g_file_get_child (parent, filename);
209 g_assert_nonnull (child);
211 res = g_file_make_directory (child, NULL, &error);
213 g_assert_no_error (error);
218 create_symlink (GFile * parent, const char *filename, const char *points_to)
224 child = g_file_get_child (parent, filename);
225 g_assert_nonnull (child);
227 res = g_file_make_symbolic_link (child, points_to, NULL, &error);
229 g_assert_no_error (error);
234 test_create_structure (gconstpointer test_data)
239 GError *error = NULL;
240 GFileOutputStream *outs;
241 GDataOutputStream *outds;
243 struct StructureItem item;
245 g_assert_nonnull (test_data);
246 g_test_message ("\n Going to create testing structure in '%s'...",
249 root = g_file_new_for_commandline_arg ((char *) test_data);
250 g_assert_nonnull (root);
252 /* create root directory */
253 g_file_make_directory (root, NULL, &error);
254 g_assert_no_error (error);
256 /* create any other items */
257 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
259 item = sample_struct[i];
260 if ((item.handle_special)
262 && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK)))
266 switch (item.file_type)
268 case G_FILE_TYPE_REGULAR:
269 g_test_message (" Creating file '%s'...", item.filename);
270 child = create_empty_file (root, item.filename, item.create_flags);
272 case G_FILE_TYPE_DIRECTORY:
273 g_test_message (" Creating directory '%s'...", item.filename);
274 child = create_empty_dir (root, item.filename);
276 case G_FILE_TYPE_SYMBOLIC_LINK:
277 g_test_message (" Creating symlink '%s' --> '%s'...", item.filename,
279 child = create_symlink (root, item.filename, item.link_to);
281 case G_FILE_TYPE_UNKNOWN:
282 case G_FILE_TYPE_SPECIAL:
283 case G_FILE_TYPE_SHORTCUT:
284 case G_FILE_TYPE_MOUNTABLE:
288 g_assert_nonnull (child);
290 if ((item.mode > 0) && (posix_compat))
293 g_file_set_attribute_uint32 (child, G_FILE_ATTRIBUTE_UNIX_MODE,
295 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
298 g_assert_no_error (error);
301 if ((item.extra_flags & TEST_DOT_HIDDEN) == TEST_DOT_HIDDEN)
303 gchar *dir, *path, *basename;
306 dir = g_path_get_dirname (item.filename);
307 basename = g_path_get_basename (item.filename);
308 path = g_build_filename (test_data, dir, ".hidden", NULL);
310 f = fopen (path, "a");
311 fprintf (f, "%s\n", basename);
319 g_object_unref (child);
322 /* create a pattern file */
323 g_test_message (" Creating pattern file...");
324 child = g_file_get_child (root, "pattern_file");
325 g_assert_nonnull (child);
328 g_file_replace (child, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error);
329 g_assert_no_error (error);
331 g_assert_nonnull (outs);
332 outds = g_data_output_stream_new (G_OUTPUT_STREAM (outs));
333 g_assert_nonnull (outds);
334 for (i = 0; i < PATTERN_FILE_SIZE; i++)
336 g_data_output_stream_put_byte (outds, i % 256, NULL, &error);
337 g_assert_no_error (error);
340 g_output_stream_close (G_OUTPUT_STREAM (outs), NULL, &error);
341 g_assert_no_error (error);
342 g_object_unref (outds);
343 g_object_unref (outs);
344 g_object_unref (child);
345 g_test_message (" done.");
347 g_object_unref (root);
351 file_exists (GFile * parent, const char *filename, gboolean * result)
359 child = g_file_get_child (parent, filename);
360 g_assert_nonnull (child);
361 res = g_file_query_exists (child, NULL);
369 test_attributes (struct StructureItem item, GFileInfo * info)
373 const char *name, *display_name, *edit_name, *copy_name, *symlink_target;
378 gboolean can_read, can_write;
381 has_attr = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
382 g_assert_true (has_attr);
383 ftype = g_file_info_get_file_type (info);
384 g_assert_cmpint (ftype, !=, G_FILE_TYPE_UNKNOWN);
385 g_assert_cmpint (ftype, ==, item.file_type);
388 if ((item.mode > 0) && (posix_compat))
391 g_file_info_get_attribute_uint32 (info,
392 G_FILE_ATTRIBUTE_UNIX_MODE) & 0xFFF;
393 g_assert_cmpint (mode, ==, item.mode);
396 /* access::can-read */
397 if (item.file_type != G_FILE_TYPE_SYMBOLIC_LINK)
400 g_file_info_get_attribute_boolean (info,
401 G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
402 g_assert_true (can_read);
405 /* access::can-write */
406 if ((write_test) && ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE))
409 g_file_info_get_attribute_boolean (info,
410 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
411 g_assert_true (can_write);
415 name = g_file_info_get_name (info);
416 g_assert_nonnull (name);
418 /* standard::display-name */
419 display_name = g_file_info_get_display_name (info);
420 g_assert_nonnull (display_name);
421 utf8_valid = g_utf8_validate (display_name, -1, NULL);
422 g_assert_true (utf8_valid);
424 /* standard::edit-name */
425 edit_name = g_file_info_get_edit_name (info);
428 utf8_valid = g_utf8_validate (edit_name, -1, NULL);
429 g_assert_true (utf8_valid);
432 /* standard::copy-name */
434 g_file_info_get_attribute_string (info,
435 G_FILE_ATTRIBUTE_STANDARD_COPY_NAME);
438 utf8_valid = g_utf8_validate (copy_name, -1, NULL);
439 g_assert_true (utf8_valid);
442 /* standard::is-symlink */
445 is_symlink = g_file_info_get_is_symlink (info);
446 g_assert_cmpint (is_symlink, ==,
447 item.file_type == G_FILE_TYPE_SYMBOLIC_LINK);
450 /* standard::symlink-target */
451 if ((item.file_type == G_FILE_TYPE_SYMBOLIC_LINK) && (posix_compat))
453 symlink_target = g_file_info_get_symlink_target (info);
454 g_assert_cmpstr (symlink_target, ==, item.link_to);
457 /* standard::is-hidden */
458 if ((item.extra_flags & TEST_HIDDEN) == TEST_HIDDEN)
461 g_file_info_get_attribute_boolean (info,
462 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
463 g_assert_true (is_hidden);
466 /* unix::is-mountpoint */
469 gboolean is_mountpoint =
470 g_file_info_get_attribute_boolean (info,
471 G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT);
472 g_assert_false (is_mountpoint);
477 test_initial_structure (gconstpointer test_data)
483 GFileInputStream *ins;
488 gssize read, total_read;
489 struct StructureItem item;
491 g_assert_nonnull (test_data);
492 g_test_message (" Testing sample structure in '%s'...", (char *) test_data);
494 root = g_file_new_for_commandline_arg ((char *) test_data);
495 g_assert_nonnull (root);
496 res = g_file_query_exists (root, NULL);
499 /* test the structure */
500 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
502 item = sample_struct[i];
503 if (((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
504 || (item.handle_special))
507 g_test_message (" Testing file '%s'...", item.filename);
509 child = file_exists (root, item.filename, &res);
510 g_assert_nonnull (child);
515 g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
517 g_assert_no_error (error);
518 g_assert_nonnull (info);
520 test_attributes (item, info);
522 g_object_unref (child);
523 g_object_unref (info);
526 /* read and test the pattern file */
527 g_test_message (" Testing pattern file...");
528 child = file_exists (root, "pattern_file", &res);
529 g_assert_nonnull (child);
534 g_file_query_info (child, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
536 g_assert_no_error (error);
537 g_assert_nonnull (info);
538 size = g_file_info_get_size (info);
539 g_assert_cmpint (size, ==, PATTERN_FILE_SIZE);
540 g_object_unref (info);
543 ins = g_file_read (child, NULL, &error);
544 g_assert_nonnull (ins);
545 g_assert_no_error (error);
547 buffer = g_malloc (PATTERN_FILE_SIZE);
550 while (total_read < PATTERN_FILE_SIZE)
554 g_input_stream_read (G_INPUT_STREAM (ins), buffer + total_read,
555 PATTERN_FILE_SIZE, NULL, &error);
556 g_assert_no_error (error);
558 g_test_message (" read %"G_GSSIZE_FORMAT" bytes, total = %"G_GSSIZE_FORMAT" of %d.",
559 read, total_read, PATTERN_FILE_SIZE);
561 g_assert_cmpint (total_read, ==, PATTERN_FILE_SIZE);
564 res = g_input_stream_close (G_INPUT_STREAM (ins), NULL, &error);
565 g_assert_no_error (error);
568 for (i = 0; i < PATTERN_FILE_SIZE; i++)
569 g_assert_cmpint (*(buffer + i), ==, i % 256);
571 g_object_unref (ins);
572 g_object_unref (child);
574 g_object_unref (root);
578 traverse_recurse_dirs (GFile * parent, GFile * root)
582 GFileEnumerator *enumerator;
589 g_assert_nonnull (root);
593 g_file_enumerate_children (parent, "*",
594 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
596 g_assert_nonnull (enumerator);
597 g_assert_no_error (error);
599 g_assert_true (g_file_enumerator_get_container (enumerator) == parent);
602 info = g_file_enumerator_next_file (enumerator, NULL, &error);
603 while ((info) && (!error))
605 descend = g_file_enumerator_get_child (enumerator, info);
606 g_assert_nonnull (descend);
607 relative_path = g_file_get_relative_path (root, descend);
608 g_assert_nonnull (relative_path);
611 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
613 if (strcmp (sample_struct[i].filename, relative_path) == 0)
615 /* test the attributes again */
616 test_attributes (sample_struct[i], info);
622 g_assert_true (found);
624 g_test_message (" Found file %s, relative to root: %s",
625 g_file_info_get_display_name (info), relative_path);
627 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
628 traverse_recurse_dirs (descend, root);
630 g_object_unref (descend);
632 g_object_unref (info);
633 g_free (relative_path);
635 info = g_file_enumerator_next_file (enumerator, NULL, &error);
637 g_assert_no_error (error);
640 res = g_file_enumerator_close (enumerator, NULL, &error);
642 g_assert_no_error (error);
643 g_assert_true (g_file_enumerator_is_closed (enumerator));
645 g_object_unref (enumerator);
649 test_traverse_structure (gconstpointer test_data)
654 g_assert_nonnull (test_data);
655 g_test_message (" Traversing through the sample structure in '%s'...",
658 root = g_file_new_for_commandline_arg ((char *) test_data);
659 g_assert_nonnull (root);
660 res = g_file_query_exists (root, NULL);
663 traverse_recurse_dirs (root, root);
665 g_object_unref (root);
672 test_enumerate (gconstpointer test_data)
677 GFileEnumerator *enumerator;
680 struct StructureItem item;
683 g_assert_nonnull (test_data);
684 g_test_message (" Test enumerate '%s'...", (char *) test_data);
686 root = g_file_new_for_commandline_arg ((char *) test_data);
687 g_assert_nonnull (root);
688 res = g_file_query_exists (root, NULL);
692 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
694 item = sample_struct[i];
695 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
698 if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
699 (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS)
701 || ((item.extra_flags & TEST_ENUMERATE_FILE) ==
702 TEST_ENUMERATE_FILE))
704 g_test_message (" Testing file '%s'", item.filename);
705 child = g_file_get_child (root, item.filename);
706 g_assert_nonnull (child);
709 g_file_enumerate_children (child, "*",
710 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
713 if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS)
715 g_assert_null (enumerator);
716 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
718 if ((item.extra_flags & TEST_ENUMERATE_FILE) == TEST_ENUMERATE_FILE)
720 g_assert_null (enumerator);
721 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY);
723 if ((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS)
725 g_assert_nonnull (enumerator);
728 info = g_file_enumerator_next_file (enumerator, NULL, &error);
729 g_assert_null (info);
730 g_assert_no_error (error);
731 /* no items should be found, no error should be logged */
735 g_error_free (error);
740 res = g_file_enumerator_close (enumerator, NULL, &error);
742 g_assert_no_error (error);
744 g_object_unref (enumerator);
746 g_object_unref (child);
749 g_object_unref (root);
753 do_copy_move (GFile * root, struct StructureItem item, const char *target_dir,
754 enum StructureExtraFlags extra_flags)
756 GFile *dst_dir, *src_file, *dst_file;
760 gboolean have_cap_dac_override = check_cap_dac_override (g_file_peek_path (root));
763 g_test_message (" do_copy_move: '%s' --> '%s'", item.filename, target_dir);
765 dst_dir = g_file_get_child (root, target_dir);
766 g_assert_nonnull (dst_dir);
767 src_file = g_file_get_child (root, item.filename);
768 g_assert_nonnull (src_file);
769 dst_file = g_file_get_child (dst_dir, item.filename);
770 g_assert_nonnull (dst_file);
773 if ((item.extra_flags & TEST_COPY) == TEST_COPY)
775 g_file_copy (src_file, dst_file,
776 G_FILE_COPY_NOFOLLOW_SYMLINKS |
778 TEST_OVERWRITE) ? G_FILE_COPY_OVERWRITE :
779 G_FILE_COPY_NONE), NULL, NULL, NULL, &error);
782 g_file_move (src_file, dst_file, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL,
786 g_test_message (" res = %d, error code %d = %s", res, error->code,
789 /* copying file/directory to itself (".") */
790 if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) &&
791 (extra_flags == TEST_ALREADY_EXISTS))
793 g_assert_false (res);
794 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
796 /* target file is a file, overwrite is not set */
797 else if (((item.extra_flags & TEST_NOT_EXISTS) != TEST_NOT_EXISTS) &&
798 (extra_flags == TEST_TARGET_IS_FILE))
800 g_assert_false (res);
801 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY);
803 /* source file is directory */
804 else if ((item.extra_flags & TEST_COPY_ERROR_RECURSE) ==
805 TEST_COPY_ERROR_RECURSE)
807 g_assert_false (res);
808 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE);
810 /* source or target path doesn't exist */
811 else if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
812 (extra_flags == TEST_NOT_EXISTS))
814 g_assert_false (res);
815 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
817 /* source or target path permission denied */
818 else if (((item.extra_flags & TEST_NO_ACCESS) == TEST_NO_ACCESS) ||
819 (extra_flags == TEST_NO_ACCESS))
821 /* This works for root, see bug #552912 */
823 if (have_cap_dac_override)
825 g_test_message ("Unable to exercise g_file_copy() or g_file_move() "
826 "failing with EACCES: we probably have "
829 g_assert_no_error (error);
834 g_assert_false (res);
835 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
838 /* no error should be found, all exceptions defined above */
842 g_assert_no_error (error);
846 g_error_free (error);
849 g_object_unref (dst_dir);
850 g_object_unref (src_file);
851 g_object_unref (dst_file);
855 test_copy_move (gconstpointer test_data)
860 struct StructureItem item;
862 g_assert_nonnull (test_data);
863 root = g_file_new_for_commandline_arg ((char *) test_data);
864 g_assert_nonnull (root);
865 res = g_file_query_exists (root, NULL);
869 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
871 item = sample_struct[i];
873 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
876 if (((item.extra_flags & TEST_COPY) == TEST_COPY) ||
877 ((item.extra_flags & TEST_MOVE) == TEST_MOVE))
879 /* test copy/move to a directory, expecting no errors if source files exist */
880 do_copy_move (root, item, TEST_DIR_TARGET, 0);
882 /* some files have been already moved so we can't count with them in the tests */
883 if ((item.extra_flags & TEST_COPY) == TEST_COPY)
885 /* test overwrite for flagged files */
886 if ((item.extra_flags & TEST_OVERWRITE) == TEST_OVERWRITE)
888 do_copy_move (root, item, TEST_DIR_TARGET, TEST_OVERWRITE);
890 /* source = target, should return G_IO_ERROR_EXISTS */
891 do_copy_move (root, item, ".", TEST_ALREADY_EXISTS);
893 do_copy_move (root, item, TEST_TARGET_FILE,
894 TEST_TARGET_IS_FILE);
895 /* target path is invalid */
896 do_copy_move (root, item, TEST_NAME_NOT_EXISTS,
899 /* tests on POSIX-compatible filesystems */
902 /* target directory is not accessible (no execute flag) */
903 do_copy_move (root, item, TEST_DIR_NO_ACCESS,
905 /* target directory is readonly */
906 do_copy_move (root, item, TEST_DIR_NO_WRITE,
912 g_object_unref (root);
915 /* Test that G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT is TRUE for / and for another
916 * known mountpoint. The FALSE case is tested for many directories and files by
917 * test_initial_structure(), via test_attributes().
920 test_unix_is_mountpoint (gconstpointer data)
922 const gchar *path = data;
923 GFile *file = g_file_new_for_path (path);
925 gboolean is_mountpoint;
926 GError *error = NULL;
928 info = g_file_query_info (file, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT,
929 G_FILE_QUERY_INFO_NONE, NULL, &error);
930 g_assert_no_error (error);
931 g_assert_nonnull (info);
934 g_file_info_get_attribute_boolean (info,
935 G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT);
936 g_assert_true (is_mountpoint);
938 g_clear_object (&info);
939 g_clear_object (&file);
943 test_create (gconstpointer test_data)
949 struct StructureItem item;
950 GFileOutputStream *os;
952 g_assert_nonnull (test_data);
954 root = g_file_new_for_commandline_arg ((char *) test_data);
955 g_assert_nonnull (root);
956 res = g_file_query_exists (root, NULL);
959 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
961 item = sample_struct[i];
963 if (((item.extra_flags & TEST_CREATE) == TEST_CREATE) ||
964 ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE) ||
965 ((item.extra_flags & TEST_APPEND) == TEST_APPEND))
967 g_test_message (" test_create: '%s'", item.filename);
969 child = g_file_get_child (root, item.filename);
970 g_assert_nonnull (child);
974 if ((item.extra_flags & TEST_CREATE) == TEST_CREATE)
975 os = g_file_create (child, item.create_flags, NULL, &error);
976 else if ((item.extra_flags & TEST_REPLACE) == TEST_REPLACE)
978 g_file_replace (child, NULL, TRUE, item.create_flags, NULL,
980 else if ((item.extra_flags & TEST_APPEND) == TEST_APPEND)
981 os = g_file_append_to (child, item.create_flags, NULL, &error);
985 g_test_message (" error code %d = %s", error->code, error->message);
987 if (((item.extra_flags & TEST_NOT_EXISTS) == 0) &&
988 ((item.extra_flags & TEST_CREATE) == TEST_CREATE))
991 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
993 else if (item.file_type == G_FILE_TYPE_DIRECTORY)
996 if ((item.extra_flags & TEST_CREATE) == TEST_CREATE)
997 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS);
999 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY);
1003 g_assert_nonnull (os);
1004 g_assert_no_error (error);
1008 g_error_free (error);
1014 g_output_stream_close (G_OUTPUT_STREAM (os), NULL, &error);
1016 g_test_message (" g_output_stream_close: error %d = %s",
1017 error->code, error->message);
1018 g_assert_true (res);
1019 g_assert_no_error (error);
1020 g_object_unref (os);
1022 g_object_unref (child);
1025 g_object_unref (root);
1029 test_open (gconstpointer test_data)
1031 GFile *root, *child;
1035 struct StructureItem item;
1036 GFileInputStream *input_stream;
1038 g_assert_nonnull (test_data);
1040 root = g_file_new_for_commandline_arg ((char *) test_data);
1041 g_assert_nonnull (root);
1042 res = g_file_query_exists (root, NULL);
1043 g_assert_true (res);
1045 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
1047 item = sample_struct[i];
1049 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
1052 if ((item.extra_flags & TEST_OPEN) == TEST_OPEN)
1054 g_test_message (" test_open: '%s'", item.filename);
1056 child = g_file_get_child (root, item.filename);
1057 g_assert_nonnull (child);
1059 input_stream = g_file_read (child, NULL, &error);
1061 if (((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS) ||
1062 ((item.extra_flags & TEST_INVALID_SYMLINK) ==
1063 TEST_INVALID_SYMLINK))
1065 g_assert_null (input_stream);
1066 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
1068 else if (item.file_type == G_FILE_TYPE_DIRECTORY)
1070 g_assert_null (input_stream);
1071 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY);
1075 g_assert_nonnull (input_stream);
1076 g_assert_no_error (error);
1080 g_error_free (error);
1086 g_input_stream_close (G_INPUT_STREAM (input_stream), NULL,
1088 g_assert_true (res);
1089 g_assert_no_error (error);
1090 g_object_unref (input_stream);
1092 g_object_unref (child);
1095 g_object_unref (root);
1099 test_delete (gconstpointer test_data)
1106 struct StructureItem item;
1109 g_assert_nonnull (test_data);
1111 root = g_file_new_for_commandline_arg ((char *) test_data);
1112 g_assert_nonnull (root);
1113 res = g_file_query_exists (root, NULL);
1114 g_assert_true (res);
1116 for (i = 0; i < G_N_ELEMENTS (sample_struct); i++)
1118 item = sample_struct[i];
1120 if ((!posix_compat) && (item.file_type == G_FILE_TYPE_SYMBOLIC_LINK))
1123 if (((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL) ||
1124 ((item.extra_flags & TEST_DELETE_TRASH) == TEST_DELETE_TRASH))
1126 child = file_exists (root, item.filename, &res);
1127 g_assert_nonnull (child);
1128 /* we don't care about result here */
1130 path = g_file_get_path (child);
1131 g_test_message (" Deleting %s, path = %s", item.filename, path);
1135 if ((item.extra_flags & TEST_DELETE_NORMAL) == TEST_DELETE_NORMAL)
1136 res = g_file_delete (child, NULL, &error);
1138 res = g_file_trash (child, NULL, &error);
1140 if ((item.extra_flags & TEST_DELETE_NON_EMPTY) ==
1141 TEST_DELETE_NON_EMPTY)
1143 g_assert_false (res);
1144 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY);
1146 if ((item.extra_flags & TEST_DELETE_FAILURE) == TEST_DELETE_FAILURE)
1148 g_assert_false (res);
1149 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
1151 if ((item.extra_flags & TEST_NOT_EXISTS) == TEST_NOT_EXISTS)
1153 g_assert_false (res);
1154 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
1159 g_test_message (" result = %d, error = %s", res, error->message);
1160 g_error_free (error);
1163 g_object_unref (child);
1166 g_object_unref (root);
1170 test_make_directory_with_parents (gconstpointer test_data)
1172 GFile *root, *child, *grandchild, *greatgrandchild;
1174 GError *error = NULL;
1176 gboolean have_cap_dac_override = check_cap_dac_override (test_data);
1179 g_assert_nonnull (test_data);
1181 root = g_file_new_for_commandline_arg ((char *) test_data);
1182 g_assert_nonnull (root);
1183 res = g_file_query_exists (root, NULL);
1184 g_assert_true (res);
1186 child = g_file_get_child (root, "a");
1187 grandchild = g_file_get_child (child, "b");
1188 greatgrandchild = g_file_get_child (grandchild, "c");
1190 /* Check that we can successfully make directory hierarchies of
1193 res = g_file_make_directory_with_parents (child, NULL, &error);
1194 g_assert_true (res);
1195 g_assert_no_error (error);
1196 res = g_file_query_exists (child, NULL);
1197 g_assert_true (res);
1199 g_file_delete (child, NULL, NULL);
1201 res = g_file_make_directory_with_parents (grandchild, NULL, &error);
1202 g_assert_true (res);
1203 g_assert_no_error (error);
1204 res = g_file_query_exists (grandchild, NULL);
1205 g_assert_true (res);
1207 g_file_delete (grandchild, NULL, NULL);
1208 g_file_delete (child, NULL, NULL);
1210 res = g_file_make_directory_with_parents (greatgrandchild, NULL, &error);
1211 g_assert_true (res);
1212 g_assert_no_error (error);
1213 res = g_file_query_exists (greatgrandchild, NULL);
1214 g_assert_true (res);
1216 g_file_delete (greatgrandchild, NULL, NULL);
1217 g_file_delete (grandchild, NULL, NULL);
1218 g_file_delete (child, NULL, NULL);
1220 /* Now test failure by trying to create a directory hierarchy
1221 * where a ancestor exists but is read-only
1224 /* No obvious way to do this on Windows */
1229 /* Permissions are ignored if we have CAP_DAC_OVERRIDE or equivalent,
1230 * and in particular if we're root */
1231 if (have_cap_dac_override)
1233 g_test_skip ("Unable to exercise g_file_make_directory_with_parents "
1234 "failing with EACCES: we probably have "
1235 "CAP_DAC_OVERRIDE");
1240 g_file_make_directory (child, NULL, NULL);
1241 g_assert_true (res);
1243 res = g_file_set_attribute_uint32 (child,
1244 G_FILE_ATTRIBUTE_UNIX_MODE,
1245 S_IRUSR + S_IXUSR, /* -r-x------ */
1246 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1248 g_assert_true (res);
1250 res = g_file_make_directory_with_parents (grandchild, NULL, &error);
1251 g_assert_false (res);
1252 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
1253 g_clear_error (&error);
1255 res = g_file_make_directory_with_parents (greatgrandchild, NULL, &error);
1256 g_assert_false (res);
1257 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED);
1258 g_clear_error (&error);
1261 g_object_unref (greatgrandchild);
1262 g_object_unref (grandchild);
1263 g_object_unref (child);
1264 g_object_unref (root);
1269 cleanup_dir_recurse (GFile *parent, GFile *root)
1273 GFileEnumerator *enumerator;
1276 char *relative_path;
1278 g_assert_nonnull (root);
1281 g_file_enumerate_children (parent, "*",
1282 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
1288 info = g_file_enumerator_next_file (enumerator, NULL, &error);
1289 while ((info) && (!error))
1291 descend = g_file_enumerator_get_child (enumerator, info);
1292 g_assert_nonnull (descend);
1293 relative_path = g_file_get_relative_path (root, descend);
1294 g_assert_nonnull (relative_path);
1295 g_free (relative_path);
1297 g_test_message (" deleting '%s'", g_file_info_get_display_name (info));
1299 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
1300 cleanup_dir_recurse (descend, root);
1303 res = g_file_delete (descend, NULL, &error);
1304 g_assert_true (res);
1306 g_object_unref (descend);
1308 g_object_unref (info);
1310 info = g_file_enumerator_next_file (enumerator, NULL, &error);
1312 g_assert_no_error (error);
1315 res = g_file_enumerator_close (enumerator, NULL, &error);
1316 g_assert_true (res);
1317 g_assert_no_error (error);
1319 g_object_unref (enumerator);
1323 prep_clean_structure (gconstpointer test_data)
1327 g_assert_nonnull (test_data);
1328 g_test_message (" Cleaning target testing structure in '%s'...",
1329 (char *) test_data);
1331 root = g_file_new_for_commandline_arg ((char *) test_data);
1332 g_assert_nonnull (root);
1334 cleanup_dir_recurse (root, root);
1336 g_file_delete (root, NULL, NULL);
1338 g_object_unref (root);
1342 main (int argc, char *argv[])
1344 static gboolean only_create_struct;
1345 const char *target_path;
1347 GOptionContext *context;
1349 static GOptionEntry cmd_entries[] = {
1350 {"read-write", 'w', 0, G_OPTION_ARG_NONE, &write_test,
1351 "Perform write tests (incl. structure creation)", NULL},
1352 {"create-struct", 'c', 0, G_OPTION_ARG_NONE, &only_create_struct,
1353 "Only create testing structure (no tests)", NULL},
1354 {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL},
1355 {"posix", 'x', 0, G_OPTION_ARG_NONE, &posix_compat,
1356 "Test POSIX-specific features (unix permissions, symlinks)", NULL},
1363 only_create_struct = FALSE;
1365 posix_compat = FALSE;
1367 /* strip all gtester-specific args */
1368 g_test_init (&argc, &argv, NULL);
1370 /* no extra parameters specified, assume we're executed from glib test suite */
1376 only_create_struct = FALSE;
1377 target_path = DEFAULT_TEST_DIR;
1378 #ifdef G_PLATFORM_WIN32
1379 posix_compat = FALSE;
1381 posix_compat = TRUE;
1385 /* add trailing args */
1387 context = g_option_context_new ("target_path");
1388 g_option_context_add_main_entries (context, cmd_entries, NULL);
1389 if (!g_option_context_parse (context, &argc, &argv, &error))
1391 g_printerr ("option parsing failed: %s\n", error->message);
1392 return g_test_run ();
1395 /* remaining arg should is the target path; we don't care of the extra args here */
1397 target_path = strdup (argv[1]);
1401 g_printerr ("error: target path was not specified\n");
1402 g_printerr ("%s", g_option_context_get_help (context, TRUE, NULL));
1403 return g_test_run ();
1406 g_option_context_free (context);
1408 /* Write test - clean target directory first */
1409 /* this can be also considered as a test - enumerate + delete */
1410 if (write_test || only_create_struct)
1411 g_test_add_data_func ("/live-g-file/prep_clean_structure", target_path,
1412 prep_clean_structure);
1414 /* Write test - create new testing structure */
1415 if (write_test || only_create_struct)
1416 g_test_add_data_func ("/live-g-file/create_structure", target_path,
1417 test_create_structure);
1419 /* Read test - test the sample structure - expect defined attributes to be there */
1420 if (!only_create_struct)
1421 g_test_add_data_func ("/live-g-file/test_initial_structure", target_path,
1422 test_initial_structure);
1424 /* Read test - test traverse the structure - no special file should appear */
1425 if (!only_create_struct)
1426 g_test_add_data_func ("/live-g-file/test_traverse_structure", target_path,
1427 test_traverse_structure);
1429 /* Read test - enumerate */
1430 if (!only_create_struct)
1431 g_test_add_data_func ("/live-g-file/test_enumerate", target_path,
1434 /* Read test - open (g_file_read()) */
1435 if (!only_create_struct)
1436 g_test_add_data_func ("/live-g-file/test_open", target_path, test_open);
1440 g_test_add_data_func ("/live-g-file/test_unix_is_mountpoint/sysroot",
1442 test_unix_is_mountpoint);
1444 g_test_add_data_func ("/live-g-file/test_unix_is_mountpoint/proc",
1446 test_unix_is_mountpoint);
1450 /* Write test - create */
1451 if (write_test && (!only_create_struct))
1452 g_test_add_data_func ("/live-g-file/test_create", target_path,
1455 /* Write test - copy, move */
1456 if (write_test && (!only_create_struct))
1457 g_test_add_data_func ("/live-g-file/test_copy_move", target_path,
1460 /* Write test - delete, trash */
1461 if (write_test && (!only_create_struct))
1462 g_test_add_data_func ("/live-g-file/test_delete", target_path,
1465 /* Write test - make_directory_with_parents */
1466 if (write_test && (!only_create_struct))
1467 g_test_add_data_func ("/live-g-file/test_make_directory_with_parents", target_path,
1468 test_make_directory_with_parents);
1470 if (write_test || only_create_struct)
1471 g_test_add_data_func ("/live-g-file/final_clean", target_path,
1472 prep_clean_structure);
1474 return g_test_run ();