]> Pileus Git - ~andy/gtk/blob - gtk/tests/filechooser.c
filechooserbutton: For tests, wait for signals instead of just sleeping
[~andy/gtk] / gtk / tests / filechooser.c
1 /* GTK - The GIMP Toolkit
2  * autotestfilechooser.c: Automated unit tests for the GtkFileChooser widget
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 /* TODO:
23  *
24  * - In test_reload_sequence(), test that the selection is preserved properly
25  *   between unmap/map.
26  *
27  * - More tests!
28  */
29
30 #define SLEEP_DURATION  100
31
32 #include "config.h"
33 #include <string.h>
34 #include <glib/gprintf.h>
35 #include <gtk/gtk.h>
36 #include "gtk/gtkfilechooserprivate.h"
37 #include "gtk/gtkfilechooserdefault.h"
38 #include "gtk/gtkfilechooserentry.h"
39
40 #if 0
41 static const char *
42 get_action_name (GtkFileChooserAction action)
43 {
44   switch (action)
45     {
46     case GTK_FILE_CHOOSER_ACTION_OPEN:          return "OPEN";
47     case GTK_FILE_CHOOSER_ACTION_SAVE:          return "SAVE";
48     case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: return "SELECT_FOLDER";
49     case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: return "CREATE_FOLDER";
50
51     default:
52       g_assert_not_reached ();
53       return NULL;
54     }
55 }
56 #endif
57
58 #ifdef BROKEN_TESTS
59 static void
60 log_test (gboolean passed, const char *test_name, ...)
61 {
62   va_list args;
63   char *str;
64
65   va_start (args, test_name);
66   str = g_strdup_vprintf (test_name, args);
67   va_end (args);
68
69   if (g_test_verbose())
70     g_printf ("%s: %s\n", passed ? "PASSED" : "FAILED", str);
71   g_free (str);
72 }
73
74 typedef void (* SetFilenameFn) (GtkFileChooser *chooser, gpointer data);
75 typedef void (* CompareFilenameFn) (GtkFileChooser *chooser, gpointer data);
76
77 struct test_set_filename_closure {
78   GtkWidget *chooser;
79   GtkWidget *accept_button;
80   gboolean focus_button;
81 };
82
83 static gboolean
84 set_filename_timeout_cb (gpointer data)
85 {
86   struct test_set_filename_closure *closure;
87
88   closure = data;
89
90   if (closure->focus_button)
91     gtk_widget_grab_focus (closure->accept_button);
92
93   gtk_button_clicked (GTK_BUTTON (closure->accept_button));
94
95   return FALSE;
96 }
97 #endif
98
99
100 static guint wait_for_idle_id = 0;
101
102 static gboolean
103 wait_for_idle_idle (gpointer data)
104 {
105   wait_for_idle_id = 0;
106
107   return G_SOURCE_REMOVE;
108 }
109
110 static void
111 wait_for_idle (void)
112 {
113   wait_for_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100,
114                                       wait_for_idle_idle,
115                                       NULL, NULL);
116
117   while (wait_for_idle_id)
118     gtk_main_iteration ();
119 }
120
121 #ifdef BROKEN_TESTS
122 static void
123 test_set_filename (GtkFileChooserAction action,
124                    gboolean focus_button,
125                    SetFilenameFn set_filename_fn,const
126                    CompareFilenameFn compare_filename_fn,
127                    gpointer data)
128 {
129   GtkWidget *chooser;
130   struct test_set_filename_closure closure;
131
132   chooser = gtk_file_chooser_dialog_new ("hello", NULL, action,
133                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
134                                          NULL);
135
136   closure.chooser = chooser;
137   closure.accept_button = gtk_dialog_add_button (GTK_DIALOG (chooser), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
138   closure.focus_button = focus_button;
139
140   gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
141
142   (* set_filename_fn) (GTK_FILE_CHOOSER (chooser), data);
143
144   gdk_threads_add_timeout_full (G_MAXINT, SLEEP_DURATION, set_filename_timeout_cb, &closure, NULL);
145   gtk_dialog_run (GTK_DIALOG (chooser));
146
147   (* compare_filename_fn) (GTK_FILE_CHOOSER (chooser), data);
148
149   gtk_widget_destroy (chooser);
150 }
151
152 static void
153 set_filename_cb (GtkFileChooser *chooser, gpointer data)
154 {
155   const char *filename;
156
157   filename = data;
158   gtk_file_chooser_set_filename (chooser, filename);
159 }
160
161 static void
162 compare_filename_cb (GtkFileChooser *chooser, gpointer data)
163 {
164   const char *filename;
165   char *out_filename;
166
167   filename = data;
168   out_filename = gtk_file_chooser_get_filename (chooser);
169
170   g_assert_cmpstr (out_filename, ==, filename);
171
172   if (out_filename)
173     g_free (out_filename);
174 }
175
176 typedef struct
177 {
178   const char *test_name;
179   GtkFileChooserAction action;
180   const char *filename;
181   gboolean focus_button;
182 } TestSetFilenameSetup;
183
184 static void
185 test_black_box_set_filename (gconstpointer data)
186 {
187   const TestSetFilenameSetup *setup = data;
188
189   test_set_filename (setup->action, setup->focus_button, set_filename_cb, compare_filename_cb, (char *) setup->filename);
190 }
191
192 struct current_name_closure {
193         const char *path;
194         const char *current_name;
195 };
196
197 static void
198 set_current_name_cb (GtkFileChooser *chooser, gpointer data)
199 {
200   struct current_name_closure *closure;
201
202   closure = data;
203
204   gtk_file_chooser_set_current_folder (chooser, closure->path);
205   gtk_file_chooser_set_current_name (chooser, closure->current_name);
206 }
207
208 static void
209 compare_current_name_cb (GtkFileChooser *chooser, gpointer data)
210 {
211   struct current_name_closure *closure;
212   char *out_filename;
213   char *filename;
214
215   closure = data;
216
217   out_filename = gtk_file_chooser_get_filename (chooser);
218
219   g_assert (out_filename != NULL);
220
221   filename = g_build_filename (closure->path, closure->current_name, NULL);
222   g_assert_cmpstr (filename, ==, out_filename);
223
224   g_free (filename);
225   g_free (out_filename);
226 }
227
228 typedef struct
229 {
230   const char *test_name;
231   GtkFileChooserAction action;
232   const char *current_name;
233   gboolean focus_button;
234 } TestSetCurrentNameSetup;
235
236 static void
237 test_black_box_set_current_name (gconstpointer data)
238 {
239   const TestSetCurrentNameSetup *setup = data;
240   struct current_name_closure closure;
241   char *cwd;
242
243   cwd = g_get_current_dir ();
244
245   closure.path = cwd;
246   closure.current_name = setup->current_name;
247
248   test_set_filename (setup->action, setup->focus_button, set_current_name_cb, compare_current_name_cb, &closure);
249
250   g_free (cwd);
251 }
252 #endif
253
254 /* FIXME: fails in CREATE_FOLDER mode when FOLDER_NAME == "/" */
255
256 #if 0
257 #define FILE_NAME "/nonexistent"
258 #define FILE_NAME_2 "/nonexistent2"
259 #define FOLDER_NAME "/etc"
260 #define FOLDER_NAME_2 "/usr"
261 #else
262 #define FILE_NAME "/etc/passwd"
263 #define FILE_NAME_2 "/etc/group"
264 #define FOLDER_NAME "/etc"
265 #define FOLDER_NAME_2 "/usr"
266 #endif
267
268 #define CURRENT_NAME "parangaricutirimicuaro.txt"
269 #define CURRENT_NAME_FOLDER "parangaricutirimicuaro"
270
271 /* https://bugzilla.novell.com/show_bug.cgi?id=184875
272  * http://bugzilla.gnome.org/show_bug.cgi?id=347066
273  * http://bugzilla.gnome.org/show_bug.cgi?id=346058
274  */
275
276 #ifdef BROKEN_TESTS
277 static void
278 setup_set_filename_tests (void)
279 {
280   static TestSetFilenameSetup tests[] =
281     {
282       { "/GtkFileChooser/black_box/set_filename/open/no_focus",          GTK_FILE_CHOOSER_ACTION_OPEN,          FILE_NAME,  FALSE },
283       { "/GtkFileChooser/black_box/set_filename/open/focus",             GTK_FILE_CHOOSER_ACTION_OPEN,          FILE_NAME,  TRUE  },
284       { "/GtkFileChooser/black_box/set_filename/save/no_focus",          GTK_FILE_CHOOSER_ACTION_SAVE,          FILE_NAME,  FALSE },
285       { "/GtkFileChooser/black_box/set_filename/save/focus",             GTK_FILE_CHOOSER_ACTION_SAVE,          FILE_NAME,  TRUE  },
286       { "/GtkFileChooser/black_box/set_filename/select_folder/no_focus", GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FOLDER_NAME,FALSE },
287       { "/GtkFileChooser/black_box/set_filename/select_folder/focus",    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FOLDER_NAME,TRUE  },
288       { "/GtkFileChooser/black_box/set_filename/create_folder/no_focus", GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, FOLDER_NAME,FALSE },
289       { "/GtkFileChooser/black_box/set_filename/create_folder/focus",    GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, FOLDER_NAME,TRUE  },
290     };
291   int i;
292
293   for (i = 0; i < G_N_ELEMENTS (tests); i++)
294     g_test_add_data_func (tests[i].test_name, &tests[i], test_black_box_set_filename);
295 }
296
297 static void
298 setup_set_current_name_tests (void)
299 {
300   static TestSetCurrentNameSetup tests[] =
301     {
302       { "/GtkFileChooser/black_box/set_current_name/save/no_focus",          GTK_FILE_CHOOSER_ACTION_SAVE,          CURRENT_NAME,        FALSE },
303       { "/GtkFileChooser/black_box/set_current_name/save/focus",             GTK_FILE_CHOOSER_ACTION_SAVE,          CURRENT_NAME,        TRUE  },
304       { "/GtkFileChooser/black_box/set_current_name/create_folder/no_focus", GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, CURRENT_NAME_FOLDER, FALSE },
305       { "/GtkFileChooser/black_box/set_current_name/create_folder/focus",    GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, CURRENT_NAME_FOLDER, TRUE  },
306     };
307   int i;
308
309   for (i = 0; i < G_N_ELEMENTS (tests); i++)
310     g_test_add_data_func (tests[i].test_name, &tests[i], test_black_box_set_current_name);
311 }
312 #endif
313
314 typedef struct
315 {
316   const char *shortname;
317   GtkFileChooserAction action;
318   const char *initial_current_folder;
319   const char *initial_filename;
320   gboolean open_dialog;
321   const char *tweak_current_folder;
322   const char *tweak_filename;
323   gint dialog_response;
324   gboolean unselect_all;
325   const char *final_current_folder;
326   const char *final_filename;
327 } FileChooserButtonTest;
328
329 static char *
330 make_button_test_name (FileChooserButtonTest *t)
331 {
332   return g_strdup_printf ("/GtkFileChooserButton/%s", t->shortname);
333 #if 0
334   GString *s = g_string_new ("/GtkFileChooserButton");
335
336   g_string_append_printf (s, "/%s/%s/%s/%s",
337                           get_action_name (t->action),
338                           t->initial_current_folder ? "set_initial_folder" : "no_default_folder",
339                           t->initial_filename ? "set_initial_filename" : "no_initial_filename",
340                           t->open_dialog ? "open_dialog" : "no_dialog");
341
342   if (t->tweak_current_folder)
343     g_string_append (s, "/tweak_current_folder");
344
345   if (t->tweak_filename)
346     g_string_append (s, "/tweak_filename");
347
348   if (t->open_dialog)
349     g_string_append_printf (s, "/%s",
350                             t->dialog_response == GTK_RESPONSE_ACCEPT ? "accept" : "cancel");
351
352   if (t->final_current_folder)
353     g_string_append (s, "/final_current_folder");
354
355   if (t->final_filename)
356     g_string_append (s, "/final_filename");
357
358   return g_string_free (s, FALSE);
359 #endif
360 }
361
362 static gboolean
363 sleep_timeout_cb (gpointer data)
364 {
365   gtk_main_quit ();
366   return FALSE;
367 }
368
369 static void
370 sleep_in_main_loop (void)
371 {
372   gdk_threads_add_timeout_full (G_MAXINT, 250, sleep_timeout_cb, NULL, NULL);
373   gtk_main ();
374 }
375
376 static void
377 build_children_list (GtkWidget *widget, gpointer data)
378 {
379   GList **list;
380
381   list = data;
382   *list = g_list_prepend (*list, widget);
383 }
384
385 static GtkWidget *
386 find_child_widget_with_atk_role (GtkWidget *widget, AtkRole role)
387 {
388   AtkObject *accessible;
389   AtkRole a_role;
390
391   accessible = gtk_widget_get_accessible (widget);
392   a_role = atk_object_get_role (accessible);
393
394   if (a_role == role)
395     return widget;
396   else
397     {
398       GtkWidget *found_child;
399
400       found_child = NULL;
401
402       if (GTK_IS_CONTAINER (widget))
403         {
404           GList *children;
405           GList *l;
406
407           children = NULL;
408           gtk_container_forall (GTK_CONTAINER (widget), build_children_list, &children);
409
410           l = children;
411
412           while (l && !found_child)
413             {
414               GtkWidget *child;
415
416               child = GTK_WIDGET (l->data);
417
418               found_child = find_child_widget_with_atk_role (child, role);
419
420               l = l->next;
421             }
422
423           g_list_free (children);
424         }
425
426       return found_child;
427     }
428 }
429
430 static const char *
431 get_atk_name_for_filechooser_button (GtkFileChooserButton *button)
432 {
433   GtkFileChooserAction action;
434   GtkWidget *widget;
435   AtkObject *accessible;
436
437   action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button));
438   g_assert (action == GTK_FILE_CHOOSER_ACTION_OPEN || action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
439
440   if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
441     widget = find_child_widget_with_atk_role (GTK_WIDGET (button), ATK_ROLE_PUSH_BUTTON);
442   else
443     widget = find_child_widget_with_atk_role (GTK_WIDGET (button), ATK_ROLE_COMBO_BOX);
444
445   accessible = gtk_widget_get_accessible (widget);
446   return atk_object_get_name (accessible);
447 }
448
449 static void
450 check_that_basename_is_shown (GtkFileChooserButton *button, const char *expected_filename)
451 {
452   GtkFileChooserAction action;
453   const char *name_on_button;
454   char *expected_basename;
455
456   name_on_button = get_atk_name_for_filechooser_button (button);
457
458   action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button));
459   g_assert (action == GTK_FILE_CHOOSER_ACTION_OPEN || action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
460
461   if (expected_filename)
462     expected_basename = g_path_get_basename (expected_filename);
463   else
464     expected_basename = NULL;
465
466   if (expected_basename)
467     g_assert_cmpstr (expected_basename, ==, name_on_button);
468   else
469     g_assert_cmpstr (name_on_button, ==, "(None)"); /* see gtkfilechooserbutton.c:FALLBACK_DISPLAY_NAME */ /* FIXME: how do we translate this? */
470
471   g_free (expected_basename);
472 }
473
474 static const char *
475 get_expected_shown_filename (GtkFileChooserAction action, const char *folder_name, const char *filename)
476 {
477   if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
478     {
479       if (filename)
480         return filename;
481       else
482         return folder_name;
483     }
484   else
485     return filename;
486 }
487
488 static GtkWidget *
489 get_file_chooser_dialog_from_button (GtkFileChooserButton *button)
490 {
491   GtkWidget *fc_dialog;
492
493   /* Give me the internal dialog, damnit */
494   fc_dialog = g_object_get_qdata (G_OBJECT (button), g_quark_from_static_string ("gtk-file-chooser-delegate"));
495   g_assert (GTK_IS_FILE_CHOOSER (fc_dialog));
496   g_assert (GTK_IS_DIALOG (fc_dialog));
497
498   return fc_dialog;
499 }
500
501 typedef struct {
502   GtkWidget *window;
503   GtkWidget *fc_button;
504 } WindowAndButton;
505
506 static WindowAndButton
507 create_window_and_file_chooser_button (GtkFileChooserAction action)
508 {
509   WindowAndButton w;
510
511   w.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
512
513   w.fc_button = gtk_file_chooser_button_new (action == GTK_FILE_CHOOSER_ACTION_OPEN ? "Select a file" : "Select a folder",
514                                              action);
515   gtk_container_add (GTK_CONTAINER (w.window), w.fc_button);
516
517   return w;
518 }
519
520 typedef struct
521 {
522   GObject *object;
523   GHashTable *signals;
524   gboolean in_main_loop;
525 } SignalWatcher;
526
527 typedef struct
528 {
529   SignalWatcher *watcher;
530   char *signal_name;
531   gulong id;
532   gboolean emitted;
533 } SignalConnection;
534
535 static SignalWatcher *
536 signal_watcher_new (GObject *object)
537 {
538   SignalWatcher *watcher = g_new0 (SignalWatcher, 1);
539
540   watcher->object = g_object_ref (object);
541   watcher->signals = g_hash_table_new (g_str_hash, g_str_equal);
542
543   return watcher;
544 }
545
546 static void
547 dummy_callback (GObject *object)
548 {
549   /* nothing */
550 }
551
552 static void
553 marshal_notify_cb (gpointer data, GClosure *closure)
554 {
555   if (data)
556     {
557       SignalConnection *conn;
558
559       conn = data;
560       conn->emitted = TRUE;
561
562       if (conn->watcher->in_main_loop)
563         {
564           gtk_main_quit ();
565           conn->watcher->in_main_loop = FALSE;
566         }
567     }
568 }
569
570 static void
571 signal_watcher_watch_signal (SignalWatcher *watcher, const char *signal_name)
572 {
573   SignalConnection *conn;
574
575   conn = g_hash_table_lookup (watcher->signals, signal_name);
576   if (!conn)
577     {
578       GClosure *closure;
579
580       conn = g_new0 (SignalConnection, 1);
581       conn->watcher = watcher;
582       conn->signal_name = g_strdup (signal_name);
583
584       closure = g_cclosure_new (G_CALLBACK (dummy_callback), NULL, NULL);
585       g_closure_add_marshal_guards (closure, conn, marshal_notify_cb, NULL, marshal_notify_cb);
586       conn->id = g_signal_connect_closure (watcher->object, signal_name, closure, FALSE);
587       conn->emitted = FALSE;
588
589       g_hash_table_insert (watcher->signals, conn->signal_name, conn);
590     }
591   else
592     conn->emitted = FALSE;
593 }
594
595 static gboolean
596 signal_watcher_expect (SignalWatcher *watcher, const char *signal_name)
597 {
598   SignalConnection *conn;
599   gboolean emitted;
600
601   conn = g_hash_table_lookup (watcher->signals, signal_name);
602   g_assert (conn != NULL);
603
604   if (!conn->emitted)
605     {
606       gdk_threads_add_timeout_full (G_MAXINT, 1000, sleep_timeout_cb, NULL, NULL);
607       watcher->in_main_loop = TRUE;
608       gtk_main ();
609       watcher->in_main_loop = FALSE;
610     }
611
612   emitted = conn->emitted;
613   conn->emitted = FALSE;
614
615   return emitted;
616 }
617
618 static void
619 destroy_connection (gpointer key, gpointer value, gpointer user_data)
620 {
621   SignalConnection *conn;
622
623   conn = value;
624   g_signal_handler_disconnect (conn->watcher->object, conn->id);
625   g_free (conn->signal_name);
626   g_free (conn);
627 }
628
629 static void
630 signal_watcher_destroy (SignalWatcher *watcher)
631 {
632   g_hash_table_foreach (watcher->signals, destroy_connection, NULL);
633   g_hash_table_destroy (watcher->signals);
634   g_object_unref (watcher->object);
635   g_free (watcher);
636 }
637
638 static void
639 test_file_chooser_button (gconstpointer data)
640 {
641   const FileChooserButtonTest *setup = data;
642   WindowAndButton w;
643   SignalWatcher *watcher;
644   GtkWidget *fc_dialog;
645   int iterations;
646   int i;
647
648   w = create_window_and_file_chooser_button (setup->action);
649
650   watcher = signal_watcher_new (G_OBJECT (w.fc_button));
651   signal_watcher_watch_signal (watcher, "current-folder-changed");
652   signal_watcher_watch_signal (watcher, "selection-changed");
653
654   if (setup->initial_current_folder)
655     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w.fc_button), setup->initial_current_folder);
656
657   if (setup->initial_filename)
658     gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (w.fc_button), setup->initial_filename);
659
660   gtk_widget_show_all (w.window);
661   wait_for_idle ();
662
663   if (setup->initial_current_folder)
664     g_assert (signal_watcher_expect (watcher, "current-folder-changed"));
665
666   if (setup->initial_filename)
667     g_assert (signal_watcher_expect (watcher, "selection-changed"));
668
669   check_that_basename_is_shown (GTK_FILE_CHOOSER_BUTTON (w.fc_button),
670                                 get_expected_shown_filename (setup->action, setup->initial_current_folder, setup->initial_filename));
671
672   /* If there is a dialog to be opened, we actually test going through it a
673    * couple of times.  This ensures that any state that the button frobs for
674    * each appearance of the dialog will make sense.
675    */
676   if (setup->open_dialog)
677     iterations = 2;
678   else
679     iterations = 1;
680
681   for (i = 0; i < iterations; i++)
682     {
683       if (setup->open_dialog)
684         {
685           GList *children;
686
687           /* Hack our way into the file chooser button; get its GtkButton child and click it */
688           children = gtk_container_get_children (GTK_CONTAINER (w.fc_button));
689           g_assert (children && GTK_IS_BUTTON (children->data));
690           gtk_button_clicked (GTK_BUTTON (children->data));
691           g_list_free (children);
692
693           wait_for_idle ();
694
695           fc_dialog = get_file_chooser_dialog_from_button (GTK_FILE_CHOOSER_BUTTON (w.fc_button));
696         }
697
698       /* Okay, now frob the button and its optional dialog */
699
700       if (setup->tweak_current_folder)
701         {
702           signal_watcher_watch_signal (watcher, "current-folder-changed");
703
704           gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w.fc_button), setup->tweak_current_folder);
705
706           g_assert (signal_watcher_expect (watcher, "current-folder-changed"));
707         }
708
709       if (setup->tweak_filename)
710         {
711           signal_watcher_watch_signal (watcher, "selection-changed");
712
713           gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (w.fc_button), setup->tweak_filename);
714
715           g_assert (signal_watcher_expect (watcher, "selection-changed"));
716         }
717
718       if (setup->unselect_all)
719         {
720           signal_watcher_watch_signal (watcher, "selection-changed");
721
722           gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (w.fc_button));
723
724           g_assert (signal_watcher_expect (watcher, "selection-changed"));
725         }
726
727       wait_for_idle ();
728
729       if (setup->open_dialog)
730         {
731           gtk_dialog_response (GTK_DIALOG (fc_dialog), setup->dialog_response);
732           wait_for_idle ();
733
734           gtk_window_resize (GTK_WINDOW (fc_dialog), 500, 500);
735         }
736
737       if (setup->final_current_folder)
738         {
739           char *folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (w.fc_button));
740
741           g_assert_cmpstr (folder, ==, setup->final_current_folder);
742           g_free (folder);
743         }
744
745       if (setup->final_filename)
746         {
747           char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w.fc_button));
748
749           g_assert_cmpstr (filename, ==, setup->final_filename);
750           g_free (filename);
751         }
752
753       check_that_basename_is_shown (GTK_FILE_CHOOSER_BUTTON (w.fc_button),
754                                     get_expected_shown_filename (setup->action, setup->final_current_folder, setup->final_filename));
755     }
756
757   signal_watcher_destroy (watcher);
758   gtk_widget_destroy (w.window);
759 }
760
761 static int
762 find_accessible_action_num (AtkObject *object, const char *action_name)
763 {
764   AtkAction *action_a;
765   int num_actions;
766   int i;
767
768   action_a = ATK_ACTION (object);
769
770   num_actions = atk_action_get_n_actions (action_a);
771
772   for (i = 0; i < num_actions; i++)
773     if (strcmp (atk_action_get_name (action_a, i), action_name) == 0)
774       return i;
775
776   return -1;
777 }
778
779 static void
780 do_accessible_action (AtkObject *object, const char *action_name)
781 {
782   int action_num;
783
784   action_num = find_accessible_action_num (object, action_name);
785   g_assert (action_num != -1);
786
787   atk_action_do_action (ATK_ACTION (object), action_num);
788 }
789
790 static void
791 test_file_chooser_button_combo_box_1 (void)
792 {
793   WindowAndButton w;
794   GtkWidget *combo_box;
795   AtkObject *combo_box_a;
796   AtkObject *menu_a;
797   int num_items;
798   int other_index;
799   AtkObject *item_a;
800   GtkWidget *fc_dialog;
801
802   w = create_window_and_file_chooser_button (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
803
804   gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (w.fc_button), FOLDER_NAME);
805
806   gtk_widget_show_all (w.window);
807
808   /* Get the accessible for the combo box */
809
810   combo_box = find_child_widget_with_atk_role (GTK_WIDGET (w.fc_button), ATK_ROLE_COMBO_BOX);
811   combo_box_a = gtk_widget_get_accessible (combo_box);
812
813   /* Press the combo box to bring up the menu */
814
815   do_accessible_action (combo_box_a, "press");
816   sleep_in_main_loop (); /* have to wait because bringing up the menu is asynchronous... */
817
818   /* Get the menu from the combo box; it's the first child */
819
820   menu_a = atk_object_ref_accessible_child (combo_box_a, 0);
821   g_assert (atk_object_get_role (menu_a) == ATK_ROLE_MENU);
822
823   /* Check that the last item in the menu is the "Other…" one */
824
825   num_items = atk_object_get_n_accessible_children (menu_a);
826   g_assert (num_items > 0);
827
828   other_index = num_items - 1;
829
830   item_a = atk_object_ref_accessible_child (menu_a, other_index);
831   g_assert_cmpstr (atk_object_get_name (item_a), ==, "Other…");  /* FIXME: how do we translate this? */
832
833   /* Activate the item */
834
835   do_accessible_action (item_a, "click");
836
837   /* Cancel the dialog */
838
839   sleep_in_main_loop ();
840   fc_dialog = get_file_chooser_dialog_from_button (GTK_FILE_CHOOSER_BUTTON (w.fc_button));
841
842   gtk_dialog_response (GTK_DIALOG (fc_dialog), GTK_RESPONSE_CANCEL);
843
844   /* Now check the selection in the combo box */
845   check_that_basename_is_shown (GTK_FILE_CHOOSER_BUTTON (w.fc_button), FOLDER_NAME);
846
847   gtk_widget_destroy (w.window);
848 }
849
850 static void
851 setup_file_chooser_button_combo_box_tests (void)
852 {
853   g_test_add_func ("/GtkFileChooserButton/combo_box-1", test_file_chooser_button_combo_box_1);
854 }
855
856 static FileChooserButtonTest button_tests[] =
857   {
858     /* OPEN tests without dialog */
859
860     {
861       "open-1",
862       GTK_FILE_CHOOSER_ACTION_OPEN,
863       NULL,                     /* initial_current_folder */
864       NULL,                     /* initial_filename */
865       FALSE,                    /* open_dialog */
866       NULL,                     /* tweak_current_folder */
867       NULL,                     /* tweak_filename */
868       0,                        /* dialog_response */
869       FALSE,                    /* unselect_all */
870       NULL,                     /* final_current_folder */
871       NULL                      /* final_filename */
872     },
873     {
874       "open-2",
875       GTK_FILE_CHOOSER_ACTION_OPEN,
876       NULL,                     /* initial_current_folder */
877       FILE_NAME,                /* initial_filename */
878       FALSE,                    /* open_dialog */
879       NULL,                     /* tweak_current_folder */
880       NULL,                     /* tweak_filename */
881       0,                        /* dialog_response */
882       FALSE,                    /* unselect_all */
883       NULL,                     /* final_current_folder */
884       FILE_NAME                 /* final_filename */
885     },
886     {
887       "open-3",
888       GTK_FILE_CHOOSER_ACTION_OPEN,
889       NULL,                     /* initial_current_folder */
890       NULL,                     /* initial_filename */
891       FALSE,                    /* open_dialog */
892       NULL,                     /* tweak_current_folder */
893       FILE_NAME,                /* tweak_filename */
894       0,                        /* dialog_response */
895       FALSE,                    /* unselect_all */
896       NULL,                     /* final_current_folder */
897       FILE_NAME                 /* final_filename */
898     },
899     {
900       "open-4",
901       GTK_FILE_CHOOSER_ACTION_OPEN,
902       NULL,                     /* initial_current_folder */
903       FILE_NAME,                /* initial_filename */
904       FALSE,                    /* open_dialog */
905       NULL,                     /* tweak_current_folder */
906       FILE_NAME_2,              /* tweak_filename */
907       0,                        /* dialog_response */
908       FALSE,                    /* unselect_all */
909       NULL,                     /* final_current_folder */
910       FILE_NAME_2               /* final_filename */
911     },
912     {
913       "open-5",
914       GTK_FILE_CHOOSER_ACTION_OPEN,
915       FOLDER_NAME,              /* initial_current_folder */
916       NULL,                     /* initial_filename */
917       FALSE,                    /* open_dialog */
918       NULL,                     /* tweak_current_folder */
919       NULL,                     /* tweak_filename */
920       0,                        /* dialog_response */
921       FALSE,                    /* unselect_all */
922       FOLDER_NAME,              /* final_current_folder */
923       NULL                      /* final_filename */
924     },
925     {
926       "open-6",
927       GTK_FILE_CHOOSER_ACTION_OPEN,
928       FOLDER_NAME,              /* initial_current_folder */
929       NULL,                     /* initial_filename */
930       FALSE,                    /* open_dialog */
931       FOLDER_NAME_2,            /* tweak_current_folder */
932       NULL,                     /* tweak_filename */
933       0,                        /* dialog_response */
934       FALSE,                    /* unselect_all */
935       FOLDER_NAME_2,            /* final_current_folder */
936       NULL                      /* final_filename */
937     },
938
939     /* SELECT_FOLDER tests without dialog */
940
941     {
942       "select-folder-1",
943       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
944       NULL,                     /* initial_current_folder */
945       NULL,                     /* initial_filename */
946       FALSE,                    /* open_dialog */
947       NULL,                     /* tweak_current_folder */
948       NULL,                     /* tweak_filename */
949       0,                        /* dialog_response */
950       FALSE,                    /* unselect_all */
951       NULL,                     /* final_current_folder */
952       NULL                      /* final_filename */
953     },
954     {
955       "select-folder-2",
956       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
957       NULL,                     /* initial_current_folder */
958       FOLDER_NAME,              /* initial_filename */
959       FALSE,                    /* open_dialog */
960       NULL,                     /* tweak_current_folder */
961       NULL,                     /* tweak_filename */
962       0,                        /* dialog_response */
963       FALSE,                    /* unselect_all */
964       NULL,                     /* final_current_folder */
965       FOLDER_NAME               /* final_filename */
966     },
967     {
968       "select-folder-3",
969       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
970       NULL,                     /* initial_current_folder */
971       FOLDER_NAME,              /* initial_filename */
972       FALSE,                    /* open_dialog */
973       NULL,                     /* tweak_current_folder */
974       FOLDER_NAME_2,            /* tweak_filename */
975       0,                        /* dialog_response */
976       FALSE,                    /* unselect_all */
977       NULL,                     /* final_current_folder */
978       FOLDER_NAME_2             /* final_filename */
979     },
980     {
981       "select-folder-4",
982       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
983       FOLDER_NAME,              /* initial_current_folder */
984       NULL,                     /* initial_filename */
985       FALSE,                    /* open_dialog */
986       NULL,                     /* tweak_current_folder */
987       NULL,                     /* tweak_filename */
988       0,                        /* dialog_response */
989       FALSE,                    /* unselect_all */
990       NULL,                     /* final_current_folder */
991       FOLDER_NAME               /* final_filename */
992     },
993     {
994       "select-folder-5",
995       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
996       FOLDER_NAME,              /* initial_current_folder */
997       NULL,                     /* initial_filename */
998       FALSE,                    /* open_dialog */
999       NULL,                     /* tweak_current_folder */
1000       NULL,                     /* tweak_filename */
1001       0,                        /* dialog_response */
1002       FALSE,                    /* unselect_all */
1003       FOLDER_NAME,              /* final_current_folder */
1004       NULL                      /* final_filename */
1005     },
1006     {
1007       "select-folder-6",
1008       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1009       FOLDER_NAME,              /* initial_current_folder */
1010       NULL,                     /* initial_filename */
1011       FALSE,                    /* open_dialog */
1012       FOLDER_NAME_2,            /* tweak_current_folder */
1013       NULL,                     /* tweak_filename */
1014       0,                        /* dialog_response */
1015       FALSE,                    /* unselect_all */
1016       NULL,                     /* final_current_folder */
1017       FOLDER_NAME_2             /* final_filename */
1018     },
1019     {
1020       "select-folder-7",
1021       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1022       FOLDER_NAME,              /* initial_current_folder */
1023       NULL,                     /* initial_filename */
1024       FALSE,                    /* open_dialog */
1025       FOLDER_NAME_2,            /* tweak_current_folder */
1026       NULL,                     /* tweak_filename */
1027       0,                        /* dialog_response */
1028       FALSE,                    /* unselect_all */
1029       FOLDER_NAME_2,            /* final_current_folder */
1030       NULL                      /* final_filename */
1031     },
1032     {
1033       "select-folder-8",
1034       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1035       FOLDER_NAME,              /* initial_current_folder */
1036       NULL,                     /* initial_filename */
1037       FALSE,                    /* open_dialog */
1038       NULL,                     /* tweak_current_folder */
1039       FOLDER_NAME_2,            /* tweak_filename */
1040       0,                        /* dialog_response */
1041       FALSE,                    /* unselect_all */
1042       NULL,                     /* final_current_folder */
1043       FOLDER_NAME_2             /* final_filename */
1044     },
1045
1046     /* OPEN tests with dialog, cancelled */
1047
1048     {
1049       "open-dialog-cancel-1",
1050       GTK_FILE_CHOOSER_ACTION_OPEN,
1051       NULL,                     /* initial_current_folder */
1052       NULL,                     /* initial_filename */
1053       TRUE,                     /* open_dialog */
1054       NULL,                     /* tweak_current_folder */
1055       NULL,                     /* tweak_filename */
1056       GTK_RESPONSE_CANCEL,      /* dialog_response */
1057       FALSE,                    /* unselect_all */
1058       NULL,                     /* final_current_folder */
1059       NULL                      /* final_filename */
1060     },
1061     {
1062       "open-dialog-cancel-2",
1063       GTK_FILE_CHOOSER_ACTION_OPEN,
1064       NULL,                     /* initial_current_folder */
1065       FILE_NAME,                /* initial_filename */
1066       TRUE,                     /* open_dialog */
1067       NULL,                     /* tweak_current_folder */
1068       NULL,                     /* tweak_filename */
1069       GTK_RESPONSE_CANCEL,      /* dialog_response */
1070       FALSE,                    /* unselect_all */
1071       NULL,                     /* final_current_folder */
1072       FILE_NAME                 /* final_filename */
1073     },
1074     {
1075       "open-dialog-cancel-3",
1076       GTK_FILE_CHOOSER_ACTION_OPEN,
1077       FOLDER_NAME,              /* initial_current_folder */
1078       NULL,                     /* initial_filename */
1079       TRUE,                     /* open_dialog */
1080       NULL,                     /* tweak_current_folder */
1081       NULL,                     /* tweak_filename */
1082       GTK_RESPONSE_CANCEL,      /* dialog_response */
1083       FALSE,                    /* unselect_all */
1084       FOLDER_NAME,              /* final_current_folder */
1085       NULL                      /* final_filename */
1086     },
1087     {
1088       "open-dialog-cancel-4",
1089       GTK_FILE_CHOOSER_ACTION_OPEN,
1090       NULL,                     /* initial_current_folder */
1091       NULL,                     /* initial_filename */
1092       TRUE,                     /* open_dialog */
1093       NULL,                     /* tweak_current_folder */
1094       FILE_NAME,                /* tweak_filename */
1095       GTK_RESPONSE_CANCEL,      /* dialog_response */
1096       FALSE,                    /* unselect_all */
1097       NULL,                     /* final_current_folder */
1098       NULL                      /* final_filename */
1099     },
1100     {
1101       "open-dialog-cancel-5",
1102       GTK_FILE_CHOOSER_ACTION_OPEN,
1103       NULL,                     /* initial_current_folder */
1104       FILE_NAME,                /* initial_filename */
1105       TRUE,                     /* open_dialog */
1106       NULL,                     /* tweak_current_folder */
1107       FILE_NAME_2,              /* tweak_filename */
1108       GTK_RESPONSE_CANCEL,      /* dialog_response */
1109       FALSE,                    /* unselect_all */
1110       NULL,                     /* final_current_folder */
1111       FILE_NAME                 /* final_filename */
1112     },
1113     {
1114       "open-dialog-cancel-6",
1115       GTK_FILE_CHOOSER_ACTION_OPEN,
1116       FOLDER_NAME,              /* initial_current_folder */
1117       NULL,                     /* initial_filename */
1118       TRUE,                     /* open_dialog */
1119       NULL,                     /* tweak_current_folder */
1120       FILE_NAME_2,              /* tweak_filename */
1121       GTK_RESPONSE_CANCEL,      /* dialog_response */
1122       FALSE,                    /* unselect_all */
1123       FOLDER_NAME,              /* final_current_folder */
1124       NULL                      /* final_filename */
1125     },
1126
1127     /* OPEN tests with dialog, cancelled via closing the dialog (not by selecting the Cancel button) */
1128
1129     {
1130       "open-dialog-close-1",
1131       GTK_FILE_CHOOSER_ACTION_OPEN,
1132       NULL,                     /* initial_current_folder */
1133       NULL,                     /* initial_filename */
1134       TRUE,                     /* open_dialog */
1135       NULL,                     /* tweak_current_folder */
1136       NULL,                     /* tweak_filename */
1137       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1138       FALSE,                    /* unselect_all */
1139       NULL,                     /* final_current_folder */
1140       NULL                      /* final_filename */
1141     },
1142     {
1143       "open-dialog-close-2",
1144       GTK_FILE_CHOOSER_ACTION_OPEN,
1145       NULL,                     /* initial_current_folder */
1146       FILE_NAME,                /* initial_filename */
1147       TRUE,                     /* open_dialog */
1148       NULL,                     /* tweak_current_folder */
1149       NULL,                     /* tweak_filename */
1150       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1151       FALSE,                    /* unselect_all */
1152       NULL,                     /* final_current_folder */
1153       FILE_NAME                 /* final_filename */
1154     },
1155     {
1156       "open-dialog-close-3",
1157       GTK_FILE_CHOOSER_ACTION_OPEN,
1158       FOLDER_NAME,              /* initial_current_folder */
1159       NULL,                     /* initial_filename */
1160       TRUE,                     /* open_dialog */
1161       NULL,                     /* tweak_current_folder */
1162       NULL,                     /* tweak_filename */
1163       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1164       FALSE,                    /* unselect_all */
1165       FOLDER_NAME,              /* final_current_folder */
1166       NULL                      /* final_filename */
1167     },
1168     {
1169       "open-dialog-close-4",
1170       GTK_FILE_CHOOSER_ACTION_OPEN,
1171       NULL,                     /* initial_current_folder */
1172       NULL,                     /* initial_filename */
1173       TRUE,                     /* open_dialog */
1174       NULL,                     /* tweak_current_folder */
1175       FILE_NAME,                /* tweak_filename */
1176       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1177       FALSE,                    /* unselect_all */
1178       NULL,                     /* final_current_folder */
1179       NULL                      /* final_filename */
1180     },
1181     {
1182       "open-dialog-close-5",
1183       GTK_FILE_CHOOSER_ACTION_OPEN,
1184       NULL,                     /* initial_current_folder */
1185       FILE_NAME,                /* initial_filename */
1186       TRUE,                     /* open_dialog */
1187       NULL,                     /* tweak_current_folder */
1188       FILE_NAME_2,              /* tweak_filename */
1189       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1190       FALSE,                    /* unselect_all */
1191       NULL,                     /* final_current_folder */
1192       FILE_NAME                 /* final_filename */
1193     },
1194     {
1195       "open-dialog-close-6",
1196       GTK_FILE_CHOOSER_ACTION_OPEN,
1197       FOLDER_NAME,              /* initial_current_folder */
1198       NULL,                     /* initial_filename */
1199       TRUE,                     /* open_dialog */
1200       NULL,                     /* tweak_current_folder */
1201       FILE_NAME_2,              /* tweak_filename */
1202       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1203       FALSE,                    /* unselect_all */
1204       FOLDER_NAME,              /* final_current_folder */
1205       NULL                      /* final_filename */
1206     },
1207
1208     /* SELECT_FOLDER tests with dialog, cancelled */
1209
1210     {
1211       "select-folder-dialog-cancel-1",
1212       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1213       NULL,                     /* initial_current_folder */
1214       NULL,                     /* initial_filename */
1215       TRUE,                     /* open_dialog */
1216       NULL,                     /* tweak_current_folder */
1217       NULL,                     /* tweak_filename */
1218       GTK_RESPONSE_CANCEL,      /* dialog_response */
1219       FALSE,                    /* unselect_all */
1220       NULL,                     /* final_current_folder */
1221       NULL                      /* final_filename */
1222     },
1223     {
1224       "select-folder-dialog-cancel-2",
1225       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1226       NULL,                     /* initial_current_folder */
1227       FOLDER_NAME,              /* initial_filename */
1228       TRUE,                     /* open_dialog */
1229       NULL,                     /* tweak_current_folder */
1230       NULL,                     /* tweak_filename */
1231       GTK_RESPONSE_CANCEL,      /* dialog_response */
1232       FALSE,                    /* unselect_all */
1233       NULL,                     /* final_current_folder */
1234       FOLDER_NAME               /* final_filename */
1235     },
1236     {
1237       "select-folder-dialog-cancel-3",
1238       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1239       FOLDER_NAME,              /* initial_current_folder */
1240       NULL,                     /* initial_filename */
1241       TRUE,                     /* open_dialog */
1242       NULL,                     /* tweak_current_folder */
1243       NULL,                     /* tweak_filename */
1244       GTK_RESPONSE_CANCEL,      /* dialog_response */
1245       FALSE,                    /* unselect_all */
1246       FOLDER_NAME,              /* final_current_folder */
1247       NULL                      /* final_filename */
1248     },
1249     {
1250       "select-folder-dialog-cancel-4",
1251       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1252       FOLDER_NAME,              /* initial_current_folder */
1253       NULL,                     /* initial_filename */
1254       TRUE,                     /* open_dialog */
1255       NULL,                     /* tweak_current_folder */
1256       NULL,                     /* tweak_filename */
1257       GTK_RESPONSE_CANCEL,      /* dialog_response */
1258       FALSE,                    /* unselect_all */
1259       NULL,                     /* final_current_folder */
1260       FOLDER_NAME               /* final_filename */
1261     },
1262     {
1263       "select-folder-dialog-cancel-5",
1264       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1265       NULL,                     /* initial_current_folder */
1266       NULL,                     /* initial_filename */
1267       TRUE,                     /* open_dialog */
1268       NULL,                     /* tweak_current_folder */
1269       FOLDER_NAME,              /* tweak_filename */
1270       GTK_RESPONSE_CANCEL,      /* dialog_response */
1271       FALSE,                    /* unselect_all */
1272       NULL,                     /* final_current_folder */
1273       NULL                      /* final_filename */
1274     },
1275     {
1276       "select-folder-dialog-cancel-6",
1277       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1278       NULL,                     /* initial_current_folder */
1279       FOLDER_NAME,              /* initial_filename */
1280       TRUE,                     /* open_dialog */
1281       NULL,                     /* tweak_current_folder */
1282       FOLDER_NAME_2,            /* tweak_filename */
1283       GTK_RESPONSE_CANCEL,      /* dialog_response */
1284       FALSE,                    /* unselect_all */
1285       NULL,                     /* final_current_folder */
1286       FOLDER_NAME               /* final_filename */
1287     },
1288     {
1289       "select-folder-dialog-cancel-7",
1290       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1291       FOLDER_NAME,              /* initial_current_folder */
1292       NULL,                     /* initial_filename */
1293       TRUE,                     /* open_dialog */
1294       NULL,                     /* tweak_current_folder */
1295       FOLDER_NAME_2,            /* tweak_filename */
1296       GTK_RESPONSE_CANCEL,      /* dialog_response */
1297       FALSE,                    /* unselect_all */
1298       FOLDER_NAME,              /* final_current_folder */
1299       NULL                      /* final_filename */
1300     },
1301     {
1302       "select-folder-dialog-cancel-8",
1303       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1304       FOLDER_NAME,              /* initial_current_folder */
1305       NULL,                     /* initial_filename */
1306       TRUE,                     /* open_dialog */
1307       NULL,                     /* tweak_current_folder */
1308       FOLDER_NAME_2,            /* tweak_filename */
1309       GTK_RESPONSE_CANCEL,      /* dialog_response */
1310       FALSE,                    /* unselect_all */
1311       NULL,                     /* final_current_folder */
1312       FOLDER_NAME               /* final_filename */
1313     },
1314
1315     /* SELECT_FOLDER tests with dialog, cancelled via closing the dialog (not selecting the Cancel button) */
1316
1317     {
1318       "select-folder-dialog-close-1",
1319       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1320       NULL,                     /* initial_current_folder */
1321       NULL,                     /* initial_filename */
1322       TRUE,                     /* open_dialog */
1323       NULL,                     /* tweak_current_folder */
1324       NULL,                     /* tweak_filename */
1325       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1326       FALSE,                    /* unselect_all */
1327       NULL,                     /* final_current_folder */
1328       NULL                      /* final_filename */
1329     },
1330     {
1331       "select-folder-dialog-close-2",
1332       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1333       NULL,                     /* initial_current_folder */
1334       FOLDER_NAME,              /* initial_filename */
1335       TRUE,                     /* open_dialog */
1336       NULL,                     /* tweak_current_folder */
1337       NULL,                     /* tweak_filename */
1338       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1339       FALSE,                    /* unselect_all */
1340       NULL,                     /* final_current_folder */
1341       FOLDER_NAME               /* final_filename */
1342     },
1343     {
1344       "select-folder-dialog-close-3",
1345       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1346       FOLDER_NAME,              /* initial_current_folder */
1347       NULL,                     /* initial_filename */
1348       TRUE,                     /* open_dialog */
1349       NULL,                     /* tweak_current_folder */
1350       NULL,                     /* tweak_filename */
1351       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1352       FALSE,                    /* unselect_all */
1353       FOLDER_NAME,              /* final_current_folder */
1354       NULL                      /* final_filename */
1355     },
1356     {
1357       "select-folder-dialog-close-4",
1358       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1359       FOLDER_NAME,              /* initial_current_folder */
1360       NULL,                     /* initial_filename */
1361       TRUE,                     /* open_dialog */
1362       NULL,                     /* tweak_current_folder */
1363       NULL,                     /* tweak_filename */
1364       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1365       FALSE,                    /* unselect_all */
1366       NULL,                     /* final_current_folder */
1367       FOLDER_NAME               /* final_filename */
1368     },
1369     {
1370       "select-folder-dialog-close-5",
1371       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1372       NULL,                     /* initial_current_folder */
1373       NULL,                     /* initial_filename */
1374       TRUE,                     /* open_dialog */
1375       NULL,                     /* tweak_current_folder */
1376       FOLDER_NAME,              /* tweak_filename */
1377       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1378       FALSE,                    /* unselect_all */
1379       NULL,                     /* final_current_folder */
1380       NULL                      /* final_filename */
1381     },
1382     {
1383       "select-folder-dialog-close-6",
1384       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1385       NULL,                     /* initial_current_folder */
1386       FOLDER_NAME,              /* initial_filename */
1387       TRUE,                     /* open_dialog */
1388       NULL,                     /* tweak_current_folder */
1389       FOLDER_NAME_2,            /* tweak_filename */
1390       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1391       FALSE,                    /* unselect_all */
1392       NULL,                     /* final_current_folder */
1393       FOLDER_NAME               /* final_filename */
1394     },
1395     {
1396       "select-folder-dialog-close-7",
1397       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1398       FOLDER_NAME,              /* initial_current_folder */
1399       NULL,                     /* initial_filename */
1400       TRUE,                     /* open_dialog */
1401       NULL,                     /* tweak_current_folder */
1402       FOLDER_NAME_2,            /* tweak_filename */
1403       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1404       FALSE,                    /* unselect_all */
1405       FOLDER_NAME,              /* final_current_folder */
1406       NULL                      /* final_filename */
1407     },
1408     {
1409       "select-folder-dialog-close-8",
1410       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1411       FOLDER_NAME,              /* initial_current_folder */
1412       NULL,                     /* initial_filename */
1413       TRUE,                     /* open_dialog */
1414       NULL,                     /* tweak_current_folder */
1415       FOLDER_NAME_2,            /* tweak_filename */
1416       GTK_RESPONSE_DELETE_EVENT,/* dialog_response */
1417       FALSE,                    /* unselect_all */
1418       NULL,                     /* final_current_folder */
1419       FOLDER_NAME               /* final_filename */
1420     },
1421
1422     /* OPEN tests with dialog */
1423
1424     {
1425       "open-dialog-1",
1426       GTK_FILE_CHOOSER_ACTION_OPEN,
1427       NULL,                     /* initial_current_folder */
1428       NULL,                     /* initial_filename */
1429       TRUE,                     /* open_dialog */
1430       NULL,                     /* tweak_current_folder */
1431       FILE_NAME,                /* tweak_filename */
1432       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1433       FALSE,                    /* unselect_all */
1434       NULL,                     /* final_current_folder */
1435       FILE_NAME                 /* final_filename */
1436     },
1437     {
1438       "open-dialog-2",
1439       GTK_FILE_CHOOSER_ACTION_OPEN,
1440       NULL,                     /* initial_current_folder */
1441       FILE_NAME,                /* initial_filename */
1442       TRUE,                     /* open_dialog */
1443       NULL,                     /* tweak_current_folder */
1444       NULL,                     /* tweak_filename */
1445       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1446       FALSE,                    /* unselect_all */
1447       NULL,                     /* final_current_folder */
1448       FILE_NAME                 /* final_filename */
1449     },
1450     {
1451       "open-dialog-3",
1452       GTK_FILE_CHOOSER_ACTION_OPEN,
1453       NULL,                     /* initial_current_folder */
1454       FILE_NAME,                /* initial_filename */
1455       TRUE,                     /* open_dialog */
1456       NULL,                     /* tweak_current_folder */
1457       FILE_NAME_2,              /* tweak_filename */
1458       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1459       FALSE,                    /* unselect_all */
1460       NULL,                     /* final_current_folder */
1461       FILE_NAME_2               /* final_filename */
1462     },
1463     {
1464       "open-dialog-4",
1465       GTK_FILE_CHOOSER_ACTION_OPEN,
1466       FOLDER_NAME,              /* initial_current_folder */
1467       NULL,                     /* initial_filename */
1468       TRUE,                     /* open_dialog */
1469       NULL,                     /* tweak_current_folder */
1470       FILE_NAME,                /* tweak_filename */
1471       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1472       FALSE,                    /* unselect_all */
1473       NULL,                     /* final_current_folder */
1474       FILE_NAME                 /* final_filename */
1475     },
1476
1477     /* SELECT_FOLDER tests with dialog */
1478
1479     {
1480       "select-folder-dialog-1",
1481       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1482       NULL,                     /* initial_current_folder */
1483       FOLDER_NAME,              /* initial_filename */
1484       TRUE,                     /* open_dialog */
1485       NULL,                     /* tweak_current_folder */
1486       NULL,                     /* tweak_filename */
1487       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1488       FALSE,                    /* unselect_all */
1489       NULL,                     /* final_current_folder */
1490       FOLDER_NAME               /* final_filename */
1491     },
1492     {
1493       "select-folder-dialog-2",
1494       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1495       FOLDER_NAME,              /* initial_current_folder */
1496       NULL,                     /* initial_filename */
1497       TRUE,                     /* open_dialog */
1498       NULL,                     /* tweak_current_folder */
1499       NULL,                     /* tweak_filename */
1500       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1501       FALSE,                    /* unselect_all */
1502       NULL,                     /* final_current_folder */
1503       FOLDER_NAME               /* final_filename */
1504     },
1505     {
1506       "select-folder-dialog-3",
1507       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1508       NULL,                     /* initial_current_folder */
1509       FOLDER_NAME,              /* initial_filename */
1510       TRUE,                     /* open_dialog */
1511       NULL,                     /* tweak_current_folder */
1512       FOLDER_NAME_2,            /* tweak_filename */
1513       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1514       FALSE,                    /* unselect_all */
1515       NULL,                     /* final_current_folder */
1516       FOLDER_NAME_2             /* final_filename */
1517     },
1518     {
1519       "select-folder-dialog-4",
1520       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1521       FOLDER_NAME,              /* initial_current_folder */
1522       NULL,                     /* initial_filename */
1523       TRUE,                     /* open_dialog */
1524       NULL,                     /* tweak_current_folder */
1525       FOLDER_NAME_2,            /* tweak_filename */
1526       GTK_RESPONSE_ACCEPT,      /* dialog_response */
1527       FALSE,                    /* unselect_all */
1528       NULL,                     /* final_current_folder */
1529       FOLDER_NAME_2             /* final_filename */
1530     },
1531
1532     /* Unselection tests */
1533     {
1534       "unselect-all-1",
1535       GTK_FILE_CHOOSER_ACTION_OPEN,
1536       NULL,                     /* initial_current_folder */
1537       NULL,                     /* initial_filename */
1538       FALSE,                    /* open_dialog */
1539       NULL,                     /* tweak_current_folder */
1540       NULL,                     /* tweak_filename */
1541       0,                        /* dialog_response */
1542       TRUE,                     /* unselect_all */
1543       NULL,                     /* final_current_folder */
1544       NULL                      /* final_filename */
1545     },
1546     {
1547       "unselect-all-2",
1548       GTK_FILE_CHOOSER_ACTION_OPEN,
1549       NULL,                     /* initial_current_folder */
1550       FILE_NAME,                /* initial_filename */
1551       FALSE,                    /* open_dialog */
1552       NULL,                     /* tweak_current_folder */
1553       NULL,                     /* tweak_filename */
1554       0,                        /* dialog_response */
1555       TRUE,                     /* unselect_all */
1556       NULL,                     /* final_current_folder */
1557       NULL                      /* final_filename */
1558     },
1559     {
1560       "unselect-all-3",
1561       GTK_FILE_CHOOSER_ACTION_OPEN,
1562       NULL,                     /* initial_current_folder */
1563       FILE_NAME,                /* initial_filename */
1564       FALSE,                    /* open_dialog */
1565       NULL,                     /* tweak_current_folder */
1566       FILE_NAME_2,              /* tweak_filename */
1567       0,                        /* dialog_response */
1568       TRUE,                     /* unselect_all */
1569       NULL,                     /* final_current_folder */
1570       NULL                      /* final_filename */
1571     },
1572     {
1573       "unselect-all-4",
1574       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1575       NULL,                     /* initial_current_folder */
1576       NULL,                     /* initial_filename */
1577       FALSE,                    /* open_dialog */
1578       NULL,                     /* tweak_current_folder */
1579       NULL,                     /* tweak_filename */
1580       0,                        /* dialog_response */
1581       TRUE,                     /* unselect_all */
1582       NULL,                     /* final_current_folder */
1583       NULL                      /* final_filename */
1584     },
1585     {
1586       "unselect-all-5",
1587       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1588       NULL,                     /* initial_current_folder */
1589       FOLDER_NAME,              /* initial_filename */
1590       FALSE,                    /* open_dialog */
1591       NULL,                     /* tweak_current_folder */
1592       NULL,                     /* tweak_filename */
1593       0,                        /* dialog_response */
1594       TRUE,                     /* unselect_all */
1595       NULL,                     /* final_current_folder */
1596       NULL                      /* final_filename */
1597     },
1598     {
1599       "unselect-all-6",
1600       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1601       NULL,                     /* initial_current_folder */
1602       FOLDER_NAME,              /* initial_filename */
1603       FALSE,                    /* open_dialog */
1604       NULL,                     /* tweak_current_folder */
1605       FOLDER_NAME_2,            /* tweak_filename */
1606       0,                        /* dialog_response */
1607       TRUE,                     /* unselect_all */
1608       NULL,                     /* final_current_folder */
1609       NULL                      /* final_filename */
1610     },
1611
1612   };
1613
1614 static void
1615 setup_file_chooser_button_tests (void)
1616 {
1617   int i;
1618
1619   for (i = 0; i < G_N_ELEMENTS (button_tests); i++)
1620     {
1621       char *test_name;
1622
1623       test_name = make_button_test_name (&button_tests[i]);
1624       g_test_add_data_func (test_name, &button_tests[i], test_file_chooser_button);
1625       g_free (test_name);
1626     }
1627
1628   setup_file_chooser_button_combo_box_tests ();
1629 }
1630
1631 #ifdef BROKEN_TESTS
1632 struct confirm_overwrite_closure {
1633   GtkWidget *chooser;
1634   GtkWidget *accept_button;
1635   gint confirm_overwrite_signal_emitted;
1636   gchar *extension;
1637 };
1638
1639 static GtkFileChooserConfirmation
1640 confirm_overwrite_cb (GtkFileChooser *chooser, gpointer data)
1641 {
1642   struct confirm_overwrite_closure *closure = data;
1643
1644   if (g_test_verbose())
1645     printf ("bling!\n");
1646   closure->confirm_overwrite_signal_emitted += 1;
1647
1648   return GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
1649 }
1650
1651 static void
1652 overwrite_response_cb (GtkFileChooser *chooser, gint response, gpointer data)
1653 {
1654   struct confirm_overwrite_closure *closure = data;
1655   char *filename;
1656
1657   if (g_test_verbose())
1658     printf ("plong!\n");
1659
1660   if (response != GTK_RESPONSE_ACCEPT)
1661     return;
1662
1663   filename = gtk_file_chooser_get_filename (chooser);
1664
1665   if (!g_str_has_suffix (filename, closure->extension))
1666     {
1667       char *basename;
1668
1669       basename = g_path_get_basename (filename);
1670       g_free (filename);
1671
1672       filename = g_strconcat (basename, closure->extension, NULL);
1673       gtk_file_chooser_set_current_name (chooser, filename);
1674
1675       g_signal_stop_emission_by_name (chooser, "response");
1676       gtk_dialog_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
1677     }
1678 }
1679
1680 static gboolean
1681 confirm_overwrite_timeout_cb (gpointer data)
1682 {
1683   struct confirm_overwrite_closure *closure;
1684
1685   closure = data;
1686   gtk_button_clicked (GTK_BUTTON (closure->accept_button));
1687
1688   return FALSE;
1689 }
1690
1691 /* http://bugzilla.gnome.org/show_bug.cgi?id=347883 */
1692 static gboolean
1693 test_confirm_overwrite_for_path (const char *path, gboolean append_extension)
1694 {
1695   gboolean passed;
1696   struct confirm_overwrite_closure closure;
1697   char *filename;
1698
1699   passed = TRUE;
1700
1701   closure.extension = NULL;
1702   closure.confirm_overwrite_signal_emitted = 0;
1703   closure.chooser = gtk_file_chooser_dialog_new ("hello", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
1704                                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1705                                                  NULL);
1706   closure.accept_button = gtk_dialog_add_button (GTK_DIALOG (closure.chooser),
1707                                                  GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT);
1708   gtk_dialog_set_default_response (GTK_DIALOG (closure.chooser), GTK_RESPONSE_ACCEPT);
1709
1710   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (closure.chooser), TRUE);
1711
1712   g_signal_connect (closure.chooser, "confirm-overwrite",
1713                     G_CALLBACK (confirm_overwrite_cb), &closure);
1714
1715   if (append_extension)
1716     {
1717       char *extension;
1718
1719       filename = g_path_get_dirname (path);
1720       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (closure.chooser), filename);
1721       g_free (filename);
1722
1723       filename = g_path_get_basename (path);
1724       extension = strchr (filename, '.');
1725
1726       if (extension)
1727         {
1728           closure.extension = g_strdup (extension);
1729           *extension = '\0';
1730         }
1731
1732       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (closure.chooser), filename);
1733       g_free (filename);
1734
1735       g_signal_connect (closure.chooser, "response",
1736                         G_CALLBACK (overwrite_response_cb), &closure);
1737     }
1738   else
1739     {
1740       gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (closure.chooser), path);
1741     }
1742
1743   gdk_threads_add_timeout_full (G_MAXINT, SLEEP_DURATION, confirm_overwrite_timeout_cb, &closure, NULL);
1744   gtk_dialog_run (GTK_DIALOG (closure.chooser));
1745
1746   filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (closure.chooser));
1747   passed = passed && filename && (strcmp (filename, path) == 0);
1748   g_free (filename);
1749
1750   gtk_widget_destroy (closure.chooser);
1751
1752   passed = passed && (1 == closure.confirm_overwrite_signal_emitted);
1753
1754   log_test (passed, "Confirm overwrite for %s", path);
1755
1756   return passed;
1757 }
1758
1759 static void
1760 test_confirm_overwrite (void)
1761 {
1762   gboolean passed = TRUE;
1763
1764   /* first test for a file we know will always exist */
1765   passed = passed && test_confirm_overwrite_for_path ("/etc/passwd", FALSE);
1766   g_assert (passed);
1767   passed = passed && test_confirm_overwrite_for_path ("/etc/resolv.conf", TRUE);
1768   g_assert (passed);
1769 }
1770 #endif
1771
1772 static const GtkFileChooserAction open_actions[] = {
1773   GTK_FILE_CHOOSER_ACTION_OPEN,
1774   GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
1775 };
1776
1777 static const GtkFileChooserAction save_actions[] = {
1778   GTK_FILE_CHOOSER_ACTION_SAVE,
1779   GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
1780 };
1781
1782
1783 #ifdef BROKEN_TESTS
1784 static gboolean
1785 has_action (const GtkFileChooserAction *actions,
1786             int n_actions,
1787             GtkFileChooserAction sought_action)
1788 {
1789   int i;
1790
1791   for (i = 0; i < n_actions; i++)
1792     if (actions[i] == sought_action)
1793       return TRUE;
1794
1795   return FALSE;
1796 }
1797
1798 static GtkFileChooserDefault *
1799 get_impl_from_dialog (GtkWidget *dialog)
1800 {
1801   GtkFileChooserDialog *d;
1802   GtkFileChooserDialogPrivate *dialog_priv;
1803   GtkFileChooserWidget *chooser_widget;
1804   GtkFileChooserWidgetPrivate *widget_priv;
1805   GtkFileChooserDefault *impl;
1806
1807   d = GTK_FILE_CHOOSER_DIALOG (dialog);
1808   dialog_priv = d->priv;
1809   chooser_widget = GTK_FILE_CHOOSER_WIDGET (dialog_priv->widget);
1810   if (!chooser_widget)
1811     g_error ("BUG: dialog_priv->widget is not a GtkFileChooserWidget");
1812
1813   widget_priv = chooser_widget->priv;
1814   impl = (GtkFileChooserDefault *) (widget_priv->impl);
1815   if (!impl)
1816     g_error ("BUG: widget_priv->impl is not a GtkFileChooserDefault");
1817
1818   return impl;
1819 }
1820
1821 static gboolean
1822 test_widgets_for_current_action (GtkFileChooserDialog *dialog,
1823                                  GtkFileChooserAction  expected_action)
1824 {
1825   GtkFileChooserDefault *impl;
1826   gboolean passed;
1827
1828   if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) != expected_action)
1829     return FALSE;
1830
1831   impl = get_impl_from_dialog (GTK_WIDGET (dialog));
1832
1833   g_assert (impl->action == expected_action);
1834
1835   passed = TRUE;
1836
1837   /* OPEN implies that the "new folder" button is hidden; otherwise it is shown */
1838   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
1839     passed = passed && !gtk_widget_get_visible (impl->browse_new_folder_button);
1840   else
1841     passed = passed && gtk_widget_get_visible (impl->browse_new_folder_button);
1842
1843   /* Check that the widgets are present/visible or not */
1844   if (has_action (open_actions, G_N_ELEMENTS (open_actions), impl->action))
1845     {
1846       passed = passed && (impl->save_widgets == NULL
1847                           && (impl->location_mode == LOCATION_MODE_PATH_BAR
1848                               ? impl->location_entry == NULL
1849                               : impl->location_entry != NULL)
1850                           && impl->save_folder_label == NULL
1851                           && impl->save_folder_combo == NULL
1852                           && impl->save_expander == NULL
1853                           && GTK_IS_CONTAINER (impl->browse_widgets) && gtk_widget_is_drawable (impl->browse_widgets));
1854     }
1855   else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action))
1856     {
1857       /* FIXME: we can't use GTK_IS_FILE_CHOOSER_ENTRY() because it uses
1858        * _gtk_file_chooser_entry_get_type(), which is a non-exported symbol.
1859        * So, we just test impl->location_entry for being non-NULL
1860        */
1861       passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && gtk_widget_is_drawable (impl->save_widgets)
1862                           && impl->location_entry != NULL && gtk_widget_is_drawable (impl->location_entry)
1863                           && GTK_IS_LABEL (impl->save_folder_label) && gtk_widget_is_drawable (impl->save_folder_label)
1864                           && GTK_IS_COMBO_BOX (impl->save_folder_combo) && gtk_widget_is_drawable (impl->save_folder_combo)
1865                           && GTK_IS_EXPANDER (impl->save_expander) && gtk_widget_is_drawable (impl->save_expander)
1866                           && GTK_IS_CONTAINER (impl->browse_widgets));
1867
1868       /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of
1869        * the children that change depending on the state of the expander.
1870        */
1871     }
1872   else
1873     {
1874       g_error ("BAD TEST: test_widgets_for_current_action() doesn't know about %s", get_action_name (impl->action));
1875       passed = FALSE;
1876     }
1877
1878   return passed;
1879 }
1880
1881 typedef gboolean (* ForeachActionCallback) (GtkFileChooserDialog *dialog,
1882                                             GtkFileChooserAction  action,
1883                                             gpointer              user_data);
1884
1885 static gboolean
1886 foreach_action (GtkFileChooserDialog *dialog,
1887                 ForeachActionCallback callback,
1888                 gpointer              user_data)
1889 {
1890   GEnumClass *enum_class;
1891   int i;
1892
1893   enum_class = g_type_class_peek (GTK_TYPE_FILE_CHOOSER_ACTION);
1894   if (!enum_class)
1895     g_error ("BUG: get_action_name(): no GEnumClass for GTK_TYPE_FILE_CHOOSER_ACTION");
1896
1897   for (i = 0; i < enum_class->n_values; i++)
1898     {
1899       GEnumValue *enum_value;
1900       GtkFileChooserAction action;
1901       gboolean passed;
1902
1903       enum_value = enum_class->values + i;
1904       action = enum_value->value;
1905
1906       passed = (* callback) (dialog, action, user_data);
1907       if (!passed)
1908         return FALSE;
1909     }
1910
1911   return TRUE;
1912 }
1913
1914 struct action_closure {
1915   GtkFileChooserAction from_action;
1916 };
1917
1918 static gboolean
1919 switch_from_to_action_cb (GtkFileChooserDialog *dialog,
1920                           GtkFileChooserAction  action,
1921                           gpointer              user_data)
1922 {
1923   struct action_closure *closure;
1924   gboolean passed;
1925
1926   closure = user_data;
1927
1928   gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), closure->from_action);
1929
1930   passed = test_widgets_for_current_action (dialog, closure->from_action);
1931   log_test (passed, "switch_from_to_action_cb(): reset to action %s", get_action_name (closure->from_action));
1932   if (!passed)
1933     return FALSE;
1934
1935   gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), action);
1936
1937   passed = test_widgets_for_current_action (dialog, action);
1938   log_test (passed, "switch_from_to_action_cb(): transition from %s to %s",
1939             get_action_name (closure->from_action),
1940             get_action_name (action));
1941   return passed;
1942 }
1943
1944 static gboolean
1945 switch_from_action_cb (GtkFileChooserDialog *dialog,
1946                        GtkFileChooserAction  action,
1947                        gpointer              user_data)
1948 {
1949   struct action_closure closure;
1950
1951   closure.from_action = action;
1952
1953   return foreach_action (dialog, switch_from_to_action_cb, &closure);
1954 }
1955
1956 static void
1957 test_action_widgets (void)
1958 {
1959   GtkWidget *dialog;
1960   GtkFileChooserAction action;
1961   gboolean passed;
1962
1963   dialog = gtk_file_chooser_dialog_new ("Test file chooser",
1964                                         NULL,
1965                                         GTK_FILE_CHOOSER_ACTION_OPEN,
1966                                         GTK_STOCK_CANCEL,
1967                                         GTK_RESPONSE_CANCEL,
1968                                         GTK_STOCK_OK,
1969                                         GTK_RESPONSE_ACCEPT,
1970                                         NULL);
1971   gtk_widget_show_now (dialog);
1972
1973   action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
1974
1975   passed = test_widgets_for_current_action (GTK_FILE_CHOOSER_DIALOG (dialog), action);
1976   log_test (passed, "test_action_widgets(): widgets for initial action %s", get_action_name (action));
1977   g_assert (passed);
1978
1979   passed = foreach_action (GTK_FILE_CHOOSER_DIALOG (dialog), switch_from_action_cb, NULL);
1980   log_test (passed, "test_action_widgets(): all transitions through property change");
1981   g_assert (passed);
1982
1983   gtk_widget_destroy (dialog);
1984 }
1985 #endif
1986
1987 #ifdef BROKEN_TESTS
1988 static gboolean
1989 test_reload_sequence (gboolean set_folder_before_map)
1990 {
1991   GtkWidget *dialog;
1992   GtkFileChooserDefault *impl;
1993   gboolean passed;
1994   char *folder;
1995   char *current_working_dir;
1996
1997   passed = TRUE;
1998
1999   current_working_dir = g_get_current_dir ();
2000
2001   dialog = gtk_file_chooser_dialog_new ("Test file chooser",
2002                                         NULL,
2003                                         GTK_FILE_CHOOSER_ACTION_OPEN,
2004                                         GTK_STOCK_CANCEL,
2005                                         GTK_RESPONSE_CANCEL,
2006                                         GTK_STOCK_OK,
2007                                         GTK_RESPONSE_ACCEPT,
2008                                         NULL);
2009   impl = get_impl_from_dialog (dialog);
2010
2011   if (set_folder_before_map)
2012     {
2013       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
2014
2015       wait_for_idle ();
2016
2017       passed = passed && (impl->current_folder != NULL
2018                           && impl->browse_files_model != NULL
2019                           && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2020                           && impl->reload_state == RELOAD_HAS_FOLDER
2021                           && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
2022                           && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2023                               ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
2024                               : TRUE));
2025
2026       wait_for_idle ();
2027
2028       folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
2029       passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2030       g_free (folder);
2031     }
2032   else
2033     {
2034       /* Initially, no folder is not loaded or pending */
2035       passed = passed && (impl->current_folder == NULL
2036                           && impl->sort_model == NULL
2037                           && impl->browse_files_model == NULL
2038                           && impl->load_state == LOAD_EMPTY
2039                           && impl->reload_state == RELOAD_EMPTY
2040                           && impl->load_timeout_id == 0);
2041
2042       wait_for_idle ();
2043
2044       folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
2045       passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2046     }
2047
2048   log_test (passed, "test_reload_sequence(): initial status");
2049
2050   /* After mapping, it is loading some folder, either the one that was explicitly set or the default one */
2051
2052   gtk_widget_show_now (dialog);
2053
2054   wait_for_idle ();
2055
2056   passed = passed && (impl->current_folder != NULL
2057                       && impl->browse_files_model != NULL
2058                       && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2059                       && impl->reload_state == RELOAD_HAS_FOLDER
2060                       && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
2061                       && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2062                           ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
2063                           : TRUE));
2064
2065   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
2066   if (set_folder_before_map)
2067     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2068   else
2069     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2070
2071   g_free (folder);
2072
2073   log_test (passed, "test_reload_sequence(): status after map");
2074
2075   /* Unmap it; we should still have a folder */
2076
2077   gtk_widget_hide (dialog);
2078
2079   wait_for_idle ();
2080
2081   passed = passed && (impl->current_folder != NULL
2082                       && impl->browse_files_model != NULL
2083                       && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2084                       && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
2085                       && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2086                           ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
2087                           : TRUE));
2088
2089   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
2090   if (set_folder_before_map)
2091     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2092   else
2093     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2094
2095   g_free (folder);
2096
2097   log_test (passed, "test_reload_sequence(): status after unmap");
2098
2099   /* Map it again! */
2100
2101   gtk_widget_show_now (dialog);
2102
2103   wait_for_idle ();
2104
2105   passed = passed && (impl->current_folder != NULL
2106                       && impl->browse_files_model != NULL
2107                       && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2108                       && impl->reload_state == RELOAD_HAS_FOLDER
2109                       && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
2110                       && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
2111                           ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
2112                           : TRUE));
2113
2114   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
2115   if (set_folder_before_map)
2116     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2117   else
2118     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2119
2120   g_free (folder);
2121
2122   log_test (passed, "test_reload_sequence(): status after re-map");
2123
2124   gtk_widget_destroy (dialog);
2125   g_free (current_working_dir);
2126
2127   return passed;
2128 }
2129
2130 static void
2131 test_reload (void)
2132 {
2133   gboolean passed;
2134
2135   passed = test_reload_sequence (FALSE);
2136   log_test (passed, "test_reload(): create and use the default folder");
2137   g_assert (passed);
2138
2139   passed = test_reload_sequence (TRUE);
2140   log_test (passed, "test_reload(): set a folder explicitly before mapping");
2141   g_assert (passed);
2142 }
2143
2144 static gboolean
2145 test_button_folder_states_for_action (GtkFileChooserAction action, gboolean use_dialog, gboolean set_folder_on_dialog)
2146 {
2147   gboolean passed;
2148   GtkWidget *window;
2149   GtkWidget *button;
2150   char *folder;
2151   GtkWidget *dialog;
2152   char *current_working_dir;
2153   gboolean must_have_cwd;
2154
2155   passed = TRUE;
2156
2157   current_working_dir = g_get_current_dir ();
2158   must_have_cwd = !(use_dialog && set_folder_on_dialog);
2159
2160   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2161
2162   if (use_dialog)
2163     {
2164       dialog = gtk_file_chooser_dialog_new ("Test", NULL, action,
2165                                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2166                                             GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2167                                             NULL);
2168       button = gtk_file_chooser_button_new_with_dialog (dialog);
2169
2170       if (set_folder_on_dialog)
2171         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
2172     }
2173   else
2174     {
2175       button = gtk_file_chooser_button_new ("Test", action);
2176       dialog = NULL; /* keep gcc happy */
2177     }
2178
2179   gtk_container_add (GTK_CONTAINER (window), button);
2180
2181   /* Pre-map; no folder is set */
2182   wait_for_idle ();
2183
2184   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
2185   if (must_have_cwd)
2186     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2187   else
2188     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2189
2190   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, pre-map, %s",
2191             get_action_name (action),
2192             use_dialog,
2193             set_folder_on_dialog,
2194             must_have_cwd ? "must have $cwd" : "must have explicit folder");
2195
2196   /* Map; folder should be set */
2197
2198   gtk_widget_show_all (window);
2199   gtk_widget_show_now (window);
2200
2201   wait_for_idle ();
2202
2203   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
2204
2205   if (must_have_cwd)
2206     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2207   else
2208     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2209
2210   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, mapped, %s",
2211             get_action_name (action),
2212             use_dialog,
2213             set_folder_on_dialog,
2214             must_have_cwd ? "must have $cwd" : "must have explicit folder");
2215   g_free (folder);
2216
2217   /* Unmap; folder should be set */
2218
2219   gtk_widget_hide (window);
2220   wait_for_idle ();
2221   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
2222
2223   if (must_have_cwd)
2224     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2225   else
2226     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2227
2228   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, unmapped, %s",
2229             get_action_name (action),
2230             use_dialog,
2231             set_folder_on_dialog,
2232             must_have_cwd ? "must have $cwd" : "must have explicit folder");
2233   g_free (folder);
2234
2235   /* Re-map; folder should be set */
2236
2237   gtk_widget_show_now (window);
2238   folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button));
2239
2240   if (must_have_cwd)
2241     passed = passed && (g_strcmp0 (folder, current_working_dir) == 0);
2242   else
2243     passed = passed && (g_strcmp0 (folder, g_get_home_dir()) == 0);
2244   wait_for_idle ();
2245   log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, re-mapped, %s",
2246             get_action_name (action),
2247             use_dialog,
2248             set_folder_on_dialog,
2249             must_have_cwd ? "must have $cwd" : "must have explicit folder");
2250   g_free (folder);
2251
2252   g_free (current_working_dir);
2253
2254   gtk_widget_destroy (window);
2255
2256   return passed;
2257 }
2258
2259 static void
2260 test_button_folder_states (void)
2261 {
2262   /* GtkFileChooserButton only supports OPEN and SELECT_FOLDER */
2263   static const GtkFileChooserAction actions_to_test[] = {
2264     GTK_FILE_CHOOSER_ACTION_OPEN,
2265     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
2266   };
2267   gboolean passed;
2268   int i;
2269
2270   passed = TRUE;
2271
2272   for (i = 0; i < G_N_ELEMENTS (actions_to_test); i++)
2273     {
2274       passed = passed && test_button_folder_states_for_action (actions_to_test[i], FALSE, FALSE);
2275       g_assert (passed);
2276       passed = passed && test_button_folder_states_for_action (actions_to_test[i], TRUE, FALSE);
2277       g_assert (passed);
2278       passed = passed && test_button_folder_states_for_action (actions_to_test[i], TRUE, TRUE);
2279       g_assert (passed);
2280       log_test (passed, "test_button_folder_states(): action %s", get_action_name (actions_to_test[i]));
2281     }
2282
2283   log_test (passed, "test_button_folder_states(): all supported actions");
2284 }
2285
2286 static void
2287 test_folder_switch_and_filters (void)
2288 {
2289   gboolean passed;
2290   char *cwd;
2291   char *base_dir;
2292   GFile *cwd_file;
2293   GFile *base_dir_file;
2294   GtkWidget *dialog;
2295   GtkFileFilter *all_filter;
2296   GtkFileFilter *txt_filter;
2297   GtkFileChooserDefault *impl;
2298
2299   passed = TRUE;
2300
2301   cwd = g_get_current_dir ();
2302   base_dir = g_build_filename (cwd, "file-chooser-test-dir", NULL);
2303
2304   dialog = gtk_file_chooser_dialog_new ("Test", NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
2305                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2306                                         GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2307                                         NULL);
2308   impl = get_impl_from_dialog (dialog);
2309
2310   cwd_file = g_file_new_for_path (cwd);
2311   base_dir_file = g_file_new_for_path (base_dir);
2312
2313   passed = passed && gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
2314   g_assert (passed);
2315
2316   /* All files filter */
2317
2318   all_filter = gtk_file_filter_new ();
2319   gtk_file_filter_set_name (all_filter, "All files");
2320   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all_filter);
2321
2322   /* *.txt filter */
2323
2324   txt_filter = gtk_file_filter_new ();
2325   gtk_file_filter_set_name (all_filter, "*.txt");
2326   gtk_file_filter_add_pattern (txt_filter, "*.txt");
2327   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), txt_filter);
2328
2329   /* Test filter set */
2330
2331   gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), all_filter);
2332   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == all_filter);
2333   g_assert (passed);
2334
2335   gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), txt_filter);
2336   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
2337   log_test (passed, "test_folder_switch_and_filters(): set and get filter");
2338   g_assert (passed);
2339
2340   gtk_widget_show (dialog);
2341
2342   /* Test that filter is unchanged when we switch folders */
2343
2344   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd);
2345   sleep_in_main_loop ();
2346   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
2347   g_assert (passed);
2348
2349   gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
2350   sleep_in_main_loop ();
2351
2352   g_signal_emit_by_name (impl->browse_path_bar, "path-clicked",
2353                          cwd_file,
2354                          base_dir_file,
2355                          FALSE);
2356   sleep_in_main_loop ();
2357   passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
2358   log_test (passed, "test_folder_switch_and_filters(): filter after changing folder");
2359   g_assert (passed);
2360
2361   /* cleanups */
2362   g_free (cwd);
2363   g_free (base_dir);
2364   g_object_unref (cwd_file);
2365   g_object_unref (base_dir_file);
2366
2367   gtk_widget_destroy (dialog);
2368
2369   log_test (passed, "test_folder_switch_and_filters(): all filter tests");
2370 }
2371 #endif
2372
2373 int
2374 main (int    argc,
2375       char **argv)
2376 {
2377   /* initialize test program */
2378   gtk_test_init (&argc, &argv);
2379
2380   /* Register tests */
2381
2382   setup_file_chooser_button_tests ();
2383 #ifdef BROKEN_TESTS
2384   setup_set_filename_tests ();
2385   setup_set_current_name_tests ();
2386
2387   g_test_add_func ("/GtkFileChooser/confirm_overwrite", test_confirm_overwrite);
2388   g_test_add_func ("/GtkFileChooser/action_widgets", test_action_widgets);
2389   g_test_add_func ("/GtkFileChooser/reload", test_reload);
2390   g_test_add_func ("/GtkFileChooser/button_folder_states", test_button_folder_states);
2391   g_test_add_func ("/GtkFileChooser/folder_switch_and_filters", test_folder_switch_and_filters);
2392 #endif
2393
2394   /* run and check selected tests */
2395   return g_test_run();
2396 }