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
26 static guint
get(GListModel * model,guint position)27 get (GListModel *model,
28 guint position)
29 {
30 GObject *object = g_list_model_get_item (model, position);
31 guint ret;
32 g_assert_nonnull (object);
33 ret = GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark));
34 g_object_unref (object);
35 return ret;
36 }
37
38 static char *
get_string(gpointer object)39 get_string (gpointer object)
40 {
41 return g_strdup_printf ("%u", GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark)));
42 }
43
44 static void
append_digit(GString * s,guint digit)45 append_digit (GString *s,
46 guint digit)
47 {
48 static const char *names[10] = { NULL, "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
49
50 if (digit == 0)
51 return;
52
53 g_assert_cmpint (digit, <, 10);
54
55 if (s->len)
56 g_string_append_c (s, ' ');
57 g_string_append (s, names[digit]);
58 }
59
60 static void
append_below_thousand(GString * s,guint n)61 append_below_thousand (GString *s,
62 guint n)
63 {
64 if (n >= 100)
65 {
66 append_digit (s, n / 100);
67 g_string_append (s, " hundred");
68 n %= 100;
69 }
70
71 if (n >= 20)
72 {
73 const char *names[10] = { NULL, NULL, "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
74 if (s->len)
75 g_string_append_c (s, ' ');
76 g_string_append (s, names [n / 10]);
77 n %= 10;
78 }
79
80 if (n >= 10)
81 {
82 const char *names[10] = { "ten", "eleven", "twelve", "thirteen", "fourteen",
83 "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
84 if (s->len)
85 g_string_append_c (s, ' ');
86 g_string_append (s, names [n - 10]);
87 }
88 else
89 {
90 append_digit (s, n);
91 }
92 }
93
94 static char *
get_spelled_out(gpointer object)95 get_spelled_out (gpointer object)
96 {
97 guint n = GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark));
98 GString *s;
99
100 g_assert_cmpint (n, <, 1000000);
101
102 if (n == 0)
103 return g_strdup ("Zero");
104
105 s = g_string_new (NULL);
106
107 if (n >= 1000)
108 {
109 append_below_thousand (s, n / 1000);
110 g_string_append (s, " thousand");
111 n %= 1000;
112 }
113
114 append_below_thousand (s, n);
115
116 /* Capitalize first letter so we can do case-sensitive matching */
117 s->str[0] = g_ascii_toupper (s->str[0]);
118
119 return g_string_free (s, FALSE);
120 }
121
122 static char *
model_to_string(GListModel * model)123 model_to_string (GListModel *model)
124 {
125 GString *string = g_string_new (NULL);
126 guint i;
127
128 for (i = 0; i < g_list_model_get_n_items (model); i++)
129 {
130 if (i > 0)
131 g_string_append (string, " ");
132 g_string_append_printf (string, "%u", get (model, i));
133 }
134
135 return g_string_free (string, FALSE);
136 }
137
138 static GListStore *
139 new_store (guint start,
140 guint end,
141 guint step);
142
143 static void
add(GListStore * store,guint number)144 add (GListStore *store,
145 guint number)
146 {
147 GObject *object;
148
149 /* 0 cannot be differentiated from NULL, so don't use it */
150 g_assert_cmpint (number, !=, 0);
151
152 object = g_object_new (G_TYPE_OBJECT, NULL);
153 g_object_set_qdata (object, number_quark, GUINT_TO_POINTER (number));
154 g_list_store_append (store, object);
155 g_object_unref (object);
156 }
157
158 #define assert_model(model, expected) G_STMT_START{ \
159 char *s = model_to_string (G_LIST_MODEL (model)); \
160 if (!g_str_equal (s, expected)) \
161 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
162 #model " == " #expected, s, "==", expected); \
163 g_free (s); \
164 }G_STMT_END
165
166 static GListStore *
new_empty_store(void)167 new_empty_store (void)
168 {
169 return g_list_store_new (G_TYPE_OBJECT);
170 }
171
172 static GListStore *
new_store(guint start,guint end,guint step)173 new_store (guint start,
174 guint end,
175 guint step)
176 {
177 GListStore *store = new_empty_store ();
178 guint i;
179
180 for (i = start; i <= end; i += step)
181 add (store, i);
182
183 return store;
184 }
185
186 static GtkFilterListModel *
new_model(guint size,GtkFilter * filter)187 new_model (guint size,
188 GtkFilter *filter)
189 {
190 GtkFilterListModel *result;
191
192 result = gtk_filter_list_model_new (g_object_ref (G_LIST_MODEL (new_store (1, size, 1))), g_object_ref (filter));
193
194 return result;
195 }
196
197 static gboolean
divisible_by(gpointer item,gpointer data)198 divisible_by (gpointer item,
199 gpointer data)
200 {
201 return GPOINTER_TO_UINT (g_object_get_qdata (item, number_quark)) % GPOINTER_TO_UINT (data) == 0;
202 }
203
204 static void
test_simple(void)205 test_simple (void)
206 {
207 GtkFilterListModel *model;
208 GtkFilter *filter;
209
210 filter = GTK_FILTER (gtk_custom_filter_new (divisible_by, GUINT_TO_POINTER (3), NULL));
211 model = new_model (20, filter);
212 g_object_unref (filter);
213 assert_model (model, "3 6 9 12 15 18");
214 g_object_unref (model);
215 }
216
217 static void
test_any_simple(void)218 test_any_simple (void)
219 {
220 GtkFilterListModel *model;
221 GtkFilter *any, *filter1, *filter2;
222 gpointer item;
223
224 any = GTK_FILTER (gtk_any_filter_new ());
225 filter1 = GTK_FILTER (gtk_custom_filter_new (divisible_by, GUINT_TO_POINTER (3), NULL));
226 filter2 = GTK_FILTER (gtk_custom_filter_new (divisible_by, GUINT_TO_POINTER (5), NULL));
227
228 model = new_model (20, any);
229 assert_model (model, "");
230
231 gtk_multi_filter_append (GTK_MULTI_FILTER (any), filter1);
232 assert_model (model, "3 6 9 12 15 18");
233
234 gtk_multi_filter_append (GTK_MULTI_FILTER (any), filter2);
235 assert_model (model, "3 5 6 9 10 12 15 18 20");
236
237 g_assert_true (g_list_model_get_item_type (G_LIST_MODEL (any)) == GTK_TYPE_FILTER);
238 g_assert_cmpuint (2, ==, g_list_model_get_n_items (G_LIST_MODEL (any)));
239 item = g_list_model_get_item (G_LIST_MODEL (any), 1);
240 g_assert_true (GTK_FILTER (item) == filter2);
241 g_object_unref (item);
242
243 gtk_multi_filter_remove (GTK_MULTI_FILTER (any), 0);
244 assert_model (model, "5 10 15 20");
245
246 /* doesn't exist */
247 gtk_multi_filter_remove (GTK_MULTI_FILTER (any), 10);
248 assert_model (model, "5 10 15 20");
249
250 gtk_multi_filter_remove (GTK_MULTI_FILTER (any), 0);
251 assert_model (model, "");
252
253 g_object_unref (model);
254 g_object_unref (any);
255 }
256
257 static void
test_string_simple(void)258 test_string_simple (void)
259 {
260 GtkFilterListModel *model;
261 GtkFilter *filter;
262
263 filter = GTK_FILTER (gtk_string_filter_new (
264 gtk_cclosure_expression_new (G_TYPE_STRING,
265 NULL,
266 0, NULL,
267 G_CALLBACK (get_string),
268 NULL, NULL)));
269
270 model = new_model (20, filter);
271 assert_model (model, "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20");
272
273 gtk_string_filter_set_search (GTK_STRING_FILTER (filter), "1");
274 assert_model (model, "1 10 11 12 13 14 15 16 17 18 19");
275
276 g_object_unref (model);
277 g_object_unref (filter);
278 }
279
280 static void
test_string_properties(void)281 test_string_properties (void)
282 {
283 GtkFilterListModel *model;
284 GtkFilter *filter;
285 GtkExpression *expr;
286
287 expr = gtk_cclosure_expression_new (G_TYPE_STRING,
288 NULL,
289 0, NULL,
290 G_CALLBACK (get_spelled_out),
291 NULL, NULL);
292 filter = GTK_FILTER (gtk_string_filter_new (expr));
293 g_assert_true (expr == gtk_string_filter_get_expression (GTK_STRING_FILTER (filter)));
294
295 model = new_model (1000, filter);
296 gtk_string_filter_set_search (GTK_STRING_FILTER (filter), "thirte");
297 assert_model (model, "13 113 213 313 413 513 613 713 813 913");
298
299 gtk_string_filter_set_search (GTK_STRING_FILTER (filter), "thirteen");
300 assert_model (model, "13 113 213 313 413 513 613 713 813 913");
301
302 gtk_string_filter_set_ignore_case (GTK_STRING_FILTER (filter), FALSE);
303 assert_model (model, "113 213 313 413 513 613 713 813 913");
304
305 gtk_string_filter_set_search (GTK_STRING_FILTER (filter), "Thirteen");
306 assert_model (model, "13");
307
308 gtk_string_filter_set_match_mode (GTK_STRING_FILTER (filter), GTK_STRING_FILTER_MATCH_MODE_PREFIX);
309 assert_model (model, "13");
310
311 gtk_string_filter_set_match_mode (GTK_STRING_FILTER (filter), GTK_STRING_FILTER_MATCH_MODE_EXACT);
312 assert_model (model, "13");
313
314 gtk_string_filter_set_ignore_case (GTK_STRING_FILTER (filter), TRUE);
315 assert_model (model, "13");
316
317 gtk_string_filter_set_match_mode (GTK_STRING_FILTER (filter), GTK_STRING_FILTER_MATCH_MODE_PREFIX);
318 assert_model (model, "13");
319
320 gtk_string_filter_set_match_mode (GTK_STRING_FILTER (filter), GTK_STRING_FILTER_MATCH_MODE_SUBSTRING);
321 assert_model (model, "13 113 213 313 413 513 613 713 813 913");
322
323 g_object_unref (model);
324 g_object_unref (filter);
325 }
326
327 static void
test_bool_simple(void)328 test_bool_simple (void)
329 {
330 GtkFilterListModel *model;
331 GtkExpression *expr;
332 GtkFilter *filter;
333
334 filter = GTK_FILTER (gtk_bool_filter_new (
335 gtk_cclosure_expression_new (G_TYPE_BOOLEAN,
336 NULL,
337 0, NULL,
338 G_CALLBACK (divisible_by),
339 GUINT_TO_POINTER (3), NULL)));
340 model = new_model (20, filter);
341 assert_model (model, "3 6 9 12 15 18");
342
343 gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), TRUE);
344 g_assert_true (gtk_bool_filter_get_invert (GTK_BOOL_FILTER (filter)));
345 assert_model (model, "1 2 4 5 7 8 10 11 13 14 16 17 19 20");
346
347 gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), FALSE);
348 g_assert_false (gtk_bool_filter_get_invert (GTK_BOOL_FILTER (filter)));
349 assert_model (model, "3 6 9 12 15 18");
350
351 expr = gtk_cclosure_expression_new (G_TYPE_BOOLEAN,
352 NULL,
353 0, NULL,
354 G_CALLBACK (divisible_by),
355 GUINT_TO_POINTER (5), NULL);
356 gtk_bool_filter_set_expression (GTK_BOOL_FILTER (filter), expr);
357 g_assert_true (expr == gtk_bool_filter_get_expression (GTK_BOOL_FILTER (filter)));
358 gtk_expression_unref (expr);
359 assert_model (model, "5 10 15 20");
360
361 gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), TRUE);
362 assert_model (model, "1 2 3 4 6 7 8 9 11 12 13 14 16 17 18 19");
363
364 gtk_bool_filter_set_expression (GTK_BOOL_FILTER (filter), NULL);
365 assert_model (model, "");
366
367 gtk_bool_filter_set_invert (GTK_BOOL_FILTER (filter), FALSE);
368 assert_model (model, "");
369
370 g_object_unref (filter);
371 g_object_unref (model);
372 }
373
374 static void
test_every_dispose(void)375 test_every_dispose (void)
376 {
377 GtkFilter *filter, *filter1, *filter2;
378
379 filter = GTK_FILTER (gtk_every_filter_new ());
380
381 filter1 = GTK_FILTER (gtk_custom_filter_new (divisible_by, GUINT_TO_POINTER (3), NULL));
382 filter2 = GTK_FILTER (gtk_custom_filter_new (divisible_by, GUINT_TO_POINTER (5), NULL));
383
384 g_object_ref (filter1);
385 g_object_ref (filter2);
386
387 gtk_multi_filter_append (GTK_MULTI_FILTER (filter), filter1);
388 gtk_multi_filter_append (GTK_MULTI_FILTER (filter), filter2);
389
390 g_object_unref (filter);
391
392 g_object_unref (filter1);
393 g_object_unref (filter2);
394 }
395
396 int
main(int argc,char * argv[])397 main (int argc, char *argv[])
398 {
399 (g_test_init) (&argc, &argv, NULL);
400 setlocale (LC_ALL, "C");
401
402 number_quark = g_quark_from_static_string ("Hell and fire was spawned to be released.");
403
404 g_test_add_func ("/filter/simple", test_simple);
405 g_test_add_func ("/filter/any/simple", test_any_simple);
406 g_test_add_func ("/filter/string/simple", test_string_simple);
407 g_test_add_func ("/filter/string/properties", test_string_properties);
408 g_test_add_func ("/filter/bool/simple", test_bool_simple);
409 g_test_add_func ("/filter/every/dispose", test_every_dispose);
410
411 return g_test_run ();
412 }
413