]> Pileus Git - ~andy/gtk/blob - tests/a11y/tree-performance.c
Use G_SOURCE_CONTINUE/REMOVE
[~andy/gtk] / tests / a11y / tree-performance.c
1 /*
2  * Copyright (C) 2011 Red Hat Inc.
3  *
4  * Author:
5  *      Matthias Clasen <mclasen@redhat.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <gtk/gtk.h>
24
25 #define N_ROWS 10000
26
27 const gchar list_ui[] =
28   "<interface>"
29   "  <object class='GtkListStore' id='liststore1'>"
30   "    <columns>"
31   "      <column type='gchararray'/>"
32   "      <column type='gchararray'/>"
33   "      <column type='gchararray'/>"
34   "      <column type='gboolean'/>"
35   "      <column type='gint'/>"
36   "      <column type='gint'/>"
37   "    </columns>"
38   "    <data>"
39   "      <row><col id='0'>One</col><col id='1'>Two</col><col id='2'>Three</col><col id='3'>True</col><col id='4'>50</col><col id='5'>50</col></row>"
40   "    </data>"
41   "  </object>"
42   "  <object class='GtkWindow' id='window1'>"
43   "    <child>"
44   "      <object class='GtkTreeView' id='treeview1'>"
45   "        <property name='visible'>True</property>"
46   "        <property name='model'>liststore1</property>"
47   "        <child>"
48   "          <object class='GtkTreeViewColumn' id='column1'>"
49   "            <property name='title' translatable='yes'>First column</property>"
50   "            <child>"
51   "              <object class='GtkCellRendererText' id='renderer1'>"
52   "              </object>"
53   "              <attributes>"
54   "                <attribute name='text'>0</attribute>"
55   "              </attributes>"
56   "            </child>"
57   "            <child>"
58   "              <object class='GtkCellRendererToggle' id='renderer2'>"
59   "              </object>"
60   "              <attributes>"
61   "                <attribute name='active'>3</attribute>"
62   "              </attributes>"
63   "            </child>"
64   "          </object>"
65   "        </child>"
66   "        <child>"
67   "          <object class='GtkTreeViewColumn' id='column2'>"
68   "            <property name='title' translatable='yes'>Second column</property>"
69   "            <child>"
70   "              <object class='GtkCellRendererText' id='renderer3'>"
71   "              </object>"
72   "              <attributes>"
73   "                <attribute name='text'>1</attribute>"
74   "              </attributes>"
75   "            </child>"
76   "            <child>"
77   "              <object class='GtkCellRendererProgress' id='renderer4'>"
78   "              </object>"
79   "              <attributes>"
80   "                <attribute name='value'>4</attribute>"
81   "              </attributes>"
82   "            </child>"
83   "          </object>"
84   "        </child>"
85   "      </object>"
86   "    </child>"
87   "  </object>"
88   "</interface>";
89
90 static void
91 walk_accessible_tree (AtkObject *accessible,
92                       gpointer   data)
93 {
94   gint *count = data;
95   gint i;
96
97   (*count)++;
98
99   for (i = 0; i < atk_object_get_n_accessible_children (accessible); i++)
100     {
101       AtkObject *child = atk_object_ref_accessible_child (accessible, i);
102       walk_accessible_tree (child, data);
103       g_object_unref (child);
104     }
105 }
106
107 static GtkWidget *
108 builder_get_toplevel (GtkBuilder *builder)
109 {
110   GSList *list, *walk;
111   GtkWidget *window = NULL;
112
113   list = gtk_builder_get_objects (builder);
114   for (walk = list; walk; walk = walk->next)
115     {
116       if (GTK_IS_WINDOW (walk->data) &&
117           gtk_widget_get_parent (walk->data) == NULL)
118         {
119           window = walk->data;
120           break;
121         }
122     }
123
124   g_slist_free (list);
125
126   return window;
127 }
128
129 static void
130 populate_list (GtkBuilder *builder)
131 {
132   GtkTreeView *tv;
133   GtkListStore *store;
134   GtkTreeIter iter;
135   gint i;
136
137   tv = (GtkTreeView *)gtk_builder_get_object (builder, "treeview1");
138   store = (GtkListStore *)gtk_tree_view_get_model (tv);
139
140   /* append a many rows */
141   for (i = 0; i < N_ROWS; i++)
142     {
143       gtk_list_store_append (store, &iter);
144       gtk_list_store_set (store, &iter, 0, "Bla", 1, "Bla bla", 2, "Bla bla bla", 3, i % 2 == 0 ? TRUE : FALSE, 4, i % 100, 5, i, -1);
145     }
146 }
147
148 static void
149 test_performance_list (void)
150 {
151   GtkBuilder *builder;
152   gdouble elapsed;
153   GtkWidget *window;
154   GError *error = NULL;
155
156   builder = gtk_builder_new ();
157   gtk_builder_add_from_string (builder, list_ui, -1, &error);
158   g_assert_no_error (error);
159   window = builder_get_toplevel (builder);
160   g_assert (window);
161
162   gtk_widget_show (window);
163
164   g_test_timer_start ();
165
166   populate_list (builder);
167
168   elapsed = g_test_timer_elapsed ();
169   g_test_minimized_result (elapsed, "large list test: %gsec", elapsed);
170   g_object_unref (builder);
171 }
172
173 static void
174 test_a11y_performance_list (void)
175 {
176   GtkBuilder *builder;
177   gdouble elapsed;
178   GtkWidget *window;
179   GError *error = NULL;
180   gint count_before;
181   gint count_after;
182
183   builder = gtk_builder_new ();
184   gtk_builder_add_from_string (builder, list_ui, -1, &error);
185   g_assert_no_error (error);
186   window = builder_get_toplevel (builder);
187   g_assert (window);
188
189   gtk_widget_show (window);
190
191   g_test_timer_start ();
192
193   /* make sure all accessibles exist */
194   count_before = 0;
195   walk_accessible_tree (gtk_widget_get_accessible (window), &count_before);
196
197   populate_list (builder);
198
199   /* for good measure, do this again */
200   count_after = 0;
201   walk_accessible_tree (gtk_widget_get_accessible (window), &count_after);
202
203   elapsed = g_test_timer_elapsed ();
204   g_test_minimized_result (elapsed, "large list with a11y: %gsec", elapsed);
205   g_object_unref (builder);
206
207   g_test_message ("%d accessibles before, %d after\n", count_before, count_after);
208 }
209
210 const gchar tree_ui[] =
211   "<interface>"
212   "  <object class='GtkTreeStore' id='treestore1'>"
213   "    <columns>"
214   "      <column type='gchararray'/>"
215   "      <column type='gchararray'/>"
216   "      <column type='gchararray'/>"
217   "      <column type='gboolean'/>"
218   "      <column type='gint'/>"
219   "      <column type='gint'/>"
220   "    </columns>"
221   "  </object>"
222   "  <object class='GtkWindow' id='window1'>"
223   "    <child>"
224   "      <object class='GtkTreeView' id='treeview1'>"
225   "        <property name='visible'>True</property>"
226   "        <property name='model'>treestore1</property>"
227   "        <child>"
228   "          <object class='GtkTreeViewColumn' id='column1'>"
229   "            <property name='title' translatable='yes'>First column</property>"
230   "            <child>"
231   "              <object class='GtkCellRendererText' id='renderer1'>"
232   "              </object>"
233   "              <attributes>"
234   "                <attribute name='text'>0</attribute>"
235   "              </attributes>"
236   "            </child>"
237   "            <child>"
238   "              <object class='GtkCellRendererToggle' id='renderer2'>"
239   "              </object>"
240   "              <attributes>"
241   "                <attribute name='active'>3</attribute>"
242   "              </attributes>"
243   "            </child>"
244   "          </object>"
245   "        </child>"
246   "        <child>"
247   "          <object class='GtkTreeViewColumn' id='column2'>"
248   "            <property name='title' translatable='yes'>Second column</property>"
249   "            <child>"
250   "              <object class='GtkCellRendererText' id='renderer3'>"
251   "              </object>"
252   "              <attributes>"
253   "                <attribute name='text'>1</attribute>"
254   "              </attributes>"
255   "            </child>"
256   "            <child>"
257   "              <object class='GtkCellRendererProgress' id='renderer4'>"
258   "              </object>"
259   "              <attributes>"
260   "                <attribute name='value'>4</attribute>"
261   "              </attributes>"
262   "            </child>"
263   "          </object>"
264   "        </child>"
265   "      </object>"
266   "    </child>"
267   "  </object>"
268   "</interface>";
269
270 static void
271 populate_tree (GtkBuilder *builder)
272 {
273   GtkTreeView *tv;
274   GtkTreeStore *store;
275   GtkTreeIter iter;
276   gint i;
277
278   tv = (GtkTreeView *)gtk_builder_get_object (builder, "treeview1");
279   store = (GtkTreeStore *)gtk_tree_view_get_model (tv);
280
281   /* append a thousand rows */
282   for (i = 0; i < N_ROWS / 3; i++)
283     {
284       gtk_tree_store_append (store, &iter, NULL);
285       gtk_tree_store_set (store, &iter, 0, "Bla", 1, "Bla bla", 2, "Bla bla bla", 3, i % 2 == 0 ? TRUE : FALSE, 4, i % 100, 5, i, -1);
286       gtk_tree_store_append (store, &iter, &iter);
287       gtk_tree_store_set (store, &iter, 0, "Bla", 1, "Bla bla", 2, "Bla bla bla", 3, i % 2 == 0 ? TRUE : FALSE, 4, i % 100, 5, i, -1);
288       gtk_tree_store_append (store, &iter, &iter);
289       gtk_tree_store_set (store, &iter, 0, "Bla", 1, "Bla bla", 2, "Bla bla bla", 3, i % 2 == 0 ? TRUE : FALSE, 4, i % 100, 5, i, -1);
290     }
291
292   gtk_tree_view_expand_all (tv);
293 }
294
295 static void
296 test_performance_tree (void)
297 {
298   GtkBuilder *builder;
299   gdouble elapsed;
300   GtkWidget *window;
301   GError *error = NULL;
302
303   builder = gtk_builder_new ();
304   gtk_builder_add_from_string (builder, tree_ui, -1, &error);
305   g_assert_no_error (error);
306   window = builder_get_toplevel (builder);
307   g_assert (window);
308
309   gtk_widget_show (window);
310
311   g_test_timer_start ();
312
313   populate_tree (builder);
314
315   elapsed = g_test_timer_elapsed ();
316   g_test_minimized_result (elapsed, "large tree test: %gsec", elapsed);
317   g_object_unref (builder);
318 }
319
320 static void
321 test_a11y_performance_tree (void)
322 {
323   GtkBuilder *builder;
324   gdouble elapsed;
325   GtkWidget *window;
326   GError *error = NULL;
327   gint count_before;
328   gint count_after;
329
330   builder = gtk_builder_new ();
331   gtk_builder_add_from_string (builder, tree_ui, -1, &error);
332   g_assert_no_error (error);
333   window = builder_get_toplevel (builder);
334   g_assert (window);
335
336   gtk_widget_show (window);
337
338   g_test_timer_start ();
339
340   /* make sure all accessibles exist */
341   count_before = 0;
342   walk_accessible_tree (gtk_widget_get_accessible (window), &count_before);
343
344   populate_tree (builder);
345
346   /* for good measure, do this again */
347   count_after = 0;
348   walk_accessible_tree (gtk_widget_get_accessible (window), &count_after);
349
350   elapsed = g_test_timer_elapsed ();
351   g_test_minimized_result (elapsed, "large tree with a11y: %gsec", elapsed);
352   g_object_unref (builder);
353
354   g_test_message ("%d accessibles before, %d after\n", count_before, count_after);
355 }
356
357 int
358 main (int argc, char *argv[])
359 {
360   gtk_test_init (&argc, &argv, NULL);
361
362   if (!g_test_perf ())
363     return 0;
364
365   g_test_add_func ("/performance/list", test_performance_list);
366   g_test_add_func ("/a11y/performance/list", test_a11y_performance_list);
367   g_test_add_func ("/performance/tree", test_performance_tree);
368   g_test_add_func ("/a11y/performance/tree", test_a11y_performance_tree);
369
370   return g_test_run ();
371 }