]> Pileus Git - ~andy/gtk/blob - tests/autotestfilesystem.c
Revert name change
[~andy/gtk] / tests / autotestfilesystem.c
1 /* GTK - The GIMP Toolkit
2  * autotestfilesystem.c: Automated tests for GtkFileSystem implementations
3  * Copyright (C) 2005, Novell, Inc.
4  *
5  * Authors:
6  *   Federico Mena-Quintero <federico@novell.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #define GTK_FILE_SYSTEM_ENABLE_UNSUPPORTED
25
26 #include "config.h"
27 #include <string.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <glib/gprintf.h>
32 #include <gtk/gtk.h>
33 #include <gtk/gtkfilesystem.h>
34
35 #ifdef G_OS_WIN32
36 #include <direct.h>
37 #define rmdir(d) _rmdir(d)
38 #endif
39
40 #define CALLBACK_TIMEOUT_MS 3000        /* Period after which the callback must have been called */
41 #define CANCEL_TIMEOUT_MS 100           /* We'll sleep for this much time before cancelling */
42
43 #define GET_FOLDER_FILENAME "/etc"
44 #define GET_INFO_FILENAME "/etc/passwd"
45 #define CREATE_FOLDER_FILENAME "/tmp/autotestfilesystem-tmp"
46 #define VOLUME_MOUNT_FILENAME "/"
47
48 /* This is stolen from gtkfilechooserdefault.c:set_file_system_backend() */
49 static GtkFileSystem *
50 get_file_system (void)
51 {
52   GtkFileSystem *file_system = NULL;
53
54 #if 1
55   file_system = gtk_file_system_create ("gnome-vfs");
56 #else
57   GtkSettings *settings = gtk_settings_get_default ();
58   gchar *default_backend = NULL;
59
60   g_object_get (settings, "gtk-file-chooser-backend", &default_backend, NULL);
61   if (default_backend)
62     {
63       file_system = gtk_file_system_create (default_backend);
64       g_free (default_backend);
65     }
66
67   if (!file_system)
68     {
69 #if defined (G_OS_UNIX)
70       file_system = gtk_file_system_unix_new ();
71 #elif defined (G_OS_WIN32)
72       file_system = gtk_file_system_win32_new ();
73 #else
74 #error "No default filesystem implementation on the platform"
75 #endif
76     }
77
78 #endif
79
80   return file_system;
81 }
82
83 \f
84
85 /***** Testing infrastructure *****/
86
87 typedef struct {
88   gboolean callback_was_called;
89   gboolean timeout_was_called;
90 } TestCallbackClosure;
91
92 static void
93 notify_callback_called (TestCallbackClosure *closure)
94 {
95   closure->callback_was_called = TRUE;
96   gtk_main_quit ();
97 }
98
99 static gboolean
100 timeout_cb (gpointer data)
101 {
102   TestCallbackClosure *closure;
103
104   closure = data;
105
106   closure->timeout_was_called = TRUE;
107   gtk_main_quit ();
108
109   return FALSE;
110 }
111
112 static void
113 wait_for_callback (TestCallbackClosure *closure)
114 {
115   gdk_threads_add_timeout (CALLBACK_TIMEOUT_MS, timeout_cb, closure);
116   gtk_main ();
117 }
118
119 typedef struct {
120   const char *test_name;
121   gboolean callback_must_be_called;
122   gpointer (* setup_fn) (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
123                          TestCallbackClosure *callback_closure);
124   void (* cleanup_fn) (gpointer data, gboolean *success, char **failure_reason);
125 } TestSpec;
126
127 static gboolean
128 run_test (TestSpec *test_spec)
129 {
130   GtkFileSystem *file_system;
131   TestCallbackClosure closure;
132   gboolean success_setup, success_cleanup;
133   gpointer test_data;
134   gboolean callback_success;
135   gboolean passed;
136   char *setup_failure_reason;
137   char *cleanup_failure_reason;
138
139   file_system = get_file_system ();
140   if (!file_system)
141     {
142       printf ("FAIL: test \"%s\"\n", test_spec->test_name);
143       printf ("      could not create file system!\n");
144       return FALSE;
145     }
146
147   closure.callback_was_called = FALSE;
148   closure.timeout_was_called = FALSE;
149
150   success_setup = success_cleanup = callback_success = FALSE;
151   setup_failure_reason = cleanup_failure_reason = NULL;
152
153   test_data = test_spec->setup_fn (file_system, &success_setup, &setup_failure_reason, &closure);
154   if (success_setup)
155     {
156       wait_for_callback (&closure);
157
158       test_spec->cleanup_fn (test_data, &success_cleanup, &cleanup_failure_reason);
159
160       callback_success = (test_spec->callback_must_be_called == closure.callback_was_called);
161     }
162
163   g_object_unref (file_system);
164
165   passed = (success_setup && success_cleanup && callback_success);
166
167   printf ("%s: test \"%s\"\n", passed ? "PASS" : "FAIL", test_spec->test_name);
168
169   if (!passed)
170     {
171       if (!success_setup)
172         printf ("      failure during setup: %s\n",
173                 setup_failure_reason ? setup_failure_reason : "unknown failure");
174       else
175         {
176           if (!success_cleanup)
177             printf ("      failure during cleanup: %s\n",
178                     cleanup_failure_reason ? cleanup_failure_reason : "unknown failure");
179
180           if (!callback_success)
181             printf ("      callback %s called but it %s called\n",
182                     test_spec->callback_must_be_called ? "MUST BE" : "MUST NOT BE",
183                     closure.callback_was_called ? "WAS" : "WAS NOT");
184         }
185     }
186
187   g_free (setup_failure_reason);
188   g_free (cleanup_failure_reason);
189
190   return passed;
191 }
192
193 static gboolean
194 run_tests (TestSpec *test_specs, int num_tests)
195 {
196   int i;
197   int num_passed;
198
199   num_passed = 0;
200
201   for (i = 0; i < num_tests; i++)
202     if (run_test (test_specs + i))
203       num_passed++;
204
205   if (num_passed == num_tests)
206     printf ("ALL TESTS PASSED\n");
207   else
208     printf ("%d of %d tests FAILED\n", (num_tests - num_passed), num_tests);
209
210   return (num_passed == num_tests);
211 }
212
213 \f
214
215 /***** Test functions *****/
216
217 static void
218 sleep_and_cancel_handle (GtkFileSystemHandle *handle)
219 {
220   g_usleep (CANCEL_TIMEOUT_MS * 1000);
221   gtk_file_system_cancel_operation (handle);
222 }
223
224 /* get_folder */
225
226 struct get_folder_data {
227   TestCallbackClosure *callback_closure;
228   GtkFileSystemHandle *handle;
229   GtkFileFolder *folder;
230 };
231
232 static void
233 get_folder_cb (GtkFileSystemHandle *handle,
234                GtkFileFolder       *folder,
235                const GError        *error,
236                gpointer             data)
237 {
238   struct get_folder_data *get_folder_data;
239
240   get_folder_data = data;
241   get_folder_data->folder = folder;
242   notify_callback_called (get_folder_data->callback_closure);
243 }
244
245 static gpointer
246 get_folder_generic_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
247                           TestCallbackClosure *callback_closure)
248 {
249   struct get_folder_data *get_folder_data;
250   GtkFilePath *path;
251
252   path = gtk_file_system_filename_to_path (file_system, GET_FOLDER_FILENAME);
253   if (!path)
254     {
255       *success = FALSE;
256       *failure_reason = g_strdup_printf ("could not turn \"%s\" into a GtkFilePath", GET_FOLDER_FILENAME);
257       return NULL;
258     }
259
260   get_folder_data = g_new (struct get_folder_data, 1);
261
262   get_folder_data->callback_closure = callback_closure;
263   get_folder_data->folder = NULL;
264
265   get_folder_data->handle = gtk_file_system_get_folder (file_system,
266                                                         path,
267                                                         GTK_FILE_INFO_ALL,
268                                                         get_folder_cb,
269                                                         get_folder_data);
270   gtk_file_path_free (path);
271
272   if (!get_folder_data->handle)
273     {
274       g_free (get_folder_data);
275       *success = FALSE;
276       *failure_reason = g_strdup ("gtk_file_system_get_folder() returned a NULL handle");
277       return NULL;
278     }
279
280   *success = TRUE;
281
282   return get_folder_data;
283 }
284
285 static gpointer
286 get_folder_no_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
287                             TestCallbackClosure *callback_closure)
288 {
289   return get_folder_generic_setup (file_system, success, failure_reason, callback_closure);
290 }
291
292 static void
293 get_folder_cleanup (gpointer data, gboolean *success, char **failure_reason)
294 {
295   struct get_folder_data *get_folder_data;
296
297   get_folder_data = data;
298
299   if (get_folder_data->folder)
300     g_object_unref (get_folder_data->folder);
301
302   g_free (get_folder_data);
303
304   *success = TRUE;
305 }
306
307 static gpointer
308 get_folder_with_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
309                               TestCallbackClosure *callback_closure)
310 {
311   struct get_folder_data *get_folder_data;
312
313   get_folder_data = get_folder_generic_setup (file_system, success, failure_reason, callback_closure);
314
315   if (*success)
316     sleep_and_cancel_handle (get_folder_data->handle);
317
318   return get_folder_data;
319 }
320
321 /* get_info */
322
323 struct get_info_data {
324   TestCallbackClosure *callback_closure;
325   GtkFileSystemHandle *handle;
326 };
327
328 static void
329 get_info_cb (GtkFileSystemHandle *handle,
330              const GtkFileInfo   *file_info,
331              const GError        *error,
332              gpointer             data)
333 {
334   struct get_info_data *get_info_data;
335
336   get_info_data = data;
337   notify_callback_called (get_info_data->callback_closure);
338 }
339
340 static gpointer
341 get_info_generic_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
342                         TestCallbackClosure *callback_closure)
343 {
344   GtkFilePath *path;
345   struct get_info_data *get_info_data;
346
347   path = gtk_file_system_filename_to_path (file_system, GET_INFO_FILENAME);
348   if (!path)
349     {
350       *success = FALSE;
351       *failure_reason = g_strdup_printf ("could not turn \"%s\" into a GtkFilePath", GET_INFO_FILENAME);
352       return NULL;
353     }
354
355   get_info_data = g_new (struct get_info_data, 1);
356
357   get_info_data->callback_closure = callback_closure;
358   get_info_data->handle = gtk_file_system_get_info (file_system,
359                                                     path,
360                                                     GTK_FILE_INFO_ALL,
361                                                     get_info_cb,
362                                                     get_info_data);
363   gtk_file_path_free (path);
364
365   if (!get_info_data->handle)
366     {
367       g_free (get_info_data);
368       *success = FALSE;
369       *failure_reason = g_strdup ("gtk_file_system_get_info() returned a NULL handle");
370       return NULL;
371     }
372
373   *success = TRUE;
374   return get_info_data;
375 }
376
377 static gpointer
378 get_info_no_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
379                           TestCallbackClosure *callback_closure)
380 {
381   return get_info_generic_setup (file_system, success, failure_reason, callback_closure);
382 }
383
384 static void
385 get_info_cleanup (gpointer data, gboolean *success, char **failure_reason)
386 {
387   struct get_info_data *get_info_data;
388
389   get_info_data = data;
390   g_free (get_info_data);
391
392   *success = TRUE;
393 }
394
395 static gpointer
396 get_info_with_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
397                             TestCallbackClosure *callback_closure)
398 {
399   struct get_info_data *get_info_data;
400
401   get_info_data = get_info_generic_setup (file_system, success, failure_reason, callback_closure);
402
403   if (*success)
404     sleep_and_cancel_handle (get_info_data->handle);
405
406   return get_info_data;
407 }
408
409 /* create_folder */
410
411 struct create_folder_data {
412   TestCallbackClosure *callback_closure;
413   GtkFileSystemHandle *handle;
414 };
415
416 static void
417 create_folder_cb (GtkFileSystemHandle *handle,
418                   const GtkFilePath   *path,
419                   const GError        *error,
420                   gpointer             data)
421 {
422   struct get_folder_data *get_folder_data;
423
424   get_folder_data = data;
425   notify_callback_called (get_folder_data->callback_closure);
426 }
427
428 static gpointer
429 create_folder_generic_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
430                              TestCallbackClosure *callback_closure)
431 {
432   GtkFilePath *path;
433   struct create_folder_data *create_folder_data;
434
435   path = gtk_file_system_filename_to_path (file_system, CREATE_FOLDER_FILENAME);
436   if (!path)
437     {
438       *success = FALSE;
439       *failure_reason = g_strdup_printf ("could not turn \"%s\" into a GtkFilePath", CREATE_FOLDER_FILENAME);
440       return NULL;
441     }
442
443   create_folder_data = g_new (struct create_folder_data, 1);
444
445   create_folder_data->callback_closure = callback_closure;
446   create_folder_data->handle = gtk_file_system_create_folder (file_system,
447                                                               path,
448                                                               create_folder_cb,
449                                                               create_folder_data);
450   gtk_file_path_free (path);
451
452   if (!create_folder_data->handle)
453     {
454       g_free (create_folder_data);
455       *success = FALSE;
456       *failure_reason = g_strdup ("gtk_file_system_create_folder() returned a NULL handle");
457       return NULL;
458     }
459
460   *success = TRUE;
461   return create_folder_data;
462 }
463
464 static gpointer
465 create_folder_no_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
466                                TestCallbackClosure *callback_closure)
467 {
468   return create_folder_generic_setup (file_system, success, failure_reason, callback_closure);
469 }
470
471 static void
472 create_folder_cleanup (gpointer data, gboolean *success, char **failure_reason)
473 {
474   struct create_folder_data *create_folder_data;
475
476   create_folder_data = data;
477
478   rmdir (CREATE_FOLDER_FILENAME);
479
480   g_free (create_folder_data);
481
482   *success = TRUE;
483 }
484
485 static gpointer
486 create_folder_with_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
487                                  TestCallbackClosure *callback_closure)
488 {
489   struct create_folder_data *create_folder_data;
490
491   create_folder_data = create_folder_generic_setup (file_system, success, failure_reason, callback_closure);
492
493   if (*success)
494     sleep_and_cancel_handle (create_folder_data->handle);
495
496   return create_folder_data;
497 }
498
499 /* volume_mount */
500
501 struct volume_mount_data {
502   TestCallbackClosure *callback_closure;
503   GtkFileSystemVolume *volume;
504   GtkFileSystemHandle *handle;
505 };
506
507 static void
508 volume_mount_cb (GtkFileSystemHandle *handle,
509                  GtkFileSystemVolume *volume,
510                  const GError        *error,
511                  gpointer             data)
512 {
513   struct volume_mount_data *volume_mount_data;
514
515   volume_mount_data = data;
516   notify_callback_called (volume_mount_data->callback_closure);
517 }
518
519 static gpointer
520 volume_mount_generic_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
521                             TestCallbackClosure *callback_closure)
522 {
523   GtkFilePath *path;
524   struct volume_mount_data *volume_mount_data;
525
526   path = gtk_file_system_filename_to_path (file_system, VOLUME_MOUNT_FILENAME);
527   if (!path)
528     {
529       *success = FALSE;
530       *failure_reason = g_strdup_printf ("could not turn \"%s\" into a GtkFilePath", VOLUME_MOUNT_FILENAME);
531       return NULL;
532     }
533
534   volume_mount_data = g_new (struct volume_mount_data, 1);
535
536   volume_mount_data->callback_closure = callback_closure;
537   volume_mount_data->volume = gtk_file_system_get_volume_for_path (file_system, path);
538   gtk_file_path_free (path);
539
540   if (!volume_mount_data->volume)
541     {
542       g_free (volume_mount_data);
543       *success = FALSE;
544       *failure_reason = g_strdup ("gtk_file_system_get_volume_for_path() returned a NULL volume");
545       return NULL;
546     }
547
548   volume_mount_data->handle = gtk_file_system_volume_mount (file_system,
549                                                             volume_mount_data->volume,
550                                                             volume_mount_cb,
551                                                             volume_mount_data);
552   if (!volume_mount_data->handle)
553     {
554       g_object_unref (volume_mount_data->volume);
555       g_free (volume_mount_data);
556       *success = FALSE;
557       *failure_reason = g_strdup ("gtk_file_system_volume_mount() returned a NULL handle");
558       return NULL;
559     }
560
561   *success = TRUE;
562   return volume_mount_data;
563 }
564
565 static gpointer
566 volume_mount_no_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
567                               TestCallbackClosure *callback_closure)
568 {
569   return volume_mount_generic_setup (file_system, success, failure_reason, callback_closure);
570 }
571
572 static void
573 volume_mount_cleanup (gpointer data, gboolean *success, char **failure_reason)
574 {
575   struct volume_mount_data *volume_mount_data;
576
577   volume_mount_data = data;
578
579   g_object_unref (volume_mount_data->volume);
580   g_free (volume_mount_data);
581
582   *success = TRUE;
583 }
584
585 static gpointer
586 volume_mount_with_cancel_setup (GtkFileSystem *file_system, gboolean *success, char **failure_reason,
587                                 TestCallbackClosure *callback_closure)
588 {
589   struct volume_mount_data *volume_mount_data;
590
591   volume_mount_data = volume_mount_generic_setup (file_system, success, failure_reason, callback_closure);
592
593   if (*success)
594     sleep_and_cancel_handle (volume_mount_data->handle);
595
596   return volume_mount_data;
597 }
598
599 /* tests */
600
601 static TestSpec tests[] = {
602   {
603     "get_folder no cancel",
604     TRUE,
605     get_folder_no_cancel_setup,
606     get_folder_cleanup
607   },
608   {
609     "get_folder with cancel",
610     FALSE,
611     get_folder_with_cancel_setup,
612     get_folder_cleanup
613   },
614   {
615     "get_info no cancel",
616     TRUE,
617     get_info_no_cancel_setup,
618     get_info_cleanup
619   },
620   {
621     "get_info with cancel",
622     FALSE,
623     get_info_with_cancel_setup,
624     get_info_cleanup
625   },
626   {
627     "create_folder no cancel",
628     TRUE,
629     create_folder_no_cancel_setup,
630     create_folder_cleanup
631   },
632   {
633     "create_folder with cancel",
634     FALSE,
635     create_folder_with_cancel_setup,
636     create_folder_cleanup
637   },
638   {
639     "volume_mount no cancel",
640     TRUE,
641     volume_mount_no_cancel_setup,
642     volume_mount_cleanup
643   },
644   {
645     "volume_mount with cancel",
646     FALSE,
647     volume_mount_with_cancel_setup,
648     volume_mount_cleanup
649   }
650 };
651
652 \f
653
654 /***** main *****/
655
656 static GLogFunc default_log_handler;
657 static int num_warnings;
658 static int num_errors;
659 static int num_critical_errors;
660
661 static void
662 log_override_cb (const gchar   *log_domain,
663                  GLogLevelFlags log_level,
664                  const gchar   *message,
665                  gpointer       user_data)
666 {
667   if (log_level & G_LOG_LEVEL_WARNING)
668     num_warnings++;
669
670   if (log_level & G_LOG_LEVEL_ERROR)
671     num_errors++;
672
673   if (log_level & G_LOG_LEVEL_CRITICAL)
674     num_critical_errors++;
675
676   (* default_log_handler) (log_domain, log_level, message, user_data);
677 }
678
679 static void
680 log_test (gboolean passed, const char *test_name, ...)
681 {
682   va_list args;
683   char *str;
684
685   va_start (args, test_name);
686   str = g_strdup_vprintf (test_name, args);
687   va_end (args);
688
689   g_printf ("%s: %s\n", passed ? "PASSED" : "FAILED", str);
690   g_free (str);
691 }
692
693 int
694 main (int argc, char **argv)
695 {
696   gboolean passed;
697   gboolean zero_warnings;
698   gboolean zero_errors;
699   gboolean zero_critical_errors;
700
701   default_log_handler = g_log_set_default_handler (log_override_cb, NULL);
702
703   gtk_init (&argc, &argv);
704
705   /* Start tests */
706
707   passed = run_tests (tests, G_N_ELEMENTS (tests));
708
709   /* Warnings and errors */
710
711   zero_warnings = num_warnings == 0;
712   zero_errors = num_errors == 0;
713   zero_critical_errors = num_critical_errors == 0;
714
715   log_test (zero_warnings, "main(): zero warnings (actual number %d)", num_warnings);
716   log_test (zero_errors, "main(): zero errors (actual number %d)", num_errors);
717   log_test (zero_critical_errors, "main(): zero critical errors (actual number %d)", num_critical_errors);
718
719   /* Done */
720
721   passed = passed && zero_warnings && zero_errors && zero_critical_errors;
722
723   log_test (passed, "main(): ALL TESTS");
724
725   return 0;
726 }