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