1 | #include <glib.h> |
2 | |
3 | #define SIZE 50 |
4 | #define NUMBER_MIN 0000 |
5 | #define NUMBER_MAX 9999 |
6 | |
7 | |
8 | static guint32 array[SIZE]; |
9 | |
10 | |
11 | static gint |
12 | sort (gconstpointer p1, gconstpointer p2) |
13 | { |
14 | gint32 a, b; |
15 | |
16 | a = GPOINTER_TO_INT (p1); |
17 | b = GPOINTER_TO_INT (p2); |
18 | |
19 | return (a > b ? +1 : a == b ? 0 : -1); |
20 | } |
21 | |
22 | /* |
23 | * gslist sort tests |
24 | */ |
25 | static void |
26 | test_slist_sort (void) |
27 | { |
28 | GSList *slist = NULL; |
29 | gint i; |
30 | |
31 | for (i = 0; i < SIZE; i++) |
32 | slist = g_slist_append (list: slist, GINT_TO_POINTER (array[i])); |
33 | |
34 | slist = g_slist_sort (list: slist, compare_func: sort); |
35 | for (i = 0; i < SIZE - 1; i++) |
36 | { |
37 | gpointer p1, p2; |
38 | |
39 | p1 = g_slist_nth_data (list: slist, n: i); |
40 | p2 = g_slist_nth_data (list: slist, n: i+1); |
41 | |
42 | g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); |
43 | } |
44 | |
45 | g_slist_free (list: slist); |
46 | } |
47 | |
48 | static void |
49 | test_slist_sort_with_data (void) |
50 | { |
51 | GSList *slist = NULL; |
52 | gint i; |
53 | |
54 | for (i = 0; i < SIZE; i++) |
55 | slist = g_slist_append (list: slist, GINT_TO_POINTER (array[i])); |
56 | |
57 | slist = g_slist_sort_with_data (list: slist, compare_func: (GCompareDataFunc)sort, NULL); |
58 | for (i = 0; i < SIZE - 1; i++) |
59 | { |
60 | gpointer p1, p2; |
61 | |
62 | p1 = g_slist_nth_data (list: slist, n: i); |
63 | p2 = g_slist_nth_data (list: slist, n: i+1); |
64 | |
65 | g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); |
66 | } |
67 | |
68 | g_slist_free (list: slist); |
69 | } |
70 | |
71 | /* Test that the sort is stable. */ |
72 | static void |
73 | test_slist_sort_stable (void) |
74 | { |
75 | GSList *list = NULL; /* (element-type utf8) */ |
76 | GSList *copy = NULL; /* (element-type utf8) */ |
77 | gsize i; |
78 | |
79 | /* Build a test list, already ordered. */ |
80 | for (i = 0; i < SIZE; i++) |
81 | list = g_slist_append (list, data: g_strdup_printf (format: "%" G_GSIZE_FORMAT, i / 5)); |
82 | |
83 | /* Take a copy and sort it. */ |
84 | copy = g_slist_copy (list); |
85 | copy = g_slist_sort (list: copy, compare_func: (GCompareFunc) g_strcmp0); |
86 | |
87 | /* Compare the two lists, checking pointers are equal to ensure the elements |
88 | * have been kept stable. */ |
89 | for (i = 0; i < SIZE; i++) |
90 | { |
91 | gpointer p1, p2; |
92 | |
93 | p1 = g_slist_nth_data (list, n: i); |
94 | p2 = g_slist_nth_data (list, n: i); |
95 | |
96 | g_assert (p1 == p2); |
97 | } |
98 | |
99 | g_slist_free (list: copy); |
100 | g_slist_free_full (list, free_func: g_free); |
101 | } |
102 | |
103 | static void |
104 | test_slist_insert_sorted (void) |
105 | { |
106 | GSList *slist = NULL; |
107 | gint i; |
108 | |
109 | for (i = 0; i < SIZE; i++) |
110 | slist = g_slist_insert_sorted (list: slist, GINT_TO_POINTER (array[i]), func: sort); |
111 | |
112 | for (i = 0; i < SIZE - 1; i++) |
113 | { |
114 | gpointer p1, p2; |
115 | |
116 | p1 = g_slist_nth_data (list: slist, n: i); |
117 | p2 = g_slist_nth_data (list: slist, n: i+1); |
118 | |
119 | g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); |
120 | } |
121 | |
122 | g_slist_free (list: slist); |
123 | } |
124 | |
125 | static void |
126 | test_slist_insert_sorted_with_data (void) |
127 | { |
128 | GSList *slist = NULL; |
129 | gint i; |
130 | |
131 | for (i = 0; i < SIZE; i++) |
132 | slist = g_slist_insert_sorted_with_data (list: slist, |
133 | GINT_TO_POINTER (array[i]), |
134 | func: (GCompareDataFunc)sort, |
135 | NULL); |
136 | |
137 | for (i = 0; i < SIZE - 1; i++) |
138 | { |
139 | gpointer p1, p2; |
140 | |
141 | p1 = g_slist_nth_data (list: slist, n: i); |
142 | p2 = g_slist_nth_data (list: slist, n: i+1); |
143 | |
144 | g_assert (GPOINTER_TO_INT (p1) <= GPOINTER_TO_INT (p2)); |
145 | } |
146 | |
147 | g_slist_free (list: slist); |
148 | } |
149 | |
150 | static void |
151 | test_slist_reverse (void) |
152 | { |
153 | GSList *slist = NULL; |
154 | GSList *st; |
155 | gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
156 | gint i; |
157 | |
158 | for (i = 0; i < 10; i++) |
159 | slist = g_slist_append (list: slist, data: &nums[i]); |
160 | |
161 | slist = g_slist_reverse (list: slist); |
162 | |
163 | for (i = 0; i < 10; i++) |
164 | { |
165 | st = g_slist_nth (list: slist, n: i); |
166 | g_assert (*((gint*) st->data) == (9 - i)); |
167 | } |
168 | |
169 | g_slist_free (list: slist); |
170 | } |
171 | |
172 | static void |
173 | test_slist_nth (void) |
174 | { |
175 | GSList *slist = NULL; |
176 | GSList *st; |
177 | gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
178 | gint i; |
179 | |
180 | for (i = 0; i < 10; i++) |
181 | slist = g_slist_append (list: slist, data: &nums[i]); |
182 | |
183 | for (i = 0; i < 10; i++) |
184 | { |
185 | st = g_slist_nth (list: slist, n: i); |
186 | g_assert (*((gint*) st->data) == i); |
187 | } |
188 | |
189 | g_slist_free (list: slist); |
190 | } |
191 | |
192 | static void |
193 | test_slist_remove (void) |
194 | { |
195 | GSList *slist = NULL; |
196 | GSList *st; |
197 | gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
198 | gint i; |
199 | |
200 | for (i = 0; i < 10; i++) |
201 | { |
202 | slist = g_slist_append (list: slist, data: &nums[i]); |
203 | slist = g_slist_append (list: slist, data: &nums[i]); |
204 | } |
205 | |
206 | g_assert_cmpint (g_slist_length (slist), ==, 20); |
207 | |
208 | for (i = 0; i < 10; i++) |
209 | { |
210 | slist = g_slist_remove (list: slist, data: &nums[i]); |
211 | } |
212 | |
213 | g_assert_cmpint (g_slist_length (slist), ==, 10); |
214 | |
215 | for (i = 0; i < 10; i++) |
216 | { |
217 | st = g_slist_nth (list: slist, n: i); |
218 | g_assert (*((gint*) st->data) == i); |
219 | } |
220 | |
221 | g_slist_free (list: slist); |
222 | } |
223 | |
224 | static void |
225 | test_slist_remove_all (void) |
226 | { |
227 | GSList *slist = NULL; |
228 | gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
229 | gint i; |
230 | |
231 | for (i = 0; i < 10; i++) |
232 | { |
233 | slist = g_slist_append (list: slist, data: &nums[i]); |
234 | slist = g_slist_append (list: slist, data: &nums[i]); |
235 | } |
236 | |
237 | g_assert_cmpint (g_slist_length (slist), ==, 20); |
238 | |
239 | for (i = 0; i < 5; i++) |
240 | { |
241 | slist = g_slist_remove_all (list: slist, data: &nums[2 * i + 1]); |
242 | slist = g_slist_remove_all (list: slist, data: &nums[8 - 2 * i]); |
243 | } |
244 | |
245 | g_assert_cmpint (g_slist_length (slist), ==, 0); |
246 | g_assert (slist == NULL); |
247 | } |
248 | |
249 | static void |
250 | test_slist_insert (void) |
251 | { |
252 | gpointer a = "a" ; |
253 | gpointer b = "b" ; |
254 | gpointer c = "c" ; |
255 | GSList *slist = NULL; |
256 | GSList *st; |
257 | gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
258 | gint i; |
259 | |
260 | slist = g_slist_insert_before (NULL, NULL, data: &nums[1]); |
261 | slist = g_slist_insert (list: slist, data: &nums[3], position: 1); |
262 | slist = g_slist_insert (list: slist, data: &nums[4], position: -1); |
263 | slist = g_slist_insert (list: slist, data: &nums[0], position: 0); |
264 | slist = g_slist_insert (list: slist, data: &nums[5], position: 100); |
265 | slist = g_slist_insert_before (slist, NULL, data: &nums[6]); |
266 | slist = g_slist_insert_before (slist, sibling: slist->next->next, data: &nums[2]); |
267 | |
268 | slist = g_slist_insert (list: slist, data: &nums[9], position: 7); |
269 | slist = g_slist_insert (list: slist, data: &nums[8], position: 7); |
270 | slist = g_slist_insert (list: slist, data: &nums[7], position: 7); |
271 | |
272 | for (i = 0; i < 10; i++) |
273 | { |
274 | st = g_slist_nth (list: slist, n: i); |
275 | g_assert (*((gint*) st->data) == i); |
276 | } |
277 | |
278 | g_slist_free (list: slist); |
279 | |
280 | slist = g_slist_insert (NULL, data: a, position: 1); |
281 | g_assert (slist->data == a); |
282 | g_assert (slist->next == NULL); |
283 | g_slist_free (list: slist); |
284 | |
285 | slist = g_slist_append (NULL, data: a); |
286 | slist = g_slist_append (list: slist, data: b); |
287 | slist = g_slist_insert (list: slist, data: c, position: 5); |
288 | |
289 | g_assert (slist->next->next->data == c); |
290 | g_assert (slist->next->next->next == NULL); |
291 | g_slist_free (list: slist); |
292 | |
293 | slist = g_slist_append (NULL, data: a); |
294 | slist = g_slist_insert_before (slist, sibling: slist, data: b); |
295 | g_assert (slist->data == b); |
296 | g_assert (slist->next->data == a); |
297 | g_assert (slist->next->next == NULL); |
298 | g_slist_free (list: slist); |
299 | } |
300 | |
301 | static gint |
302 | find_num (gconstpointer l, gconstpointer data) |
303 | { |
304 | return *(gint*)l - GPOINTER_TO_INT(data); |
305 | } |
306 | |
307 | static void |
308 | test_slist_position (void) |
309 | { |
310 | GSList *slist = NULL; |
311 | GSList *st; |
312 | gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
313 | gint i; |
314 | |
315 | for (i = 0; i < 10; i++) |
316 | { |
317 | slist = g_slist_append (list: slist, data: &nums[i]); |
318 | } |
319 | |
320 | g_assert_cmpint (g_slist_index (slist, NULL), ==, -1); |
321 | g_assert_cmpint (g_slist_position (slist, NULL), ==, -1); |
322 | |
323 | for (i = 0; i < 10; i++) |
324 | { |
325 | g_assert_cmpint (g_slist_index (slist, &nums[i]), ==, i); |
326 | st = g_slist_find_custom (list: slist, GINT_TO_POINTER(i), func: find_num); |
327 | g_assert (st != NULL); |
328 | g_assert_cmpint (g_slist_position (slist, st), ==, i); |
329 | } |
330 | |
331 | st = g_slist_find_custom (list: slist, GINT_TO_POINTER (1000), func: find_num); |
332 | g_assert (st == NULL); |
333 | |
334 | g_slist_free (list: slist); |
335 | } |
336 | |
337 | static void |
338 | test_slist_concat (void) |
339 | { |
340 | gpointer a = "a" ; |
341 | gpointer b = "b" ; |
342 | GSList *s1, *s2, *s; |
343 | |
344 | s1 = g_slist_append (NULL, data: a); |
345 | s2 = g_slist_append (NULL, data: b); |
346 | s = g_slist_concat (list1: s1, list2: s2); |
347 | g_assert (s->data == a); |
348 | g_assert (s->next->data == b); |
349 | g_assert (s->next->next == NULL); |
350 | g_slist_free (list: s); |
351 | |
352 | s1 = g_slist_append (NULL, data: a); |
353 | |
354 | s = g_slist_concat (NULL, list2: s1); |
355 | g_assert_cmpint (g_slist_length (s), ==, 1); |
356 | s = g_slist_concat (list1: s1, NULL); |
357 | g_assert_cmpint (g_slist_length (s), ==, 1); |
358 | |
359 | g_slist_free (list: s); |
360 | |
361 | s = g_slist_concat (NULL, NULL); |
362 | g_assert (s == NULL); |
363 | } |
364 | |
365 | static void |
366 | test_slist_copy (void) |
367 | { |
368 | GSList *slist = NULL, *copy; |
369 | GSList *s1, *s2; |
370 | guint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
371 | gsize i; |
372 | |
373 | /* Copy and test a many-element list. */ |
374 | for (i = 0; i < 10; i++) |
375 | slist = g_slist_append (list: slist, data: &nums[i]); |
376 | |
377 | copy = g_slist_copy (list: slist); |
378 | |
379 | g_assert_cmpuint (g_slist_length (copy), ==, g_slist_length (slist)); |
380 | |
381 | for (s1 = copy, s2 = slist; s1 != NULL && s2 != NULL; s1 = s1->next, s2 = s2->next) |
382 | g_assert (s1->data == s2->data); |
383 | |
384 | g_slist_free (list: copy); |
385 | g_slist_free (list: slist); |
386 | |
387 | /* Copy a NULL list. */ |
388 | copy = g_slist_copy (NULL); |
389 | g_assert_null (copy); |
390 | } |
391 | |
392 | static gpointer |
393 | copy_and_count_string (gconstpointer src, |
394 | gpointer data) |
395 | { |
396 | const gchar *str = src; |
397 | gsize *count = data; |
398 | |
399 | *count = *count + 1; |
400 | return g_strdup (str); |
401 | } |
402 | |
403 | static void |
404 | test_slist_copy_deep (void) |
405 | { |
406 | GSList *slist = NULL, *copy; |
407 | GSList *s1, *s2; |
408 | gsize count; |
409 | |
410 | /* Deep-copy a simple list. */ |
411 | slist = g_slist_append (list: slist, data: "a" ); |
412 | slist = g_slist_append (list: slist, data: "b" ); |
413 | slist = g_slist_append (list: slist, data: "c" ); |
414 | |
415 | count = 0; |
416 | copy = g_slist_copy_deep (list: slist, func: copy_and_count_string, user_data: &count); |
417 | |
418 | g_assert_cmpuint (count, ==, g_slist_length (slist)); |
419 | g_assert_cmpuint (g_slist_length (copy), ==, count); |
420 | for (s1 = slist, s2 = copy; s1 != NULL && s2 != NULL; s1 = s1->next, s2 = s2->next) |
421 | { |
422 | g_assert_cmpstr (s1->data, ==, s2->data); |
423 | g_assert (s1->data != s2->data); |
424 | } |
425 | |
426 | g_slist_free_full (list: copy, free_func: g_free); |
427 | g_slist_free (list: slist); |
428 | |
429 | /* Try with an empty list. */ |
430 | count = 0; |
431 | copy = g_slist_copy_deep (NULL, func: copy_and_count_string, user_data: &count); |
432 | g_assert_cmpuint (count, ==, 0); |
433 | g_assert_null (copy); |
434 | } |
435 | |
436 | int |
437 | main (int argc, char *argv[]) |
438 | { |
439 | gint i; |
440 | |
441 | g_test_init (argc: &argc, argv: &argv, NULL); |
442 | |
443 | /* Create an array of random numbers. */ |
444 | for (i = 0; i < SIZE; i++) |
445 | array[i] = g_test_rand_int_range (NUMBER_MIN, NUMBER_MAX); |
446 | |
447 | g_test_add_func (testpath: "/slist/sort" , test_func: test_slist_sort); |
448 | g_test_add_func (testpath: "/slist/sort-with-data" , test_func: test_slist_sort_with_data); |
449 | g_test_add_func (testpath: "/slist/sort/stable" , test_func: test_slist_sort_stable); |
450 | g_test_add_func (testpath: "/slist/insert-sorted" , test_func: test_slist_insert_sorted); |
451 | g_test_add_func (testpath: "/slist/insert-sorted-with-data" , test_func: test_slist_insert_sorted_with_data); |
452 | g_test_add_func (testpath: "/slist/reverse" , test_func: test_slist_reverse); |
453 | g_test_add_func (testpath: "/slist/nth" , test_func: test_slist_nth); |
454 | g_test_add_func (testpath: "/slist/remove" , test_func: test_slist_remove); |
455 | g_test_add_func (testpath: "/slist/remove-all" , test_func: test_slist_remove_all); |
456 | g_test_add_func (testpath: "/slist/insert" , test_func: test_slist_insert); |
457 | g_test_add_func (testpath: "/slist/position" , test_func: test_slist_position); |
458 | g_test_add_func (testpath: "/slist/concat" , test_func: test_slist_concat); |
459 | g_test_add_func (testpath: "/slist/copy" , test_func: test_slist_copy); |
460 | g_test_add_func (testpath: "/slist/copy/deep" , test_func: test_slist_copy_deep); |
461 | |
462 | return g_test_run (); |
463 | } |
464 | |