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 *
model_to_string(GListModel * model)25 model_to_string (GListModel *model)
26 {
27 GtkStringList *self = GTK_STRING_LIST (model);
28 GString *string = g_string_new (NULL);
29 guint i;
30
31 for (i = 0; i < g_list_model_get_n_items (model); i++)
32 {
33 if (i > 0)
34 g_string_append (string, " ");
35 g_string_append_printf (string, "%s", gtk_string_list_get_string (self, 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
items_changed(GListModel * model,guint position,guint removed,guint added,GString * changes)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 (changes, ", ");
68
69 if (removed == 1 && added == 0)
70 {
71 g_string_append_printf (changes, "-%u", position);
72 }
73 else if (removed == 0 && added == 1)
74 {
75 g_string_append_printf (changes, "+%u", position);
76 }
77 else
78 {
79 g_string_append_printf (changes, "%u", position);
80 if (removed > 0)
81 g_string_append_printf (changes, "-%u", removed);
82 if (added > 0)
83 g_string_append_printf (changes, "+%u", added);
84 }
85 }
86
87 static void
free_changes(gpointer data)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 (changes, TRUE);
96 }
97
98 static GtkStringList *
new_model(const char ** strings)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 ("");
106 g_object_set_qdata_full (G_OBJECT(result), changes_quark, changes, free_changes);
107 g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes);
108
109 return result;
110 }
111
112 static void
test_string_object(void)113 test_string_object (void)
114 {
115 GtkStringObject *so;
116
117 so = gtk_string_object_new ("Hello");
118 g_assert_cmpstr (gtk_string_object_get_string (so), ==, "Hello");
119 g_object_unref (so);
120 }
121
122 static void
test_create_empty(void)123 test_create_empty (void)
124 {
125 GtkStringList *list;
126
127 list = new_model ((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 (list);
135 }
136
137 static void
test_create_strv(void)138 test_create_strv (void)
139 {
140 GtkStringList *list;
141
142 list = new_model ((const char *[]){ "a", "b", "c", NULL });
143
144 assert_model (list, "a b c");
145 assert_changes (list, "");
146
147 g_object_unref (list);
148 }
149
150 static void
test_create_builder(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 (ui, -1);
167 list = GTK_STRING_LIST (gtk_builder_get_object (builder, "list"));
168 assert_model (list, "a b c");
169
170 g_object_unref (builder);
171 }
172
173 static void
test_get_string(void)174 test_get_string (void)
175 {
176 GtkStringList *list;
177
178 list = new_model ((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 (list);
188 }
189
190 static void
test_splice(void)191 test_splice (void)
192 {
193 GtkStringList *list;
194
195 list = new_model ((const char *[]){ "a", "b", "c", "d", "e", NULL });
196
197 assert_model (list, "a b c d e");
198
199 gtk_string_list_splice (list, 2, 2, (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 (list);
205 }
206
207 static void
test_add_remove(void)208 test_add_remove (void)
209 {
210 GtkStringList *list;
211
212 list = new_model ((const char *[]){ "a", "b", "c", "d", "e", NULL });
213
214 assert_model (list, "a b c d e");
215
216 gtk_string_list_remove (list, 2);
217
218 assert_model (list, "a b d e");
219 assert_changes (list, "-2");
220
221 gtk_string_list_append (list, "x");
222
223 assert_model (list, "a b d e x");
224 assert_changes (list, "+4");
225
226 g_object_unref (list);
227 }
228
229 static void
test_take(void)230 test_take (void)
231 {
232 GtkStringList *list;
233
234 list = new_model ((const char *[]){ NULL });
235
236 assert_model (list, "");
237
238 gtk_string_list_take (list, g_strdup_printf ("%d dollars", (int)1e6));
239 assert_model (list, "1000000 dollars");
240 assert_changes (list, "+0");
241
242 g_object_unref (list);
243 }
244
245 int
main(int argc,char * argv[])246 main (int argc, char *argv[])
247 {
248 (g_test_init) (&argc, &argv, NULL);
249
250 changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?");
251
252 g_test_add_func ("/stringobject/basic", test_string_object);
253 g_test_add_func ("/stringlist/create/empty", test_create_empty);
254 g_test_add_func ("/stringlist/create/strv", test_create_strv);
255 g_test_add_func ("/stringlist/create/builder", test_create_builder);
256 g_test_add_func ("/stringlist/get_string", test_get_string);
257 g_test_add_func ("/stringlist/splice", test_splice);
258 g_test_add_func ("/stringlist/add_remove", test_add_remove);
259 g_test_add_func ("/stringlist/take", test_take);
260
261 return g_test_run ();
262 }
263