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