1 /* GtkRBTree tests.
2  *
3  * Copyright (C) 2011, Red Hat, Inc.
4  * Authors: Benjamin Otte <otte@gnome.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <locale.h>
21 
22 #include <gtk/gtk.h>
23 
24 #include "gtk/gtkpropertylookuplistmodelprivate.h"
25 
26 GQuark changes_quark;
27 
28 static char *
model_to_string(GListModel * model)29 model_to_string (GListModel *model)
30 {
31   GString *string = g_string_new (NULL);
32   gpointer item;
33   guint i;
34 
35   for (i = 0; i < g_list_model_get_n_items (model); i++)
36     {
37       if (i > 0)
38         g_string_append (string, " ");
39       item = g_list_model_get_item (model, i);
40       g_string_append_printf (string, "%s", G_OBJECT_TYPE_NAME (item));
41       g_object_unref (item);
42     }
43 
44   return g_string_free (string, FALSE);
45 }
46 
47 #define assert_model(model, expected) G_STMT_START{ \
48   char *s = model_to_string (G_LIST_MODEL (model)); \
49   if (!g_str_equal (s, expected)) \
50      g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
51          #model " == " #expected, s, "==", expected); \
52   g_free (s); \
53 }G_STMT_END
54 
55 #define assert_changes(model, expected) G_STMT_START{ \
56   GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \
57   if (!g_str_equal (changes->str, expected)) \
58      g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
59          #model " == " #expected, changes->str, "==", expected); \
60   g_string_set_size (changes, 0); \
61 }G_STMT_END
62 
63 static void
items_changed(GListModel * model,guint position,guint removed,guint added,GString * changes)64 items_changed (GListModel *model,
65                guint       position,
66                guint       removed,
67                guint       added,
68                GString    *changes)
69 {
70   g_assert_true (removed != 0 || added != 0);
71 
72   if (changes->len)
73     g_string_append (changes, ", ");
74 
75   if (removed == 1 && added == 0)
76     {
77       g_string_append_printf (changes, "-%u", position);
78     }
79   else if (removed == 0 && added == 1)
80     {
81       g_string_append_printf (changes, "+%u", position);
82     }
83   else
84     {
85       g_string_append_printf (changes, "%u", position);
86       if (removed > 0)
87         g_string_append_printf (changes, "-%u", removed);
88       if (added > 0)
89         g_string_append_printf (changes, "+%u", added);
90     }
91 }
92 
93 static void
free_changes(gpointer data)94 free_changes (gpointer data)
95 {
96   GString *changes = data;
97 
98   /* all changes must have been checked via assert_changes() before */
99   g_assert_cmpstr (changes->str, ==, "");
100 
101   g_string_free (changes, TRUE);
102 }
103 
104 static GSList *widgets = NULL;
105 
106 static GtkWidget *
create_widget_tree(void)107 create_widget_tree (void)
108 {
109   GtkWidget *window, *box, *grid, *label;
110 
111   window = gtk_window_new ();
112   widgets = g_slist_prepend (widgets, window);
113 
114   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
115   gtk_window_set_child (GTK_WINDOW (window), box);
116 
117   grid = gtk_grid_new ();
118   gtk_box_append (GTK_BOX (box), grid);
119 
120   label = gtk_label_new ("Hello World");
121   gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
122 
123   return label;
124 }
125 
126 static void
destroy_widgets(void)127 destroy_widgets (void)
128 {
129   g_slist_free_full (widgets, (GDestroyNotify) gtk_window_destroy);
130   widgets = NULL;
131 }
132 
133 static GtkPropertyLookupListModel *
new_model(gboolean fill)134 new_model (gboolean fill)
135 {
136   GtkPropertyLookupListModel *result;
137   GString *changes;
138 
139   result = gtk_property_lookup_list_model_new (GTK_TYPE_WIDGET, "parent");
140   if (fill)
141     {
142       GtkWidget *widget = create_widget_tree ();
143       gtk_property_lookup_list_model_set_object (result, widget);
144     }
145   changes = g_string_new ("");
146   g_object_set_qdata_full (G_OBJECT(result), changes_quark, changes, free_changes);
147   g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes);
148 
149   return result;
150 }
151 
152 static void
test_create_empty(void)153 test_create_empty (void)
154 {
155   GtkPropertyLookupListModel *model;
156 
157   model = new_model (FALSE);
158   assert_model (model, "");
159   assert_changes (model, "");
160 
161   g_object_unref (model);
162 }
163 
164 static void
test_create(void)165 test_create (void)
166 {
167   GtkPropertyLookupListModel *model;
168 
169   model = new_model (TRUE);
170   assert_model (model, "GtkLabel GtkGrid GtkBox GtkWindow");
171   assert_changes (model, "");
172 
173   g_object_unref (model);
174   destroy_widgets ();
175 }
176 
177 static void
test_set_object(void)178 test_set_object (void)
179 {
180   GtkPropertyLookupListModel *model;
181   GtkWidget *widget;
182 
183   widget = create_widget_tree ();
184 
185   model = new_model (FALSE);
186   gtk_property_lookup_list_model_set_object (model, widget);
187   assert_model (model, "GtkLabel GtkGrid GtkBox GtkWindow");
188   assert_changes (model, "+0");
189   g_object_unref (model);
190 
191   model = new_model (FALSE);
192   assert_model (model, "");
193   gtk_property_lookup_list_model_set_object (model, widget);
194   assert_model (model, "GtkLabel GtkGrid GtkBox GtkWindow");
195   assert_changes (model, "0+4");
196   g_object_unref (model);
197 
198   destroy_widgets ();
199 }
200 
201 static void
test_change_property(void)202 test_change_property (void)
203 {
204   GtkPropertyLookupListModel *model;
205   GtkWidget *widget, *parent, *grandparent;
206 
207   widget = create_widget_tree ();
208   parent = gtk_widget_get_parent (widget);
209   grandparent = gtk_widget_get_parent (parent);
210 
211   model = new_model (FALSE);
212   assert_model (model, ""); /* make sure the model has a definite size */
213   gtk_property_lookup_list_model_set_object (model, widget);
214   assert_model (model, "GtkLabel GtkGrid GtkBox GtkWindow");
215   assert_changes (model, "0+4");
216 
217   gtk_grid_remove (GTK_GRID (parent), widget);
218   assert_model (model, "GtkLabel");
219   assert_changes (model, "1-3");
220 
221   gtk_box_append (GTK_BOX (grandparent), widget);
222   assert_model (model, "GtkLabel GtkBox GtkWindow");
223   assert_changes (model, "1+2");
224 
225   g_object_unref (model);
226   destroy_widgets ();
227 }
228 
229 int
main(int argc,char * argv[])230 main (int argc, char *argv[])
231 {
232   gtk_test_init (&argc, &argv);
233 
234   changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?");
235 
236   g_test_add_func ("/propertylookuplistmodel/create_empty", test_create_empty);
237   g_test_add_func ("/propertylookuplistmodel/create", test_create);
238   g_test_add_func ("/propertylookuplistmodel/set-object", test_set_object);
239   g_test_add_func ("/propertylookuplistmodel/change-property", test_change_property);
240 
241   return g_test_run ();
242 }
243