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
24static GQuark number_quark;
25static GQuark changes_quark;
26
27static guint
28get (GListModel *model,
29 guint position)
30{
31 GObject *object = g_list_model_get_item (list: model, position);
32 guint number;
33 g_assert_nonnull (object);
34 number = GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark));
35 g_object_unref (object);
36 return number;
37}
38
39static char *
40model_to_string (GListModel *model)
41{
42 GString *string = g_string_new (NULL);
43 guint i;
44
45 for (i = 0; i < g_list_model_get_n_items (list: model); i++)
46 {
47 if (i > 0)
48 g_string_append (string, val: " ");
49 g_string_append_printf (string, format: "%u", get (model, position: i));
50 }
51
52 return g_string_free (string, FALSE);
53}
54
55static GListStore *
56new_store (guint start,
57 guint end,
58 guint step);
59
60#if 0
61static void
62splice (GListStore *store,
63 guint pos,
64 guint removed,
65 guint *numbers,
66 guint added)
67{
68 GObject *objects[added];
69 guint i;
70
71 for (i = 0; i < added; i++)
72 {
73 /* 0 cannot be differentiated from NULL, so don't use it */
74 g_assert_true (numbers[i] != 0);
75 objects[i] = g_object_new (G_TYPE_OBJECT, NULL);
76 g_object_set_qdata (objects[i], number_quark, GUINT_TO_POINTER (numbers[i]));
77 }
78
79 g_list_store_splice (store, pos, removed, (gpointer *) objects, added);
80
81 for (i = 0; i < added; i++)
82 g_object_unref (objects[i]);
83}
84#endif
85
86static void
87add (GListStore *store,
88 guint number)
89{
90 GObject *object;
91
92 /* 0 cannot be differentiated from NULL, so don't use it */
93 g_assert_cmpint (number, !=, 0);
94
95 object = g_object_new (G_TYPE_OBJECT, NULL);
96 g_object_set_qdata (object, quark: number_quark, GUINT_TO_POINTER (number));
97 g_list_store_append (store, item: object);
98 g_object_unref (object);
99}
100
101#define assert_model(model, expected) G_STMT_START{ \
102 char *s = model_to_string (G_LIST_MODEL (model)); \
103 if (!g_str_equal (s, expected)) \
104 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
105 #model " == " #expected, s, "==", expected); \
106 g_free (s); \
107}G_STMT_END
108
109#define assert_changes(model, expected) G_STMT_START{ \
110 GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \
111 if (!g_str_equal (changes->str, expected)) \
112 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
113 #model " == " #expected, changes->str, "==", expected); \
114 g_string_set_size (changes, 0); \
115}G_STMT_END
116
117static GListStore *
118new_empty_store (void)
119{
120 return g_list_store_new (G_TYPE_OBJECT);
121}
122
123static GListStore *
124new_store (guint start,
125 guint end,
126 guint step)
127{
128 GListStore *store = new_empty_store ();
129 guint i;
130
131 for (i = start; i <= end; i += step)
132 add (store, number: i);
133
134 return store;
135}
136
137static void
138items_changed (GListModel *model,
139 guint position,
140 guint removed,
141 guint added,
142 GString *changes)
143{
144 g_assert_true (removed != 0 || added != 0);
145
146 if (changes->len)
147 g_string_append (string: changes, val: ", ");
148
149 if (removed == 1 && added == 0)
150 {
151 g_string_append_printf (string: changes, format: "-%u", position);
152 }
153 else if (removed == 0 && added == 1)
154 {
155 g_string_append_printf (string: changes, format: "+%u", position);
156 }
157 else
158 {
159 g_string_append_printf (string: changes, format: "%u", position);
160 if (removed > 0)
161 g_string_append_printf (string: changes, format: "-%u", removed);
162 if (added > 0)
163 g_string_append_printf (string: changes, format: "+%u", added);
164 }
165}
166
167static void
168free_changes (gpointer data)
169{
170 GString *changes = data;
171
172 /* all changes must have been checked via assert_changes() before */
173 g_assert_cmpstr (changes->str, ==, "");
174
175 g_string_free (string: changes, TRUE);
176}
177
178static gpointer
179map_multiply (gpointer item,
180 gpointer factor)
181{
182 GObject *object;
183 guint num;
184
185 object = g_object_new (G_TYPE_OBJECT, NULL);
186 num = GPOINTER_TO_UINT (g_object_get_qdata (item, number_quark));
187 g_object_set_qdata (object, quark: number_quark, GUINT_TO_POINTER (GPOINTER_TO_UINT (factor) * num));
188 g_object_unref (object: item);
189
190 return object;
191}
192
193static GtkMapListModel *
194new_model (GListStore *store)
195{
196 GtkMapListModel *result;
197 GString *changes;
198
199 if (store)
200 g_object_ref (store);
201 result = gtk_map_list_model_new (model: G_LIST_MODEL (ptr: store), map_func: map_multiply, GUINT_TO_POINTER (2), NULL);
202 changes = g_string_new (init: "");
203 g_object_set_qdata_full (G_OBJECT(result), quark: changes_quark, data: changes, destroy: free_changes);
204 g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes);
205
206 return result;
207}
208
209static void
210test_create_empty (void)
211{
212 GtkMapListModel *map;
213
214 map = new_model (NULL);
215 assert_model (map, "");
216 assert_changes (map, "");
217
218 g_object_unref (object: map);
219}
220
221static void
222test_create (void)
223{
224 GtkMapListModel *map;
225 GListStore *store;
226
227 store = new_store (start: 1, end: 5, step: 1);
228 map = new_model (store);
229 assert_model (map, "2 4 6 8 10");
230 assert_changes (map, "");
231
232 g_object_unref (object: store);
233 assert_model (map, "2 4 6 8 10");
234 assert_changes (map, "");
235
236 g_object_unref (object: map);
237}
238
239static void
240test_set_model (void)
241{
242 GtkMapListModel *map;
243 GListStore *store;
244
245 map = new_model (NULL);
246 assert_model (map, "");
247 assert_changes (map, "");
248
249 store = new_store (start: 1, end: 5, step: 1);
250 gtk_map_list_model_set_model (self: map, model: G_LIST_MODEL (ptr: store));
251 assert_model (map, "2 4 6 8 10");
252 assert_changes (map, "0+5");
253
254 gtk_map_list_model_set_model (self: map, NULL);
255 assert_model (map, "");
256 assert_changes (map, "0-5");
257
258 g_object_unref (object: store);
259 g_object_unref (object: map);
260}
261
262static void
263test_set_map_func (void)
264{
265 GtkMapListModel *map;
266 GListStore *store;
267
268 store = new_store (start: 1, end: 5, step: 1);
269 map = new_model (store);
270 assert_model (map, "2 4 6 8 10");
271 assert_changes (map, "");
272
273 gtk_map_list_model_set_map_func (self: map, map_func: map_multiply, GUINT_TO_POINTER (3), NULL);
274 assert_model (map, "3 6 9 12 15");
275 assert_changes (map, "0-5+5");
276
277 gtk_map_list_model_set_map_func (self: map, NULL, NULL, NULL);
278 assert_model (map, "1 2 3 4 5");
279 assert_changes (map, "0-5+5");
280
281 gtk_map_list_model_set_map_func (self: map, map_func: map_multiply, GUINT_TO_POINTER (2), NULL);
282 assert_model (map, "2 4 6 8 10");
283 assert_changes (map, "0-5+5");
284
285 g_object_unref (object: store);
286 g_object_unref (object: map);
287}
288
289int
290main (int argc, char *argv[])
291{
292 (g_test_init) (argc: &argc, argv: &argv, NULL);
293 setlocale (LC_ALL, locale: "C");
294
295 number_quark = g_quark_from_static_string (string: "Hell and fire was spawned to be released.");
296 changes_quark = g_quark_from_static_string (string: "What did I see? Can I believe what I saw?");
297
298 g_test_add_func (testpath: "/maplistmodel/create_empty", test_func: test_create_empty);
299 g_test_add_func (testpath: "/maplistmodel/create", test_func: test_create);
300 g_test_add_func (testpath: "/maplistmodel/set-model", test_func: test_set_model);
301 g_test_add_func (testpath: "/maplistmodel/set-map-func", test_func: test_set_map_func);
302
303 return g_test_run ();
304}
305

source code of gtk/testsuite/gtk/maplistmodel.c