1 | #include "config.h" |
2 | |
3 | #include <glib.h> |
4 | #include <locale.h> |
5 | #include <stdlib.h> |
6 | #include <string.h> |
7 | |
8 | static gboolean missing_locale = FALSE; |
9 | |
10 | typedef struct { |
11 | const gchar **input; |
12 | const gchar **sorted; |
13 | const gchar **file_sorted; |
14 | } CollateTest; |
15 | |
16 | typedef struct { |
17 | gchar *key; |
18 | const gchar *str; |
19 | } Line; |
20 | |
21 | static void |
22 | clear_line (Line *line) |
23 | { |
24 | g_free (mem: line->key); |
25 | } |
26 | |
27 | static int |
28 | compare_collate (const void *a, const void *b) |
29 | { |
30 | const Line *line_a = a; |
31 | const Line *line_b = b; |
32 | |
33 | return g_utf8_collate (str1: line_a->str, str2: line_b->str); |
34 | } |
35 | |
36 | static int |
37 | compare_key (const void *a, const void *b) |
38 | { |
39 | const Line *line_a = a; |
40 | const Line *line_b = b; |
41 | |
42 | return strcmp (s1: line_a->key, s2: line_b->key); |
43 | } |
44 | |
45 | static void |
46 | do_collate (gboolean for_file, gboolean use_key, const CollateTest *test) |
47 | { |
48 | GArray *line_array; |
49 | Line line; |
50 | gint i; |
51 | |
52 | if (missing_locale) |
53 | { |
54 | g_test_skip (msg: "no en_US locale" ); |
55 | return; |
56 | } |
57 | |
58 | line_array = g_array_new (FALSE, FALSE, element_size: sizeof(Line)); |
59 | g_array_set_clear_func (array: line_array, clear_func: (GDestroyNotify)clear_line); |
60 | |
61 | for (i = 0; test->input[i]; i++) |
62 | { |
63 | line.str = test->input[i]; |
64 | if (for_file) |
65 | line.key = g_utf8_collate_key_for_filename (str: line.str, len: -1); |
66 | else |
67 | line.key = g_utf8_collate_key (str: line.str, len: -1); |
68 | |
69 | g_array_append_val (line_array, line); |
70 | } |
71 | |
72 | qsort (base: line_array->data, nmemb: line_array->len, size: sizeof (Line), compar: use_key ? compare_key : compare_collate); |
73 | |
74 | for (i = 0; test->input[i]; i++) |
75 | { |
76 | const gchar *str; |
77 | str = g_array_index (line_array, Line, i).str; |
78 | if (for_file) |
79 | g_assert_cmpstr (str, ==, test->file_sorted[i]); |
80 | else |
81 | g_assert_cmpstr (str, ==, test->sorted[i]); |
82 | } |
83 | |
84 | g_array_free (array: line_array, TRUE); |
85 | } |
86 | |
87 | static void |
88 | test_collate (gconstpointer d) |
89 | { |
90 | const CollateTest *test = d; |
91 | do_collate (FALSE, FALSE, test); |
92 | } |
93 | |
94 | static void |
95 | test_collate_key (gconstpointer d) |
96 | { |
97 | const CollateTest *test = d; |
98 | do_collate (FALSE, TRUE, test); |
99 | } |
100 | |
101 | static void |
102 | test_collate_file (gconstpointer d) |
103 | { |
104 | const CollateTest *test = d; |
105 | do_collate (TRUE, TRUE, test); |
106 | } |
107 | |
108 | const gchar *input0[] = { |
109 | "z" , |
110 | "c" , |
111 | "eer34" , |
112 | "223" , |
113 | "er1" , |
114 | "üĠണ" , |
115 | "foo" , |
116 | "bar" , |
117 | "baz" , |
118 | "GTK+" , |
119 | NULL |
120 | }; |
121 | |
122 | const gchar *sorted0[] = { |
123 | "223" , |
124 | "bar" , |
125 | "baz" , |
126 | "c" , |
127 | "eer34" , |
128 | "er1" , |
129 | "foo" , |
130 | "GTK+" , |
131 | "üĠണ" , |
132 | "z" , |
133 | NULL |
134 | }; |
135 | |
136 | const gchar *file_sorted0[] = { |
137 | "223" , |
138 | "bar" , |
139 | "baz" , |
140 | "c" , |
141 | "eer34" , |
142 | "er1" , |
143 | "foo" , |
144 | "GTK+" , |
145 | "üĠണ" , |
146 | "z" , |
147 | NULL |
148 | }; |
149 | |
150 | const gchar *input1[] = { |
151 | "file.txt" , |
152 | "file2.bla" , |
153 | "file.c" , |
154 | "file3.xx" , |
155 | "bla001" , |
156 | "bla02" , |
157 | "bla03" , |
158 | "bla4" , |
159 | "bla10" , |
160 | "bla100" , |
161 | "event.c" , |
162 | "eventgenerator.c" , |
163 | "event.h" , |
164 | NULL |
165 | }; |
166 | |
167 | const gchar *sorted1[] = { |
168 | "bla001" , |
169 | "bla02" , |
170 | "bla03" , |
171 | "bla10" , |
172 | "bla100" , |
173 | "bla4" , |
174 | "event.c" , |
175 | "eventgenerator.c" , |
176 | "event.h" , |
177 | "file2.bla" , |
178 | "file3.xx" , |
179 | "file.c" , |
180 | "file.txt" , |
181 | NULL |
182 | }; |
183 | |
184 | const gchar *file_sorted1[] = { |
185 | "bla001" , |
186 | "bla02" , |
187 | "bla03" , |
188 | "bla4" , |
189 | "bla10" , |
190 | "bla100" , |
191 | "event.c" , |
192 | "event.h" , |
193 | "eventgenerator.c" , |
194 | "file.c" , |
195 | "file.txt" , |
196 | "file2.bla" , |
197 | "file3.xx" , |
198 | NULL |
199 | }; |
200 | |
201 | const gchar *input2[] = { |
202 | "file26" , |
203 | "file100" , |
204 | "file1" , |
205 | "file:foo" , |
206 | "a.a" , |
207 | "file027" , |
208 | "file10" , |
209 | "aa.a" , |
210 | "file5" , |
211 | "file0027" , |
212 | "a-.a" , |
213 | "file0000" , |
214 | "file000x" , |
215 | NULL |
216 | }; |
217 | |
218 | const gchar *sorted2[] = { |
219 | "a-.a" , |
220 | "a.a" , |
221 | "aa.a" , |
222 | "file0000" , |
223 | "file000x" , |
224 | "file0027" , |
225 | "file027" , |
226 | "file1" , |
227 | "file10" , |
228 | "file100" , |
229 | "file26" , |
230 | "file5" , |
231 | "file:foo" , |
232 | NULL |
233 | }; |
234 | |
235 | const gchar *file_sorted2[] = { |
236 | /* Filename collation in OS X follows Finder style which gives |
237 | * a slightly different order from usual Linux locales. */ |
238 | #ifdef HAVE_CARBON |
239 | "a-.a" , |
240 | "a.a" , |
241 | "aa.a" , |
242 | "file:foo" , |
243 | "file0000" , |
244 | "file000x" , |
245 | "file1" , |
246 | "file5" , |
247 | "file10" , |
248 | "file26" , |
249 | "file0027" , |
250 | "file027" , |
251 | "file100" , |
252 | #else |
253 | "a.a" , |
254 | "a-.a" , |
255 | "aa.a" , |
256 | "file0000" , |
257 | "file000x" , |
258 | "file1" , |
259 | "file5" , |
260 | "file10" , |
261 | "file26" , |
262 | "file027" , |
263 | "file0027" , |
264 | "file100" , |
265 | "file:foo" , |
266 | #endif |
267 | NULL |
268 | }; |
269 | |
270 | int |
271 | main (int argc, char *argv[]) |
272 | { |
273 | gchar *path; |
274 | guint i; |
275 | const gchar *locale; |
276 | CollateTest test[3]; |
277 | |
278 | g_test_init (argc: &argc, argv: &argv, NULL); |
279 | |
280 | g_setenv (variable: "LC_ALL" , value: "en_US" , TRUE); |
281 | locale = setlocale (LC_ALL, locale: "" ); |
282 | if (locale == NULL || strcmp (s1: locale, s2: "en_US" ) != 0) |
283 | { |
284 | g_test_message (format: "No suitable locale, skipping tests" ); |
285 | missing_locale = TRUE; |
286 | /* let the tests run to completion so they show up as SKIP'd in TAP |
287 | * output */ |
288 | } |
289 | |
290 | test[0].input = input0; |
291 | test[0].sorted = sorted0; |
292 | test[0].file_sorted = file_sorted0; |
293 | test[1].input = input1; |
294 | test[1].sorted = sorted1; |
295 | test[1].file_sorted = file_sorted1; |
296 | test[2].input = input2; |
297 | test[2].sorted = sorted2; |
298 | test[2].file_sorted = file_sorted2; |
299 | |
300 | for (i = 0; i < G_N_ELEMENTS (test); i++) |
301 | { |
302 | path = g_strdup_printf (format: "/unicode/collate/%d" , i); |
303 | g_test_add_data_func (testpath: path, test_data: &test[i], test_func: test_collate); |
304 | g_free (mem: path); |
305 | path = g_strdup_printf (format: "/unicode/collate-key/%d" , i); |
306 | g_test_add_data_func (testpath: path, test_data: &test[i], test_func: test_collate_key); |
307 | g_free (mem: path); |
308 | path = g_strdup_printf (format: "/unicode/collate-filename/%d" , i); |
309 | g_test_add_data_func (testpath: path, test_data: &test[i], test_func: test_collate_file); |
310 | g_free (mem: path); |
311 | } |
312 | |
313 | return g_test_run (); |
314 | } |
315 | |