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