tests: use new g_test_build_filename() API
[platform/upstream/glib.git] / gio / tests / file.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <gio/gio.h>
5 #include <gio/gfiledescriptorbased.h>
6 #ifdef G_OS_UNIX
7 #include <sys/stat.h>
8 #endif
9
10 static void
11 test_basic (void)
12 {
13   GFile *file;
14   gchar *s;
15
16   file = g_file_new_for_path ("./some/directory/testfile");
17
18   s = g_file_get_basename (file);
19   g_assert_cmpstr (s, ==, "testfile");
20   g_free (s);
21
22   s = g_file_get_uri (file);
23   g_assert (g_str_has_prefix (s, "file://"));
24   g_assert (g_str_has_suffix (s, "/some/directory/testfile"));
25   g_free (s);
26
27   g_assert (g_file_has_uri_scheme (file, "file"));
28   s = g_file_get_uri_scheme (file);
29   g_assert_cmpstr (s, ==, "file");
30   g_free (s);
31
32   g_object_unref (file);
33 }
34
35 static void
36 test_parent (void)
37 {
38   GFile *file;
39   GFile *file2;
40   GFile *parent;
41   GFile *root;
42
43   file = g_file_new_for_path ("./some/directory/testfile");
44   file2 = g_file_new_for_path ("./some/directory");
45   root = g_file_new_for_path ("/");
46
47   g_assert (g_file_has_parent (file, file2));
48
49   parent = g_file_get_parent (file);
50   g_assert (g_file_equal (parent, file2));
51   g_object_unref (parent);
52
53   g_assert (g_file_get_parent (root) == NULL);
54
55   g_object_unref (file);
56   g_object_unref (file2);
57   g_object_unref (root);
58 }
59
60 static void
61 test_child (void)
62 {
63   GFile *file;
64   GFile *child;
65   GFile *child2;
66
67   file = g_file_new_for_path ("./some/directory");
68   child = g_file_get_child (file, "child");
69   g_assert (g_file_has_parent (child, file));
70
71   child2 = g_file_get_child_for_display_name (file, "child2", NULL);
72   g_assert (g_file_has_parent (child2, file));
73
74   g_object_unref (child);
75   g_object_unref (child2);
76   g_object_unref (file);
77 }
78
79 static void
80 test_type (void)
81 {
82   GFile *datapath_f;
83   GFile *file;
84   GFileType type;
85   GError *error = NULL;
86   gchar *datapath;
87
88   datapath = g_test_build_filename (G_TEST_DISTED, ".", NULL);
89   datapath_f = g_file_new_for_path (datapath);
90   g_free (datapath);
91
92   file = g_file_get_child (datapath_f, "g-icon.c");
93   type = g_file_query_file_type (file, 0, NULL);
94   g_assert_cmpint (type, ==, G_FILE_TYPE_REGULAR);
95   g_object_unref (file);
96
97   file = g_file_get_child (datapath_f, "schema-tests");
98   type = g_file_query_file_type (file, 0, NULL);
99   g_assert_cmpint (type, ==, G_FILE_TYPE_DIRECTORY);
100
101   g_file_read (file, NULL, &error);
102   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY);
103   g_error_free (error);
104   g_object_unref (file);
105
106   g_object_unref (datapath_f);
107 }
108
109
110 typedef struct
111 {
112   GFile *file;
113   GFileMonitor *monitor;
114   GOutputStream *ostream;
115   GInputStream *istream;
116   GMainLoop *loop;
117   gint buffersize;
118   gint monitor_created;
119   gint monitor_deleted;
120   gint monitor_changed;
121   gchar *monitor_path;
122   gint pos;
123   gchar *data;
124   gchar *buffer;
125   guint timeout;
126 } CreateDeleteData;
127
128 static void
129 monitor_changed (GFileMonitor      *monitor,
130                  GFile             *file,
131                  GFile             *other_file,
132                  GFileMonitorEvent  event_type,
133                  gpointer           user_data)
134 {
135   CreateDeleteData *data = user_data;
136   gchar *path;
137
138   path = g_file_get_path (file);
139   g_assert_cmpstr (data->monitor_path, ==, path);
140   g_free (path);
141
142   if (event_type == G_FILE_MONITOR_EVENT_CREATED)
143     data->monitor_created++;
144   if (event_type == G_FILE_MONITOR_EVENT_DELETED)
145     data->monitor_deleted++;
146   if (event_type == G_FILE_MONITOR_EVENT_CHANGED)
147     data->monitor_changed++;
148 }
149
150
151 static gboolean
152 quit_idle (gpointer user_data)
153 {
154   CreateDeleteData *data = user_data;
155
156   g_source_remove (data->timeout); 
157   g_main_loop_quit (data->loop);
158
159   return FALSE;
160 }
161
162 static void
163 iclosed_cb (GObject      *source,
164             GAsyncResult *res,
165             gpointer      user_data)
166 {
167   CreateDeleteData *data = user_data;
168   GError *error;
169   gboolean ret;
170
171   error = NULL;
172   ret = g_input_stream_close_finish (data->istream, res, &error);
173   g_assert_no_error (error);
174   g_assert (ret);
175
176   g_assert (g_input_stream_is_closed (data->istream));
177
178   ret = g_file_delete (data->file, NULL, &error);
179   g_assert (ret);
180   g_assert_no_error (error);
181
182   /* work around file monitor bug:
183    * inotify events are only processed every 1000 ms, regardless
184    * of the rate limit set on the file monitor
185    */
186   g_timeout_add (2000, quit_idle, data);
187 }
188
189 static void
190 read_cb (GObject      *source,
191          GAsyncResult *res,
192          gpointer      user_data)
193 {
194   CreateDeleteData *data = user_data;
195   GError *error;
196   gssize size;
197
198   error = NULL;
199   size = g_input_stream_read_finish (data->istream, res, &error);
200   g_assert_no_error (error);
201
202   data->pos += size;
203   if (data->pos < strlen (data->data))
204     {
205       g_input_stream_read_async (data->istream,
206                                  data->buffer + data->pos,
207                                  strlen (data->data) - data->pos,
208                                  0,
209                                  NULL,
210                                  read_cb,
211                                  data);
212     }
213   else
214     {
215       g_assert_cmpstr (data->buffer, ==, data->data);
216       g_assert (!g_input_stream_is_closed (data->istream));
217       g_input_stream_close_async (data->istream, 0, NULL, iclosed_cb, data);
218     }
219 }
220
221 static void
222 ipending_cb (GObject      *source,
223              GAsyncResult *res,
224              gpointer      user_data)
225 {
226   CreateDeleteData *data = user_data;
227   GError *error;
228
229   error = NULL;
230   g_input_stream_read_finish (data->istream, res, &error);
231   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING);
232   g_error_free (error);
233 }
234
235 static void
236 skipped_cb (GObject      *source,
237             GAsyncResult *res,
238             gpointer      user_data)
239 {
240   CreateDeleteData *data = user_data;
241   GError *error;
242   gssize size;
243
244   error = NULL;
245   size = g_input_stream_skip_finish (data->istream, res, &error);
246   g_assert_no_error (error);
247   g_assert_cmpint (size, ==, data->pos);
248
249   g_input_stream_read_async (data->istream,
250                              data->buffer + data->pos,
251                              strlen (data->data) - data->pos,
252                              0,
253                              NULL,
254                              read_cb,
255                              data);
256   /* check that we get a pending error */
257   g_input_stream_read_async (data->istream,
258                              data->buffer + data->pos,
259                              strlen (data->data) - data->pos,
260                              0,
261                              NULL,
262                              ipending_cb,
263                              data);
264 }
265
266 static void
267 opened_cb (GObject      *source,
268            GAsyncResult *res,
269            gpointer      user_data)
270 {
271   GFileInputStream *base;
272   CreateDeleteData *data = user_data;
273   GError *error;
274
275   error = NULL;
276   base = g_file_read_finish (data->file, res, &error);
277   g_assert_no_error (error);
278
279   if (data->buffersize == 0)
280     data->istream = G_INPUT_STREAM (g_object_ref (base));
281   else
282     data->istream = g_buffered_input_stream_new_sized (G_INPUT_STREAM (base), data->buffersize);
283   g_object_unref (base);
284
285   data->buffer = g_new0 (gchar, strlen (data->data) + 1);
286
287   /* copy initial segment directly, then skip */
288   memcpy (data->buffer, data->data, 10);
289   data->pos = 10;
290
291   g_input_stream_skip_async (data->istream,
292                              10,
293                              0,
294                              NULL,
295                              skipped_cb,
296                              data);
297 }
298
299 static void
300 oclosed_cb (GObject      *source,
301             GAsyncResult *res,
302             gpointer      user_data)
303 {
304   CreateDeleteData *data = user_data;
305   GError *error;
306   gboolean ret;
307
308   error = NULL;
309   ret = g_output_stream_close_finish (data->ostream, res, &error);
310   g_assert_no_error (error);
311   g_assert (ret);
312   g_assert (g_output_stream_is_closed (data->ostream));
313
314   g_file_read_async (data->file, 0, NULL, opened_cb, data);
315 }
316
317 static void
318 written_cb (GObject      *source,
319             GAsyncResult *res,
320             gpointer      user_data)
321 {
322   CreateDeleteData *data = user_data;
323   gssize size;
324   GError *error;
325
326   error = NULL;
327   size = g_output_stream_write_finish (data->ostream, res, &error);
328   g_assert_no_error (error);
329
330   data->pos += size;
331   if (data->pos < strlen (data->data))
332     {
333       g_output_stream_write_async (data->ostream,
334                                    data->data + data->pos,
335                                    strlen (data->data) - data->pos,
336                                    0,
337                                    NULL,
338                                    written_cb,
339                                    data);
340     }
341   else
342     {
343       g_assert (!g_output_stream_is_closed (data->ostream));
344       g_output_stream_close_async (data->ostream, 0, NULL, oclosed_cb, data);
345     }
346 }
347
348 static void
349 opending_cb (GObject      *source,
350              GAsyncResult *res,
351              gpointer      user_data)
352 {
353   CreateDeleteData *data = user_data;
354   GError *error;
355
356   error = NULL;
357   g_output_stream_write_finish (data->ostream, res, &error);
358   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING);
359   g_error_free (error);
360 }
361
362 static void
363 created_cb (GObject      *source,
364             GAsyncResult *res,
365             gpointer      user_data)
366 {
367   GFileOutputStream *base;
368   CreateDeleteData *data = user_data;
369   GError *error;
370
371   error = NULL;
372   base = g_file_create_finish (G_FILE (source), res, &error);
373   g_assert_no_error (error);
374   g_assert (g_file_query_exists  (data->file, NULL));
375
376   if (data->buffersize == 0)
377     data->ostream = G_OUTPUT_STREAM (g_object_ref (base));
378   else
379     data->ostream = g_buffered_output_stream_new_sized (G_OUTPUT_STREAM (base), data->buffersize);
380   g_object_unref (base);
381
382   g_output_stream_write_async (data->ostream,
383                                data->data,
384                                strlen (data->data),
385                                0,
386                                NULL,
387                                written_cb,
388                                data);
389   /* check that we get a pending error */
390   g_output_stream_write_async (data->ostream,
391                                data->data,
392                                strlen (data->data),
393                                0,
394                                NULL,
395                                opending_cb,
396                                data);
397 }
398
399 static gboolean
400 stop_timeout (gpointer data)
401 {
402   g_assert_not_reached ();
403
404   return FALSE;
405 }
406
407 /*
408  * This test does a fully async create-write-read-delete.
409  * Callbackistan.
410  */
411 static void
412 test_create_delete (gconstpointer d)
413 {
414   GError *error;
415   CreateDeleteData *data;
416   GFileIOStream *iostream;
417
418   data = g_new0 (CreateDeleteData, 1);
419
420   data->buffersize = GPOINTER_TO_INT (d);
421   data->data = "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789";
422   data->pos = 0;
423
424   data->file = g_file_new_tmp ("g_file_create_delete_XXXXXX",
425                                &iostream, NULL);
426   g_assert (data->file != NULL);
427   g_object_unref (iostream);
428
429   data->monitor_path = g_file_get_path (data->file);
430   remove (data->monitor_path);
431
432   g_assert (!g_file_query_exists  (data->file, NULL));
433
434   error = NULL;
435   data->monitor = g_file_monitor_file (data->file, 0, NULL, &error);
436   g_assert_no_error (error);
437
438   /* This test doesn't work with GPollFileMonitor, because it assumes
439    * that the monitor will notice a create immediately followed by a
440    * delete, rather than coalescing them into nothing.
441    */
442   if (!strcmp (G_OBJECT_TYPE_NAME (data->monitor), "GPollFileMonitor"))
443     {
444       g_print ("skipping test for this GFileMonitor implementation");
445       goto skip;
446     }
447
448   g_file_monitor_set_rate_limit (data->monitor, 100);
449
450   g_signal_connect (data->monitor, "changed", G_CALLBACK (monitor_changed), data);
451
452   data->loop = g_main_loop_new (NULL, FALSE);
453
454   data->timeout = g_timeout_add (5000, stop_timeout, NULL);
455
456   g_file_create_async (data->file, 0, 0, NULL, created_cb, data);
457
458   g_main_loop_run (data->loop);
459
460   g_assert_cmpint (data->monitor_created, ==, 1);
461   g_assert_cmpint (data->monitor_deleted, ==, 1);
462   g_assert_cmpint (data->monitor_changed, >, 0);
463
464   g_assert (!g_file_monitor_is_cancelled (data->monitor));
465   g_file_monitor_cancel (data->monitor);
466   g_assert (g_file_monitor_is_cancelled (data->monitor));
467
468   g_main_loop_unref (data->loop);
469   g_object_unref (data->ostream);
470   g_object_unref (data->istream);
471
472  skip:
473   g_object_unref (data->monitor);
474   g_object_unref (data->file);
475   free (data->monitor_path);
476   g_free (data->buffer);
477   g_free (data);
478 }
479
480 static const gchar *replace_data =
481     "/**\n"
482     " * g_file_replace_contents_async:\n"
483     " * @file: input #GFile.\n"
484     " * @contents: string of contents to replace the file with.\n"
485     " * @length: the length of @contents in bytes.\n"
486     " * @etag: (allow-none): a new <link linkend=\"gfile-etag\">entity tag</link> for the @file, or %NULL\n"
487     " * @make_backup: %TRUE if a backup should be created.\n"
488     " * @flags: a set of #GFileCreateFlags.\n"
489     " * @cancellable: optional #GCancellable object, %NULL to ignore.\n"
490     " * @callback: a #GAsyncReadyCallback to call when the request is satisfied\n"
491     " * @user_data: the data to pass to callback function\n"
492     " * \n"
493     " * Starts an asynchronous replacement of @file with the given \n"
494     " * @contents of @length bytes. @etag will replace the document's\n"
495     " * current entity tag.\n"
496     " * \n"
497     " * When this operation has completed, @callback will be called with\n"
498     " * @user_user data, and the operation can be finalized with \n"
499     " * g_file_replace_contents_finish().\n"
500     " * \n"
501     " * If @cancellable is not %NULL, then the operation can be cancelled by\n"
502     " * triggering the cancellable object from another thread. If the operation\n"
503     " * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. \n"
504     " * \n"
505     " * If @make_backup is %TRUE, this function will attempt to \n"
506     " * make a backup of @file.\n"
507     " **/\n";
508
509 typedef struct
510 {
511   GFile *file;
512   const gchar *data;
513   GMainLoop *loop;
514   gboolean again;
515 } ReplaceLoadData;
516
517 static void replaced_cb (GObject      *source,
518                          GAsyncResult *res,
519                          gpointer      user_data);
520
521 static void
522 loaded_cb (GObject      *source,
523            GAsyncResult *res,
524            gpointer      user_data)
525 {
526   ReplaceLoadData *data = user_data;
527   gboolean ret;
528   GError *error;
529   gchar *contents;
530   gsize length;
531
532   error = NULL;
533   ret = g_file_load_contents_finish (data->file, res, &contents, &length, NULL, &error);
534   g_assert (ret);
535   g_assert_no_error (error);
536   g_assert_cmpint (length, ==, strlen (data->data));
537   g_assert_cmpstr (contents, ==, data->data);
538
539   g_free (contents);
540
541   if (data->again)
542     {
543       data->again = FALSE;
544       data->data = "pi pa po";
545
546       g_file_replace_contents_async (data->file,
547                                      data->data,
548                                      strlen (data->data),
549                                      NULL,
550                                      FALSE,
551                                      0,
552                                      NULL,
553                                      replaced_cb,
554                                      data);
555     }
556   else
557     {
558        error = NULL;
559        ret = g_file_delete (data->file, NULL, &error);
560        g_assert_no_error (error);
561        g_assert (ret);
562        g_assert (!g_file_query_exists (data->file, NULL));
563
564        g_main_loop_quit (data->loop);
565     }
566 }
567
568 static void
569 replaced_cb (GObject      *source,
570              GAsyncResult *res,
571              gpointer      user_data)
572 {
573   ReplaceLoadData *data = user_data;
574   GError *error;
575
576   error = NULL;
577   g_file_replace_contents_finish (data->file, res, NULL, &error);
578   g_assert_no_error (error);
579
580   g_file_load_contents_async (data->file, NULL, loaded_cb, data);
581 }
582
583 static void
584 test_replace_load (void)
585 {
586   ReplaceLoadData *data;
587   gchar *path;
588   GFileIOStream *iostream;
589
590   data = g_new0 (ReplaceLoadData, 1);
591   data->again = TRUE;
592   data->data = replace_data;
593
594   data->file = g_file_new_tmp ("g_file_replace_load_XXXXXX",
595                                &iostream, NULL);
596   g_assert (data->file != NULL);
597   g_object_unref (iostream);
598
599   path = g_file_get_path (data->file);
600   remove (path);
601
602   g_assert (!g_file_query_exists (data->file, NULL));
603
604   data->loop = g_main_loop_new (NULL, FALSE);
605
606   g_file_replace_contents_async (data->file,
607                                  data->data,
608                                  strlen (data->data),
609                                  NULL,
610                                  FALSE,
611                                  0,
612                                  NULL,
613                                  replaced_cb,
614                                  data);
615
616   g_main_loop_run (data->loop);
617
618   g_main_loop_unref (data->loop);
619   g_object_unref (data->file);
620   g_free (data);
621   free (path);
622 }
623
624 static void
625 test_replace_cancel (void)
626 {
627   GFile *tmpdir, *file;
628   GFileOutputStream *ostream;
629   GFileEnumerator *fenum;
630   GFileInfo *info;
631   GCancellable *cancellable;
632   gchar *path;
633   gsize nwrote;
634   GError *error = NULL;
635
636   g_test_bug ("629301");
637
638   path = g_dir_make_tmp ("g_file_replace_cancel_XXXXXX", &error);
639   g_assert_no_error (error);
640   tmpdir = g_file_new_for_path (path);
641   g_free (path);
642
643   file = g_file_get_child (tmpdir, "file");
644   g_file_replace_contents (file,
645                            replace_data,
646                            strlen (replace_data),
647                            NULL, FALSE, 0, NULL,
648                            NULL, &error);
649   g_assert_no_error (error);
650
651   ostream = g_file_replace (file, NULL, TRUE, 0, NULL, &error);
652   g_assert_no_error (error);
653
654   g_output_stream_write_all (G_OUTPUT_STREAM (ostream),
655                              replace_data, strlen (replace_data),
656                              &nwrote, NULL, &error);
657   g_assert_no_error (error);
658   g_assert_cmpint (nwrote, ==, strlen (replace_data));
659
660   /* At this point there should be two files; the original and the
661    * temporary.
662    */
663   fenum = g_file_enumerate_children (tmpdir, NULL, 0, NULL, &error);
664   g_assert_no_error (error);
665
666   info = g_file_enumerator_next_file (fenum, NULL, &error);
667   g_assert_no_error (error);
668   g_assert (info != NULL);
669   g_object_unref (info);
670   info = g_file_enumerator_next_file (fenum, NULL, &error);
671   g_assert_no_error (error);
672   g_assert (info != NULL);
673   g_object_unref (info);
674
675   g_file_enumerator_close (fenum, NULL, &error);
676   g_assert_no_error (error);
677   g_object_unref (fenum);
678
679   /* Make sure the temporary gets deleted even if we cancel. */
680   cancellable = g_cancellable_new ();
681   g_cancellable_cancel (cancellable);
682   g_output_stream_close (G_OUTPUT_STREAM (ostream), cancellable, &error);
683   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
684   g_clear_error (&error);
685
686   g_object_unref (cancellable);
687   g_object_unref (ostream);
688
689   g_file_delete (file, NULL, &error);
690   g_assert_no_error (error);
691   g_object_unref (file);
692
693   /* This will only succeed if the temp file was deleted. */
694   g_file_delete (tmpdir, NULL, &error);
695   g_assert_no_error (error);
696   g_object_unref (tmpdir);
697 }
698
699 static void
700 on_file_deleted (GObject      *object,
701                  GAsyncResult *result,
702                  gpointer      user_data)
703 {
704   GError *local_error = NULL;
705   GMainLoop *loop = user_data;
706
707   (void) g_file_delete_finish ((GFile*)object, result, &local_error);
708   g_assert_no_error (local_error);
709
710   g_main_loop_quit (loop);
711 }
712
713 static void
714 test_async_delete (void)
715 {
716   GFile *file;
717   GFileIOStream *iostream;
718   GError *local_error = NULL;
719   GError **error = &local_error;
720   GMainLoop *loop;
721
722   file = g_file_new_tmp ("g_file_delete_XXXXXX",
723                          &iostream, error);
724   g_assert_no_error (local_error);
725   g_object_unref (iostream);
726
727   g_assert (g_file_query_exists (file, NULL));
728
729   loop = g_main_loop_new (NULL, TRUE);
730
731   g_file_delete_async (file, G_PRIORITY_DEFAULT, NULL, on_file_deleted, loop);
732
733   g_main_loop_run (loop);
734
735   g_assert (!g_file_query_exists (file, NULL));
736
737   g_main_loop_unref (loop);
738   g_object_unref (file);
739 }
740
741 #ifdef G_OS_UNIX
742 static void
743 test_copy_preserve_mode (void)
744 {
745   GFile *tmpfile;
746   GFile *dest_tmpfile;
747   GFileInfo *dest_info;
748   GFileIOStream *iostream;
749   GError *local_error = NULL;
750   GError **error = &local_error;
751   guint32 romode = S_IFREG | 0600;
752   guint32 dest_mode;
753
754   tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX",
755                             &iostream, error);
756   g_assert_no_error (local_error);
757   g_io_stream_close ((GIOStream*)iostream, NULL, error);
758   g_assert_no_error (local_error);
759   g_clear_object (&iostream);
760
761   g_file_set_attribute (tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_ATTRIBUTE_TYPE_UINT32,
762                         &romode, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
763                         NULL, error);
764   g_assert_no_error (local_error);
765
766   dest_tmpfile = g_file_new_tmp ("tmp-copy-preserve-modeXXXXXX",
767                                  &iostream, error);
768   g_assert_no_error (local_error);
769   g_io_stream_close ((GIOStream*)iostream, NULL, error);
770   g_assert_no_error (local_error);
771   g_clear_object (&iostream);
772
773   g_file_copy (tmpfile, dest_tmpfile, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA,
774                NULL, NULL, NULL, error);
775   g_assert_no_error (local_error);
776
777   dest_info = g_file_query_info (dest_tmpfile, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
778                                  NULL, error);
779   g_assert_no_error (local_error);
780
781   dest_mode = g_file_info_get_attribute_uint32 (dest_info, G_FILE_ATTRIBUTE_UNIX_MODE);
782   
783   g_assert_cmpint (dest_mode, ==, romode);
784
785   (void) g_file_delete (tmpfile, NULL, NULL);
786   (void) g_file_delete (dest_tmpfile, NULL, NULL);
787   
788   g_clear_object (&tmpfile);
789   g_clear_object (&dest_tmpfile);
790   g_clear_object (&dest_info);
791 }
792 #endif
793
794 int
795 main (int argc, char *argv[])
796 {
797   g_test_init (&argc, &argv, NULL);
798
799   g_test_bug_base ("http://bugzilla.gnome.org/");
800
801   g_test_add_func ("/file/basic", test_basic);
802   g_test_add_func ("/file/parent", test_parent);
803   g_test_add_func ("/file/child", test_child);
804   g_test_add_func ("/file/type", test_type);
805   g_test_add_data_func ("/file/async-create-delete/0", GINT_TO_POINTER (0), test_create_delete);
806   g_test_add_data_func ("/file/async-create-delete/1", GINT_TO_POINTER (1), test_create_delete);
807   g_test_add_data_func ("/file/async-create-delete/10", GINT_TO_POINTER (10), test_create_delete);
808   g_test_add_data_func ("/file/async-create-delete/25", GINT_TO_POINTER (25), test_create_delete);
809   g_test_add_data_func ("/file/async-create-delete/4096", GINT_TO_POINTER (4096), test_create_delete);
810   g_test_add_func ("/file/replace-load", test_replace_load);
811   g_test_add_func ("/file/replace-cancel", test_replace_cancel);
812   g_test_add_func ("/file/async-delete", test_async_delete);
813 #ifdef G_OS_UNIX
814   g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode);
815 #endif
816
817   return g_test_run ();
818 }