1 /*
2 * Copyright © 2014 Ran Benita <ran234@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "xkbcommon/xkbcommon-compose.h"
25
26 #include "test.h"
27
28 static const char *
compose_status_string(enum xkb_compose_status status)29 compose_status_string(enum xkb_compose_status status)
30 {
31 switch (status) {
32 case XKB_COMPOSE_NOTHING:
33 return "nothing";
34 case XKB_COMPOSE_COMPOSING:
35 return "composing";
36 case XKB_COMPOSE_COMPOSED:
37 return "composed";
38 case XKB_COMPOSE_CANCELLED:
39 return "cancelled";
40 }
41
42 return "<invalid-status>";
43 }
44
45 static const char *
feed_result_string(enum xkb_compose_feed_result result)46 feed_result_string(enum xkb_compose_feed_result result)
47 {
48 switch (result) {
49 case XKB_COMPOSE_FEED_IGNORED:
50 return "ignored";
51 case XKB_COMPOSE_FEED_ACCEPTED:
52 return "accepted";
53 }
54
55 return "<invalid-result>";
56 }
57
58 /*
59 * Feed a sequence of keysyms to a fresh compose state and test the outcome.
60 *
61 * The varargs consists of lines in the following format:
62 * <input keysym> <expected feed result> <expected status> <expected string> <expected keysym>
63 * Terminated by a line consisting only of XKB_KEY_NoSymbol.
64 */
65 static bool
test_compose_seq_va(struct xkb_compose_table * table,va_list ap)66 test_compose_seq_va(struct xkb_compose_table *table, va_list ap)
67 {
68 int ret;
69 struct xkb_compose_state *state;
70 char buffer[64];
71
72 state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS);
73 assert(state);
74
75 for (int i = 1; ; i++) {
76 xkb_keysym_t input_keysym;
77 enum xkb_compose_feed_result result, expected_result;
78 enum xkb_compose_status status, expected_status;
79 const char *expected_string;
80 xkb_keysym_t keysym, expected_keysym;
81
82 input_keysym = va_arg(ap, xkb_keysym_t);
83 if (input_keysym == XKB_KEY_NoSymbol)
84 break;
85
86 expected_result = va_arg(ap, enum xkb_compose_feed_result);
87 expected_status = va_arg(ap, enum xkb_compose_status);
88 expected_string = va_arg(ap, const char *);
89 expected_keysym = va_arg(ap, xkb_keysym_t);
90
91 result = xkb_compose_state_feed(state, input_keysym);
92
93 if (result != expected_result) {
94 fprintf(stderr, "after feeding %d keysyms:\n", i);
95 fprintf(stderr, "expected feed result: %s\n",
96 feed_result_string(expected_result));
97 fprintf(stderr, "got feed result: %s\n",
98 feed_result_string(result));
99 goto fail;
100 }
101
102 status = xkb_compose_state_get_status(state);
103 if (status != expected_status) {
104 fprintf(stderr, "after feeding %d keysyms:\n", i);
105 fprintf(stderr, "expected status: %s\n",
106 compose_status_string(expected_status));
107 fprintf(stderr, "got status: %s\n",
108 compose_status_string(status));
109 goto fail;
110 }
111
112 ret = xkb_compose_state_get_utf8(state, buffer, sizeof(buffer));
113 if (ret < 0 || (size_t) ret >= sizeof(buffer)) {
114 fprintf(stderr, "after feeding %d keysyms:\n", i);
115 fprintf(stderr, "expected string: %s\n", expected_string);
116 fprintf(stderr, "got error: %d\n", ret);
117 goto fail;
118 }
119 if (!streq(buffer, expected_string)) {
120 fprintf(stderr, "after feeding %d keysyms:\n", i);
121 fprintf(stderr, "expected string: %s\n", strempty(expected_string));
122 fprintf(stderr, "got string: %s\n", buffer);
123 goto fail;
124 }
125
126 keysym = xkb_compose_state_get_one_sym(state);
127 if (keysym != expected_keysym) {
128 fprintf(stderr, "after feeding %d keysyms:\n", i);
129 xkb_keysym_get_name(expected_keysym, buffer, sizeof(buffer));
130 fprintf(stderr, "expected keysym: %s\n", buffer);
131 xkb_keysym_get_name(keysym, buffer, sizeof(buffer));
132 fprintf(stderr, "got keysym (%#x): %s\n", keysym, buffer);
133 goto fail;
134 }
135 }
136
137 xkb_compose_state_unref(state);
138 return true;
139
140 fail:
141 xkb_compose_state_unref(state);
142 return false;
143 }
144
145 static bool
test_compose_seq(struct xkb_compose_table * table,...)146 test_compose_seq(struct xkb_compose_table *table, ...)
147 {
148 va_list ap;
149 bool ok;
150 va_start(ap, table);
151 ok = test_compose_seq_va(table, ap);
152 va_end(ap);
153 return ok;
154 }
155
156 static bool
test_compose_seq_buffer(struct xkb_context * ctx,const char * buffer,...)157 test_compose_seq_buffer(struct xkb_context *ctx, const char *buffer, ...)
158 {
159 va_list ap;
160 bool ok;
161 struct xkb_compose_table *table;
162 table = xkb_compose_table_new_from_buffer(ctx, buffer, strlen(buffer), "",
163 XKB_COMPOSE_FORMAT_TEXT_V1,
164 XKB_COMPOSE_COMPILE_NO_FLAGS);
165 assert(table);
166 va_start(ap, buffer);
167 ok = test_compose_seq_va(table, ap);
168 va_end(ap);
169 xkb_compose_table_unref(table);
170 return ok;
171 }
172
173 static void
test_seqs(struct xkb_context * ctx)174 test_seqs(struct xkb_context *ctx)
175 {
176 struct xkb_compose_table *table;
177 char *path;
178 FILE *file;
179
180 path = test_get_path("compose/en_US.UTF-8/Compose");
181 file = fopen(path, "r");
182 assert(file);
183 free(path);
184
185 table = xkb_compose_table_new_from_file(ctx, file, "",
186 XKB_COMPOSE_FORMAT_TEXT_V1,
187 XKB_COMPOSE_COMPILE_NO_FLAGS);
188 assert(table);
189 fclose(file);
190
191 assert(test_compose_seq(table,
192 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
193 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde,
194 XKB_KEY_NoSymbol));
195
196 assert(test_compose_seq(table,
197 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
198 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde,
199 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
200 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde,
201 XKB_KEY_NoSymbol));
202
203 assert(test_compose_seq(table,
204 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
205 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde,
206 XKB_KEY_NoSymbol));
207
208 assert(test_compose_seq(table,
209 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
210 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe,
211 XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe,
212 XKB_KEY_NoSymbol));
213
214 assert(test_compose_seq(table,
215 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
216 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "´", XKB_KEY_acute,
217 XKB_KEY_NoSymbol));
218
219 assert(test_compose_seq(table,
220 XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
221 XKB_KEY_Shift_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
222 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
223 XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
224 XKB_KEY_Control_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
225 XKB_KEY_T, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "@", XKB_KEY_at,
226 XKB_KEY_NoSymbol));
227
228 assert(test_compose_seq(table,
229 XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
230 XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
231 XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
232 XKB_KEY_NoSymbol));
233
234 assert(test_compose_seq(table,
235 XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
236 XKB_KEY_apostrophe, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
237 XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol,
238 XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
239 XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
240 XKB_KEY_NoSymbol));
241
242 xkb_compose_table_unref(table);
243
244 /* Make sure one-keysym sequences work. */
245 assert(test_compose_seq_buffer(ctx,
246 "<A> : \"foo\" X \n"
247 "<B> <A> : \"baz\" Y \n",
248 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X,
249 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X,
250 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
251 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
252 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "baz", XKB_KEY_Y,
253 XKB_KEY_NoSymbol));
254
255 /* No sequences at all. */
256 assert(test_compose_seq_buffer(ctx,
257 "",
258 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
259 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
260 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
261 XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
262 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
263 XKB_KEY_NoSymbol));
264
265 /* Only keysym - string derived from keysym. */
266 assert(test_compose_seq_buffer(ctx,
267 "<A> <B> : X \n"
268 "<B> <A> : dollar \n"
269 "<C> : dead_acute \n",
270 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
271 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "X", XKB_KEY_X,
272 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
273 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "$", XKB_KEY_dollar,
274 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_dead_acute,
275 XKB_KEY_NoSymbol));
276
277 /* Make sure a cancelling keysym doesn't start a new sequence. */
278 assert(test_compose_seq_buffer(ctx,
279 "<A> <B> : X \n"
280 "<C> <D> : Y \n",
281 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
282 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol,
283 XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
284 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
285 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol,
286 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
287 XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "Y", XKB_KEY_Y,
288 XKB_KEY_NoSymbol));
289 }
290
291 static void
test_conflicting(struct xkb_context * ctx)292 test_conflicting(struct xkb_context *ctx)
293 {
294 // new is prefix of old
295 assert(test_compose_seq_buffer(ctx,
296 "<A> <B> <C> : \"foo\" A \n"
297 "<A> <B> : \"bar\" B \n",
298 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
299 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
300 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A,
301 XKB_KEY_NoSymbol));
302
303 // old is a prefix of new
304 assert(test_compose_seq_buffer(ctx,
305 "<A> <B> : \"bar\" B \n"
306 "<A> <B> <C> : \"foo\" A \n",
307 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
308 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
309 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A,
310 XKB_KEY_NoSymbol));
311
312 // new duplicate of old
313 assert(test_compose_seq_buffer(ctx,
314 "<A> <B> : \"bar\" B \n"
315 "<A> <B> : \"bar\" B \n",
316 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
317 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B,
318 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol,
319 XKB_KEY_NoSymbol));
320
321 // new same length as old #1
322 assert(test_compose_seq_buffer(ctx,
323 "<A> <B> : \"foo\" A \n"
324 "<A> <B> : \"bar\" B \n",
325 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
326 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B,
327 XKB_KEY_NoSymbol));
328
329 // new same length as old #2
330 assert(test_compose_seq_buffer(ctx,
331 "<A> <B> : \"foo\" A \n"
332 "<A> <B> : \"foo\" B \n",
333 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
334 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_B,
335 XKB_KEY_NoSymbol));
336
337 // new same length as old #3
338 assert(test_compose_seq_buffer(ctx,
339 "<A> <B> : \"foo\" A \n"
340 "<A> <B> : \"bar\" A \n",
341 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
342 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_A,
343 XKB_KEY_NoSymbol));
344 }
345
346 static void
test_state(struct xkb_context * ctx)347 test_state(struct xkb_context *ctx)
348 {
349 struct xkb_compose_table *table;
350 struct xkb_compose_state *state;
351 char *path;
352 FILE *file;
353
354 path = test_get_path("compose/en_US.UTF-8/Compose");
355 file = fopen(path, "r");
356 assert(file);
357 free(path);
358
359 table = xkb_compose_table_new_from_file(ctx, file, "",
360 XKB_COMPOSE_FORMAT_TEXT_V1,
361 XKB_COMPOSE_COMPILE_NO_FLAGS);
362 assert(table);
363 fclose(file);
364
365 state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS);
366 assert(state);
367
368 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
369 xkb_compose_state_reset(state);
370 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
371 xkb_compose_state_feed(state, XKB_KEY_NoSymbol);
372 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
373 xkb_compose_state_feed(state, XKB_KEY_Multi_key);
374 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING);
375 xkb_compose_state_reset(state);
376 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
377 xkb_compose_state_feed(state, XKB_KEY_Multi_key);
378 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING);
379 xkb_compose_state_feed(state, XKB_KEY_Multi_key);
380 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED);
381 xkb_compose_state_feed(state, XKB_KEY_Multi_key);
382 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING);
383 xkb_compose_state_feed(state, XKB_KEY_Multi_key);
384 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED);
385 xkb_compose_state_reset(state);
386 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
387 xkb_compose_state_feed(state, XKB_KEY_dead_acute);
388 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING);
389 xkb_compose_state_feed(state, XKB_KEY_A);
390 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED);
391 xkb_compose_state_reset(state);
392 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
393 xkb_compose_state_feed(state, XKB_KEY_dead_acute);
394 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING);
395 xkb_compose_state_feed(state, XKB_KEY_A);
396 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED);
397 xkb_compose_state_reset(state);
398 xkb_compose_state_feed(state, XKB_KEY_NoSymbol);
399 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING);
400
401 xkb_compose_state_unref(state);
402 xkb_compose_table_unref(table);
403 }
404
405 static void
test_XCOMPOSEFILE(struct xkb_context * ctx)406 test_XCOMPOSEFILE(struct xkb_context *ctx)
407 {
408 struct xkb_compose_table *table;
409 char *path;
410
411 path = test_get_path("compose/en_US.UTF-8/Compose");
412 setenv("XCOMPOSEFILE", path, 1);
413 free(path);
414
415 table = xkb_compose_table_new_from_locale(ctx, "blabla",
416 XKB_COMPOSE_COMPILE_NO_FLAGS);
417 assert(table);
418
419 assert(test_compose_seq(table,
420 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
421 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde,
422 XKB_KEY_NoSymbol));
423
424 xkb_compose_table_unref(table);
425 }
426
427 static void
test_modifier_syntax(struct xkb_context * ctx)428 test_modifier_syntax(struct xkb_context *ctx)
429 {
430 const char *table_string;
431
432 /* We don't do anything with the modifiers, but make sure we can parse
433 * them. */
434
435 assert(test_compose_seq_buffer(ctx,
436 "None <A> : X \n"
437 "! Shift <B> : Y \n"
438 "! Ctrl <C> : Y \n"
439 "! Alt <D> : Y \n"
440 "! Caps <E> : Y \n"
441 "! Lock <F> : Y \n"
442 "! Shift Ctrl <G> : Y \n"
443 "! ~Shift <H> : Y \n"
444 "! ~Shift Ctrl <I> : Y \n"
445 "! Shift ~Ctrl <J> : Y \n"
446 "! Shift ~Ctrl ~Alt <K> : Y \n"
447 "<L> ! Shift <M> : Y \n"
448 "None <N> ! Shift <O> : Y \n"
449 "None <P> ! Shift <Q> : Y \n",
450 XKB_KEY_NoSymbol));
451
452 fprintf(stderr, "<START bad input string>\n");
453 table_string =
454 "! None <A> : X \n"
455 "! Foo <B> : X \n"
456 "None ! Shift <C> : X \n"
457 "! <D> : X \n"
458 "! ~ <E> : X \n"
459 "! ! <F> : X \n"
460 "! Ctrl ! Ctrl <G> : X \n"
461 "<H> ! : X \n"
462 "<I> None : X \n"
463 "None None <J> : X \n"
464 "<K> : !Shift X \n";
465 assert(!xkb_compose_table_new_from_buffer(ctx, table_string,
466 strlen(table_string), "C",
467 XKB_COMPOSE_FORMAT_TEXT_V1,
468 XKB_COMPOSE_COMPILE_NO_FLAGS));
469 fprintf(stderr, "<END bad input string>\n");
470 }
471
472 static void
test_include(struct xkb_context * ctx)473 test_include(struct xkb_context *ctx)
474 {
475 char *path, *table_string;
476 int ret;
477
478 path = test_get_path("compose/en_US.UTF-8/Compose");
479 assert(path);
480
481 /* We don't have a mechanism to change the include paths like we
482 * have for keymaps. So we must include the full path. */
483 ret = asprintf(&table_string,
484 "<dead_tilde> <space> : \"foo\" X\n"
485 "include \"%s\"\n"
486 "<dead_tilde> <dead_tilde> : \"bar\" Y\n", path);
487 assert(ret >= 0);
488
489 assert(test_compose_seq_buffer(ctx, table_string,
490 /* No conflict. */
491 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
492 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "´", XKB_KEY_acute,
493
494 /* Comes before - doesn't override. */
495 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
496 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde,
497
498 /* Comes after - does override. */
499 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol,
500 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_Y,
501
502 XKB_KEY_NoSymbol));
503
504 free(path);
505 free(table_string);
506 }
507
508 int
main(int argc,char * argv[])509 main(int argc, char *argv[])
510 {
511 struct xkb_context *ctx;
512
513 ctx = test_get_context(CONTEXT_NO_FLAG);
514 assert(ctx);
515
516 test_seqs(ctx);
517 test_conflicting(ctx);
518 test_XCOMPOSEFILE(ctx);
519 test_state(ctx);
520 test_modifier_syntax(ctx);
521 test_include(ctx);
522
523 xkb_context_unref(ctx);
524 return 0;
525 }
526