1 | /* GtkStringList tests |
2 | * |
3 | * Copyright (C) 2020, Red Hat, Inc. |
4 | * Authors: Matthias Clasen |
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 <gtk/gtk.h> |
21 | |
22 | static GQuark changes_quark; |
23 | |
24 | static char * |
25 | model_to_string (GListModel *model) |
26 | { |
27 | GtkStringList *self = GTK_STRING_LIST (ptr: model); |
28 | GString *string = g_string_new (NULL); |
29 | guint i; |
30 | |
31 | for (i = 0; i < g_list_model_get_n_items (list: model); i++) |
32 | { |
33 | if (i > 0) |
34 | g_string_append (string, val: " " ); |
35 | g_string_append_printf (string, format: "%s" , gtk_string_list_get_string (self, position: i)); |
36 | } |
37 | |
38 | return g_string_free (string, FALSE); |
39 | } |
40 | |
41 | #define assert_model(model, expected) G_STMT_START{ \ |
42 | char *s = model_to_string (G_LIST_MODEL (model)); \ |
43 | if (!g_str_equal (s, expected)) \ |
44 | g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ |
45 | #model " == " #expected, s, "==", expected); \ |
46 | g_free (s); \ |
47 | }G_STMT_END |
48 | |
49 | #define assert_changes(model, expected) G_STMT_START{ \ |
50 | GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \ |
51 | if (!g_str_equal (changes->str, expected)) \ |
52 | g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ |
53 | #model " == " #expected, changes->str, "==", expected); \ |
54 | g_string_set_size (changes, 0); \ |
55 | }G_STMT_END |
56 | |
57 | static void |
58 | items_changed (GListModel *model, |
59 | guint position, |
60 | guint removed, |
61 | guint added, |
62 | GString *changes) |
63 | { |
64 | g_assert_true (removed != 0 || added != 0); |
65 | |
66 | if (changes->len) |
67 | g_string_append (string: changes, val: ", " ); |
68 | |
69 | if (removed == 1 && added == 0) |
70 | { |
71 | g_string_append_printf (string: changes, format: "-%u" , position); |
72 | } |
73 | else if (removed == 0 && added == 1) |
74 | { |
75 | g_string_append_printf (string: changes, format: "+%u" , position); |
76 | } |
77 | else |
78 | { |
79 | g_string_append_printf (string: changes, format: "%u" , position); |
80 | if (removed > 0) |
81 | g_string_append_printf (string: changes, format: "-%u" , removed); |
82 | if (added > 0) |
83 | g_string_append_printf (string: changes, format: "+%u" , added); |
84 | } |
85 | } |
86 | |
87 | static void |
88 | free_changes (gpointer data) |
89 | { |
90 | GString *changes = data; |
91 | |
92 | /* all changes must have been checked via assert_changes() before */ |
93 | g_assert_cmpstr (changes->str, ==, "" ); |
94 | |
95 | g_string_free (string: changes, TRUE); |
96 | } |
97 | |
98 | static GtkStringList * |
99 | new_model (const char **strings) |
100 | { |
101 | GtkStringList *result; |
102 | GString *changes; |
103 | |
104 | result = gtk_string_list_new (strings); |
105 | changes = g_string_new (init: "" ); |
106 | g_object_set_qdata_full (G_OBJECT(result), quark: changes_quark, data: changes, destroy: free_changes); |
107 | g_signal_connect (result, "items-changed" , G_CALLBACK (items_changed), changes); |
108 | |
109 | return result; |
110 | } |
111 | |
112 | static void |
113 | test_string_object (void) |
114 | { |
115 | GtkStringObject *so; |
116 | |
117 | so = gtk_string_object_new (string: "Hello" ); |
118 | g_assert_cmpstr (gtk_string_object_get_string (so), ==, "Hello" ); |
119 | g_object_unref (object: so); |
120 | } |
121 | |
122 | static void |
123 | test_create_empty (void) |
124 | { |
125 | GtkStringList *list; |
126 | |
127 | list = new_model (strings: (const char *[]){ NULL }); |
128 | |
129 | g_assert_true (g_type_is_a (g_list_model_get_item_type (G_LIST_MODEL (list)), G_TYPE_OBJECT)); |
130 | |
131 | assert_model (list, "" ); |
132 | assert_changes (list, "" ); |
133 | |
134 | g_object_unref (object: list); |
135 | } |
136 | |
137 | static void |
138 | test_create_strv (void) |
139 | { |
140 | GtkStringList *list; |
141 | |
142 | list = new_model (strings: (const char *[]){ "a" , "b" , "c" , NULL }); |
143 | |
144 | assert_model (list, "a b c" ); |
145 | assert_changes (list, "" ); |
146 | |
147 | g_object_unref (object: list); |
148 | } |
149 | |
150 | static void |
151 | test_create_builder (void) |
152 | { |
153 | const char *ui = |
154 | "<interface>" |
155 | " <object class=\"GtkStringList\" id=\"list\">" |
156 | " <items>" |
157 | " <item translatable=\"yes\" context=\"ctx\" comments=\"none\">a</item>" |
158 | " <item>b</item>" |
159 | " <item>c</item>" |
160 | " </items>" |
161 | " </object>" |
162 | "</interface>" ; |
163 | GtkBuilder *builder; |
164 | GtkStringList *list; |
165 | |
166 | builder = gtk_builder_new_from_string (string: ui, length: -1); |
167 | list = GTK_STRING_LIST (ptr: gtk_builder_get_object (builder, name: "list" )); |
168 | assert_model (list, "a b c" ); |
169 | |
170 | g_object_unref (object: builder); |
171 | } |
172 | |
173 | static void |
174 | test_get_string (void) |
175 | { |
176 | GtkStringList *list; |
177 | |
178 | list = new_model (strings: (const char *[]){ "a" , "b" , "c" , NULL }); |
179 | |
180 | assert_model (list, "a b c" ); |
181 | |
182 | g_assert_cmpstr (gtk_string_list_get_string (list, 0), ==, "a" ); |
183 | g_assert_cmpstr (gtk_string_list_get_string (list, 1), ==, "b" ); |
184 | g_assert_cmpstr (gtk_string_list_get_string (list, 2), ==, "c" ); |
185 | g_assert_null (gtk_string_list_get_string (list, 3)); |
186 | |
187 | g_object_unref (object: list); |
188 | } |
189 | |
190 | static void |
191 | test_splice (void) |
192 | { |
193 | GtkStringList *list; |
194 | |
195 | list = new_model (strings: (const char *[]){ "a" , "b" , "c" , "d" , "e" , NULL }); |
196 | |
197 | assert_model (list, "a b c d e" ); |
198 | |
199 | gtk_string_list_splice (self: list, position: 2, n_removals: 2, additions: (const char *[]){ "x" , "y" , "z" , NULL }); |
200 | |
201 | assert_model (list, "a b x y z e" ); |
202 | assert_changes (list, "2-2+3" ); |
203 | |
204 | g_object_unref (object: list); |
205 | } |
206 | |
207 | static void |
208 | test_add_remove (void) |
209 | { |
210 | GtkStringList *list; |
211 | |
212 | list = new_model (strings: (const char *[]){ "a" , "b" , "c" , "d" , "e" , NULL }); |
213 | |
214 | assert_model (list, "a b c d e" ); |
215 | |
216 | gtk_string_list_remove (self: list, position: 2); |
217 | |
218 | assert_model (list, "a b d e" ); |
219 | assert_changes (list, "-2" ); |
220 | |
221 | gtk_string_list_append (self: list, string: "x" ); |
222 | |
223 | assert_model (list, "a b d e x" ); |
224 | assert_changes (list, "+4" ); |
225 | |
226 | g_object_unref (object: list); |
227 | } |
228 | |
229 | static void |
230 | test_take (void) |
231 | { |
232 | GtkStringList *list; |
233 | |
234 | list = new_model (strings: (const char *[]){ NULL }); |
235 | |
236 | assert_model (list, "" ); |
237 | |
238 | gtk_string_list_take (self: list, string: g_strdup_printf (format: "%d dollars" , (int)1e6)); |
239 | assert_model (list, "1000000 dollars" ); |
240 | assert_changes (list, "+0" ); |
241 | |
242 | g_object_unref (object: list); |
243 | } |
244 | |
245 | int |
246 | main (int argc, char *argv[]) |
247 | { |
248 | (g_test_init) (argc: &argc, argv: &argv, NULL); |
249 | |
250 | changes_quark = g_quark_from_static_string (string: "What did I see? Can I believe what I saw?" ); |
251 | |
252 | g_test_add_func (testpath: "/stringobject/basic" , test_func: test_string_object); |
253 | g_test_add_func (testpath: "/stringlist/create/empty" , test_func: test_create_empty); |
254 | g_test_add_func (testpath: "/stringlist/create/strv" , test_func: test_create_strv); |
255 | g_test_add_func (testpath: "/stringlist/create/builder" , test_func: test_create_builder); |
256 | g_test_add_func (testpath: "/stringlist/get_string" , test_func: test_get_string); |
257 | g_test_add_func (testpath: "/stringlist/splice" , test_func: test_splice); |
258 | g_test_add_func (testpath: "/stringlist/add_remove" , test_func: test_add_remove); |
259 | g_test_add_func (testpath: "/stringlist/take" , test_func: test_take); |
260 | |
261 | return g_test_run (); |
262 | } |
263 | |