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 | static GQuark number_quark; |
25 | static GQuark changes_quark; |
26 | |
27 | static guint |
28 | get (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 | |
39 | static char * |
40 | model_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 | |
55 | static GListStore * |
56 | new_store (guint start, |
57 | guint end, |
58 | guint step); |
59 | |
60 | #if 0 |
61 | static void |
62 | splice (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 | |
86 | static void |
87 | add (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 | |
117 | static GListStore * |
118 | new_empty_store (void) |
119 | { |
120 | return g_list_store_new (G_TYPE_OBJECT); |
121 | } |
122 | |
123 | static GListStore * |
124 | new_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 | |
137 | static void |
138 | items_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 | |
167 | static void |
168 | free_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 | |
178 | static gpointer |
179 | map_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 | |
193 | static GtkMapListModel * |
194 | new_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 | |
209 | static void |
210 | test_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 | |
221 | static void |
222 | test_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 | |
239 | static void |
240 | test_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 | |
262 | static void |
263 | test_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 | |
289 | int |
290 | main (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 | |