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;
25
26static guint
27get (GListModel *model,
28 guint position)
29{
30 GObject *object = g_list_model_get_item (list: 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
38static char *
39get_string (gpointer object)
40{
41 return g_strdup_printf (format: "%u", GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark)));
42}
43
44static void
45append_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 (string: s, val: names[digit]);
58}
59
60static void
61append_below_thousand (GString *s,
62 guint n)
63{
64 if (n >= 100)
65 {
66 append_digit (s, digit: n / 100);
67 g_string_append (string: s, val: " 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 (string: s, val: 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 (string: s, val: names [n - 10]);
87 }
88 else
89 {
90 append_digit (s, digit: n);
91 }
92}
93
94static char *
95get_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 (str: "Zero");
104
105 s = g_string_new (NULL);
106
107 if (n >= 1000)
108 {
109 append_below_thousand (s, n: n / 1000);
110 g_string_append (string: s, val: " 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 (c: s->str[0]);
118
119 return g_string_free (string: s, FALSE);
120}
121
122static char *
123model_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 (list: model); i++)
129 {
130 if (i > 0)
131 g_string_append (string, val: " ");
132 g_string_append_printf (string, format: "%u", get (model, position: i));
133 }
134
135 return g_string_free (string, FALSE);
136}
137
138static GListStore *
139new_store (guint start,
140 guint end,
141 guint step);
142
143static void
144add (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, quark: number_quark, GUINT_TO_POINTER (number));
154 g_list_store_append (store, item: 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
166static GListStore *
167new_empty_store (void)
168{
169 return g_list_store_new (G_TYPE_OBJECT);
170}
171
172static GListStore *
173new_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, number: i);
182
183 return store;
184}
185
186static GtkFilterListModel *
187new_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
197static gboolean
198divisible_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
204static void
205test_simple (void)
206{
207 GtkFilterListModel *model;
208 GtkFilter *filter;
209
210 filter = GTK_FILTER (ptr: gtk_custom_filter_new (match_func: divisible_by, GUINT_TO_POINTER (3), NULL));
211 model = new_model (size: 20, filter);
212 g_object_unref (object: filter);
213 assert_model (model, "3 6 9 12 15 18");
214 g_object_unref (object: model);
215}
216
217static void
218test_any_simple (void)
219{
220 GtkFilterListModel *model;
221 GtkFilter *any, *filter1, *filter2;
222 gpointer item;
223
224 any = GTK_FILTER (ptr: gtk_any_filter_new ());
225 filter1 = GTK_FILTER (ptr: gtk_custom_filter_new (match_func: divisible_by, GUINT_TO_POINTER (3), NULL));
226 filter2 = GTK_FILTER (ptr: gtk_custom_filter_new (match_func: divisible_by, GUINT_TO_POINTER (5), NULL));
227
228 model = new_model (size: 20, filter: any);
229 assert_model (model, "");
230
231 gtk_multi_filter_append (self: GTK_MULTI_FILTER (ptr: any), filter: filter1);
232 assert_model (model, "3 6 9 12 15 18");
233
234 gtk_multi_filter_append (self: GTK_MULTI_FILTER (ptr: any), filter: 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 (list: G_LIST_MODEL (ptr: any), position: 1);
240 g_assert_true (GTK_FILTER (item) == filter2);
241 g_object_unref (object: item);
242
243 gtk_multi_filter_remove (self: GTK_MULTI_FILTER (ptr: any), position: 0);
244 assert_model (model, "5 10 15 20");
245
246 /* doesn't exist */
247 gtk_multi_filter_remove (self: GTK_MULTI_FILTER (ptr: any), position: 10);
248 assert_model (model, "5 10 15 20");
249
250 gtk_multi_filter_remove (self: GTK_MULTI_FILTER (ptr: any), position: 0);
251 assert_model (model, "");
252
253 g_object_unref (object: model);
254 g_object_unref (object: any);
255}
256
257static void
258test_string_simple (void)
259{
260 GtkFilterListModel *model;
261 GtkFilter *filter;
262
263 filter = GTK_FILTER (ptr: gtk_string_filter_new (
264 expression: gtk_cclosure_expression_new (G_TYPE_STRING,
265 NULL,
266 n_params: 0, NULL,
267 G_CALLBACK (get_string),
268 NULL, NULL)));
269
270 model = new_model (size: 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 (self: GTK_STRING_FILTER (ptr: filter), search: "1");
274 assert_model (model, "1 10 11 12 13 14 15 16 17 18 19");
275
276 g_object_unref (object: model);
277 g_object_unref (object: filter);
278}
279
280static void
281test_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 n_params: 0, NULL,
290 G_CALLBACK (get_spelled_out),
291 NULL, NULL);
292 filter = GTK_FILTER (ptr: gtk_string_filter_new (expression: expr));
293 g_assert_true (expr == gtk_string_filter_get_expression (GTK_STRING_FILTER (filter)));
294
295 model = new_model (size: 1000, filter);
296 gtk_string_filter_set_search (self: GTK_STRING_FILTER (ptr: filter), search: "thirte");
297 assert_model (model, "13 113 213 313 413 513 613 713 813 913");
298
299 gtk_string_filter_set_search (self: GTK_STRING_FILTER (ptr: filter), search: "thirteen");
300 assert_model (model, "13 113 213 313 413 513 613 713 813 913");
301
302 gtk_string_filter_set_ignore_case (self: GTK_STRING_FILTER (ptr: filter), FALSE);
303 assert_model (model, "113 213 313 413 513 613 713 813 913");
304
305 gtk_string_filter_set_search (self: GTK_STRING_FILTER (ptr: filter), search: "Thirteen");
306 assert_model (model, "13");
307
308 gtk_string_filter_set_match_mode (self: GTK_STRING_FILTER (ptr: filter), mode: GTK_STRING_FILTER_MATCH_MODE_PREFIX);
309 assert_model (model, "13");
310
311 gtk_string_filter_set_match_mode (self: GTK_STRING_FILTER (ptr: filter), mode: GTK_STRING_FILTER_MATCH_MODE_EXACT);
312 assert_model (model, "13");
313
314 gtk_string_filter_set_ignore_case (self: GTK_STRING_FILTER (ptr: filter), TRUE);
315 assert_model (model, "13");
316
317 gtk_string_filter_set_match_mode (self: GTK_STRING_FILTER (ptr: filter), mode: GTK_STRING_FILTER_MATCH_MODE_PREFIX);
318 assert_model (model, "13");
319
320 gtk_string_filter_set_match_mode (self: GTK_STRING_FILTER (ptr: filter), mode: 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 (object: model);
324 g_object_unref (object: filter);
325}
326
327static void
328test_bool_simple (void)
329{
330 GtkFilterListModel *model;
331 GtkExpression *expr;
332 GtkFilter *filter;
333
334 filter = GTK_FILTER (ptr: gtk_bool_filter_new (
335 expression: gtk_cclosure_expression_new (G_TYPE_BOOLEAN,
336 NULL,
337 n_params: 0, NULL,
338 G_CALLBACK (divisible_by),
339 GUINT_TO_POINTER (3), NULL)));
340 model = new_model (size: 20, filter);
341 assert_model (model, "3 6 9 12 15 18");
342
343 gtk_bool_filter_set_invert (self: GTK_BOOL_FILTER (ptr: 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 (self: GTK_BOOL_FILTER (ptr: 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 n_params: 0, NULL,
354 G_CALLBACK (divisible_by),
355 GUINT_TO_POINTER (5), NULL);
356 gtk_bool_filter_set_expression (self: GTK_BOOL_FILTER (ptr: filter), expression: expr);
357 g_assert_true (expr == gtk_bool_filter_get_expression (GTK_BOOL_FILTER (filter)));
358 gtk_expression_unref (self: expr);
359 assert_model (model, "5 10 15 20");
360
361 gtk_bool_filter_set_invert (self: GTK_BOOL_FILTER (ptr: 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 (self: GTK_BOOL_FILTER (ptr: filter), NULL);
365 assert_model (model, "");
366
367 gtk_bool_filter_set_invert (self: GTK_BOOL_FILTER (ptr: filter), FALSE);
368 assert_model (model, "");
369
370 g_object_unref (object: filter);
371 g_object_unref (object: model);
372}
373
374static void
375test_every_dispose (void)
376{
377 GtkFilter *filter, *filter1, *filter2;
378
379 filter = GTK_FILTER (ptr: gtk_every_filter_new ());
380
381 filter1 = GTK_FILTER (ptr: gtk_custom_filter_new (match_func: divisible_by, GUINT_TO_POINTER (3), NULL));
382 filter2 = GTK_FILTER (ptr: gtk_custom_filter_new (match_func: divisible_by, GUINT_TO_POINTER (5), NULL));
383
384 g_object_ref (filter1);
385 g_object_ref (filter2);
386
387 gtk_multi_filter_append (self: GTK_MULTI_FILTER (ptr: filter), filter: filter1);
388 gtk_multi_filter_append (self: GTK_MULTI_FILTER (ptr: filter), filter: filter2);
389
390 g_object_unref (object: filter);
391
392 g_object_unref (object: filter1);
393 g_object_unref (object: filter2);
394}
395
396int
397main (int argc, char *argv[])
398{
399 (g_test_init) (argc: &argc, argv: &argv, NULL);
400 setlocale (LC_ALL, locale: "C");
401
402 number_quark = g_quark_from_static_string (string: "Hell and fire was spawned to be released.");
403
404 g_test_add_func (testpath: "/filter/simple", test_func: test_simple);
405 g_test_add_func (testpath: "/filter/any/simple", test_func: test_any_simple);
406 g_test_add_func (testpath: "/filter/string/simple", test_func: test_string_simple);
407 g_test_add_func (testpath: "/filter/string/properties", test_func: test_string_properties);
408 g_test_add_func (testpath: "/filter/bool/simple", test_func: test_bool_simple);
409 g_test_add_func (testpath: "/filter/every/dispose", test_func: test_every_dispose);
410
411 return g_test_run ();
412}
413

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