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