1 /**
2  * test-config.c
3  *
4  * Copyright (c) 2012
5  *      libchewing Core Team. See ChangeLog for details.
6  *
7  * See the file "COPYING" for information on usage and redistribution
8  * of this file.
9  */
10 
11 #ifdef HAVE_CONFIG_H
12 #    include <config.h>
13 #endif
14 
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "chewing.h"
20 #include "testhelper.h"
21 
22 static const int MIN_CAND_PER_PAGE = 1;
23 static const int MAX_CAND_PER_PAGE = 10;
24 static const int DEFAULT_CAND_PER_PAGE = 10;
25 static const int MIN_CHI_SYMBOL_LEN = 0;
26 static const int MAX_CHI_SYMBOL_LEN = 39;
27 
28 static const int DEFAULT_SELECT_KEY[] = {
29     '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
30 };
31 
32 static const int ALTERNATE_SELECT_KEY[] = {
33     'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';'
34 };
35 
36 static const TestData DATA = { "`a", "\xE2\x80\xA6" /* … */  };
37 
38 FILE *fd;
39 
test_default_value()40 void test_default_value()
41 {
42     int *select_key;
43     ChewingContext *ctx;
44 
45     ctx = chewing_new();
46     start_testcase(ctx, fd);
47 
48     select_key = chewing_get_selKey(ctx);
49     ok(select_key, "chewing_get_selKey shall not return NULL");
50     ok(!memcmp(select_key, DEFAULT_SELECT_KEY,
51                sizeof(DEFAULT_SELECT_KEY)), "default select key shall be default value");
52     chewing_free(select_key);
53 
54     ok(chewing_get_candPerPage(ctx) == DEFAULT_CAND_PER_PAGE, "default candPerPage shall be %d", DEFAULT_CAND_PER_PAGE);
55 
56     ok(chewing_get_maxChiSymbolLen(ctx) == MAX_CHI_SYMBOL_LEN,
57        "default maxChiSymbolLen shall be %d", MAX_CHI_SYMBOL_LEN);
58 
59     ok(chewing_get_addPhraseDirection(ctx) == 0, "default addPhraseDirection shall be 0");
60 
61     ok(chewing_get_spaceAsSelection(ctx) == 0, "default spaceAsSelection shall be 0");
62 
63     ok(chewing_get_escCleanAllBuf(ctx) == 0, "default escCleanAllBuf shall be 0");
64 
65 BEGIN_IGNORE_DEPRECATIONS
66     ok(chewing_get_hsuSelKeyType(ctx) == 0, "default hsuSelKeyType shall be 0");
67 END_IGNORE_DEPRECATIONS
68 
69     ok(chewing_get_autoShiftCur(ctx) == 0, "default autoShiftCur shall be 0");
70 
71     ok(chewing_get_easySymbolInput(ctx) == 0, "default easySymbolInput shall be 0");
72 
73     ok(chewing_get_phraseChoiceRearward(ctx) == 0, "default phraseChoiceRearward shall be 0");
74 
75     ok(chewing_get_ChiEngMode(ctx) == CHINESE_MODE, "default ChiEngMode shall be CHINESE_MODE");
76 
77     ok(chewing_get_ShapeMode(ctx) == HALFSHAPE_MODE, "default ShapeMode shall be HALFSHAPE_MODE");
78 
79     chewing_delete(ctx);
80 }
81 
test_set_candPerPage()82 void test_set_candPerPage()
83 {
84     const int VALUE[] = {
85         MIN_CAND_PER_PAGE,
86         MAX_CAND_PER_PAGE,
87     };
88 
89     const int INVALID_VALUE[] = {
90         MIN_CAND_PER_PAGE - 1,
91         MAX_CAND_PER_PAGE + 1,
92     };
93 
94     ChewingContext *ctx;
95     size_t i;
96     size_t j;
97 
98     ctx = chewing_new();
99     start_testcase(ctx, fd);
100 
101     for (i = 0; i < ARRAY_SIZE(VALUE); ++i) {
102         chewing_set_candPerPage(ctx, VALUE[i]);
103         ok(chewing_get_candPerPage(ctx) == VALUE[i], "candPerPage shall be `%d'", VALUE[i]);
104 
105         for (j = 0; j < ARRAY_SIZE(INVALID_VALUE); ++j) {
106             // mode shall not change when set mode has invalid value.
107             chewing_set_candPerPage(ctx, INVALID_VALUE[j]);
108             ok(chewing_get_candPerPage(ctx) == VALUE[i], "candPerPage shall be `%d'", VALUE[i]);
109         }
110     }
111 
112     chewing_delete(ctx);
113 }
114 
test_set_maxChiSymbolLen()115 void test_set_maxChiSymbolLen()
116 {
117     ChewingContext *ctx;
118     int i;
119 
120     ctx = chewing_new();
121     start_testcase(ctx, fd);
122 
123     chewing_set_maxChiSymbolLen(ctx, 16);
124     ok(chewing_get_maxChiSymbolLen(ctx) == 16, "maxChiSymbolLen shall be 16");
125 
126     chewing_set_maxChiSymbolLen(ctx, MIN_CHI_SYMBOL_LEN - 1);
127     ok(chewing_get_maxChiSymbolLen(ctx) == 16,
128        "maxChiSymbolLen shall not change when set to %d", MIN_CHI_SYMBOL_LEN - 1);
129 
130     chewing_set_maxChiSymbolLen(ctx, MAX_CHI_SYMBOL_LEN + 1);
131     ok(chewing_get_maxChiSymbolLen(ctx) == 16,
132        "maxChiSymbolLen shall not change when set to %d", MAX_CHI_SYMBOL_LEN + 1);
133 
134 
135     // Test auto commit
136     chewing_set_maxChiSymbolLen(ctx, MAX_CHI_SYMBOL_LEN);
137 
138     // In boundary
139     for (i = 0; i < MAX_CHI_SYMBOL_LEN; ++i)
140         type_keystroke_by_string(ctx, "hk4");
141     ok(chewing_commit_Check(ctx) == 0,
142        "auto commit shall not be triggered when entering %d symbols", MAX_CHI_SYMBOL_LEN);
143 
144     // Out of boundary
145     type_keystroke_by_string(ctx, "hk4");
146     ok(chewing_commit_Check(ctx) == 1,
147        "auto commit shall be triggered when entering %d symbols", MAX_CHI_SYMBOL_LEN + 1);
148 
149     chewing_delete(ctx);
150 }
151 
test_maxChiSymbolLen()152 void test_maxChiSymbolLen()
153 {
154     ChewingContext *ctx;
155     int i;
156 
157     ctx = chewing_new();
158     start_testcase(ctx, fd);
159 
160     chewing_set_maxChiSymbolLen(ctx, MAX_CHI_SYMBOL_LEN);
161 
162     for (i = 0; i < MAX_CHI_SYMBOL_LEN; ++i) {
163         type_keystroke_by_string(ctx, "hk4");
164     }
165 
166     // Use easy symbol 'Orz' as last input for worst case scenario.
167     chewing_set_easySymbolInput(ctx, 1);
168     type_keystroke_by_string(ctx, "L");
169 
170     chewing_delete(ctx);
171 }
172 
test_set_selKey_normal()173 void test_set_selKey_normal()
174 {
175     ChewingContext *ctx;
176     int *select_key;
177 
178     ctx = chewing_new();
179     start_testcase(ctx, fd);
180 
181     // XXX: chewing_set_selKey shall accept const char *.
182     chewing_set_selKey(ctx, ALTERNATE_SELECT_KEY, ARRAY_SIZE(ALTERNATE_SELECT_KEY));
183     select_key = chewing_get_selKey(ctx);
184     ok(select_key, "chewing_get_selKey shall not return NULL");
185     ok(!memcmp(select_key, ALTERNATE_SELECT_KEY,
186                sizeof(ALTERNATE_SELECT_KEY)), "select key shall be ALTERNATE_SELECT_KEY");
187 
188     type_keystroke_by_string(ctx, DATA.token);
189     ok_preedit_buffer(ctx, DATA.expected);
190 
191     chewing_free(select_key);
192 
193     chewing_delete(ctx);
194 }
195 
test_set_selKey_error_handling()196 void test_set_selKey_error_handling()
197 {
198     ChewingContext *ctx;
199     int *select_key;
200 
201     ctx = chewing_new();
202     start_testcase(ctx, fd);
203 
204     chewing_set_selKey(NULL, ALTERNATE_SELECT_KEY, ARRAY_SIZE(ALTERNATE_SELECT_KEY));
205     select_key = chewing_get_selKey(ctx);
206     ok(select_key, "chewing_get_selKey shall not return NULL");
207     ok(!memcmp(select_key, DEFAULT_SELECT_KEY, sizeof(DEFAULT_SELECT_KEY)), "select key shall be DEFAULT_SELECT_KEY");
208     chewing_free(select_key);
209 
210     chewing_set_selKey(ctx, NULL, ARRAY_SIZE(ALTERNATE_SELECT_KEY));
211     select_key = chewing_get_selKey(ctx);
212     ok(select_key, "chewing_get_selKey shall not return NULL");
213     ok(!memcmp(select_key, DEFAULT_SELECT_KEY, sizeof(DEFAULT_SELECT_KEY)), "select key shall be DEFAULT_SELECT_KEY");
214     chewing_free(select_key);
215 
216     chewing_set_selKey(ctx, ALTERNATE_SELECT_KEY, 0);
217     select_key = chewing_get_selKey(ctx);
218     ok(select_key, "chewing_get_selKey shall not return NULL");
219     ok(!memcmp(select_key, DEFAULT_SELECT_KEY, sizeof(DEFAULT_SELECT_KEY)), "select key shall be DEFAULT_SELECT_KEY");
220     chewing_free(select_key);
221 
222     chewing_set_selKey(ctx, ALTERNATE_SELECT_KEY, 11);
223     select_key = chewing_get_selKey(ctx);
224     ok(select_key, "chewing_get_selKey shall not return NULL");
225     ok(!memcmp(select_key, DEFAULT_SELECT_KEY, sizeof(DEFAULT_SELECT_KEY)), "select key shall be DEFAULT_SELECT_KEY");
226     chewing_free(select_key);
227 
228     chewing_delete(ctx);
229 }
230 
test_set_selKey()231 void test_set_selKey()
232 {
233     test_set_selKey_normal();
234     test_set_selKey_error_handling();
235 }
236 
test_set_addPhraseDirection()237 void test_set_addPhraseDirection()
238 {
239     ChewingContext *ctx;
240     int value;
241     int mode;
242 
243     ctx = chewing_new();
244     start_testcase(ctx, fd);
245 
246     for (value = 0; value < 2; ++value) {
247         chewing_set_addPhraseDirection(ctx, value);
248         mode = chewing_get_addPhraseDirection(ctx);
249         ok(mode == value, "addPhraseDirection `%d' shall be `%d'", mode, value);
250 
251         chewing_set_addPhraseDirection(ctx, -1);
252         mode = chewing_get_addPhraseDirection(ctx);
253         ok(mode == value, "addPhraseDirection `%d' shall be `%d'", mode, value);
254 
255         chewing_set_addPhraseDirection(ctx, 2);
256         mode = chewing_get_addPhraseDirection(ctx);
257         ok(mode == value, "addPhraseDirection `%d' shall be `%d'", mode, value);
258     }
259 
260     chewing_delete(ctx);
261 }
262 
test_set_spaceAsSelection()263 void test_set_spaceAsSelection()
264 {
265     ChewingContext *ctx;
266     int value;
267     int mode;
268 
269     ctx = chewing_new();
270     start_testcase(ctx, fd);
271 
272     for (value = 0; value < 2; ++value) {
273         chewing_set_spaceAsSelection(ctx, value);
274         mode = chewing_get_spaceAsSelection(ctx);
275         ok(mode == value, "spaceAsSelection `%d' shall be `%d'", mode, value);
276 
277         chewing_set_spaceAsSelection(ctx, -1);
278         mode = chewing_get_spaceAsSelection(ctx);
279         ok(mode == value, "spaceAsSelection `%d' shall be `%d'", mode, value);
280 
281         chewing_set_spaceAsSelection(ctx, 2);
282         mode = chewing_get_spaceAsSelection(ctx);
283         ok(mode == value, "spaceAsSelection `%d' shall be `%d'", mode, value);
284     }
285 
286     chewing_delete(ctx);
287 }
288 
test_set_escCleanAllBuf()289 void test_set_escCleanAllBuf()
290 {
291     ChewingContext *ctx;
292     int value;
293     int mode;
294 
295     ctx = chewing_new();
296     start_testcase(ctx, fd);
297 
298     for (value = 0; value < 2; ++value) {
299         chewing_set_escCleanAllBuf(ctx, value);
300         mode = chewing_get_escCleanAllBuf(ctx);
301         ok(mode == value, "escCleanAllBuf shall be `%d'", value);
302 
303         chewing_set_escCleanAllBuf(ctx, -1);
304         mode = chewing_get_escCleanAllBuf(ctx);
305         ok(mode == value, "escCleanAllBuf shall be `%d'", value);
306 
307         chewing_set_escCleanAllBuf(ctx, 2);
308         mode = chewing_get_escCleanAllBuf(ctx);
309         ok(mode == value, "escCleanAllBuf shall be `%d'", value);
310     }
311 
312     chewing_delete(ctx);
313 }
314 
test_set_autoShiftCur()315 void test_set_autoShiftCur()
316 {
317     ChewingContext *ctx;
318     int value;
319     int mode;
320 
321     ctx = chewing_new();
322     start_testcase(ctx, fd);
323 
324     for (value = 0; value < 2; ++value) {
325         chewing_set_autoShiftCur(ctx, value);
326         mode = chewing_get_autoShiftCur(ctx);
327         ok(mode == value, "autoShiftCur shall be `%d'", value);
328 
329         chewing_set_autoShiftCur(ctx, -1);
330         mode = chewing_get_autoShiftCur(ctx);
331         ok(mode == value, "autoShiftCur shall be `%d'", value);
332 
333         chewing_set_autoShiftCur(ctx, 2);
334         mode = chewing_get_autoShiftCur(ctx);
335         ok(mode == value, "autoShiftCur shall be `%d'", value);
336     }
337 
338     chewing_delete(ctx);
339 }
340 
test_set_easySymbolInput()341 void test_set_easySymbolInput()
342 {
343     ChewingContext *ctx;
344     int value;
345     int mode;
346 
347     ctx = chewing_new();
348     start_testcase(ctx, fd);
349 
350     for (value = 0; value < 2; ++value) {
351         chewing_set_easySymbolInput(ctx, value);
352         mode = chewing_get_easySymbolInput(ctx);
353         ok(mode == value, "easySymbolInput `%d', shall be `%d'", mode, value);
354 
355         chewing_set_easySymbolInput(ctx, -1);
356         mode = chewing_get_easySymbolInput(ctx);
357         ok(mode == value, "easySymbolInput `%d', shall be `%d'", mode, value);
358 
359         chewing_set_easySymbolInput(ctx, 2);
360         mode = chewing_get_easySymbolInput(ctx);
361         ok(mode == value, "easySymbolInput `%d', shall be `%d'", mode, value);
362     }
363 
364     chewing_delete(ctx);
365 }
366 
test_set_phraseChoiceRearward()367 void test_set_phraseChoiceRearward()
368 {
369     ChewingContext *ctx;
370     int value;
371     int mode;
372 
373     ctx = chewing_new();
374     start_testcase(ctx, fd);
375 
376     for (value = 0; value < 2; ++value) {
377         chewing_set_phraseChoiceRearward(ctx, value);
378         mode = chewing_get_phraseChoiceRearward(ctx);
379         ok(mode == value, "phraseChoiceRearward `%d' shall be `%d'", mode, value);
380 
381         chewing_set_phraseChoiceRearward(ctx, -1);
382         mode = chewing_get_phraseChoiceRearward(ctx);
383         ok(mode == value, "phraseChoiceRearward `%d' shall be `%d'", mode, value);
384 
385         chewing_set_phraseChoiceRearward(ctx, 2);
386         mode = chewing_get_phraseChoiceRearward(ctx);
387         ok(mode == value, "phraseChoiceRearward `%d' shall be `%d'", mode, value);
388     }
389 
390     chewing_delete(ctx);
391 }
392 
test_set_ChiEngMode()393 void test_set_ChiEngMode()
394 {
395     const int VALUE[] = {
396         CHINESE_MODE,
397         SYMBOL_MODE,
398     };
399 
400     const int INVALID_VALUE[] = {
401         -1,
402         2,
403     };
404 
405     ChewingContext *ctx;
406     size_t i;
407     size_t j;
408 
409     ctx = chewing_new();
410     start_testcase(ctx, fd);
411 
412     for (i = 0; i < ARRAY_SIZE(VALUE); ++i) {
413         chewing_set_ChiEngMode(ctx, VALUE[i]);
414         ok(chewing_get_ChiEngMode(ctx) == VALUE[i], "ChiEngMode shall be `%d'", VALUE[i]);
415 
416         for (j = 0; j < ARRAY_SIZE(INVALID_VALUE); ++j) {
417             // mode shall not change when set mode has invalid value.
418             chewing_set_ChiEngMode(ctx, INVALID_VALUE[j]);
419             ok(chewing_get_ChiEngMode(ctx) == VALUE[i], "ChiEngMode shall be `%d'", VALUE[i]);
420         }
421     }
422 
423     chewing_delete(ctx);
424 }
425 
test_set_ShapeMode()426 void test_set_ShapeMode()
427 {
428     const int VALUE[] = {
429         HALFSHAPE_MODE,
430         FULLSHAPE_MODE,
431     };
432 
433     const int INVALID_VALUE[] = {
434         -1,
435         2,
436     };
437 
438     ChewingContext *ctx;
439     size_t i;
440     size_t j;
441 
442     ctx = chewing_new();
443     start_testcase(ctx, fd);
444 
445     for (i = 0; i < ARRAY_SIZE(VALUE); ++i) {
446         chewing_set_ShapeMode(ctx, VALUE[i]);
447         ok(chewing_get_ShapeMode(ctx) == VALUE[i], "ShapeMode shall be `%d'", VALUE[i]);
448 
449         for (j = 0; j < ARRAY_SIZE(INVALID_VALUE); ++j) {
450             // mode shall not change when set mode has invalid value.
451             chewing_set_ShapeMode(ctx, INVALID_VALUE[j]);
452             ok(chewing_get_ShapeMode(ctx) == VALUE[i], "ShapeMode shall be `%d'", VALUE[i]);
453         }
454     }
455 
456     chewing_delete(ctx);
457 }
458 
test_deprecated()459 void test_deprecated()
460 {
461     ChewingContext *ctx;
462     int type;
463     ChewingConfigData configure;
464 
465     memset(&configure, 0, sizeof(ChewingConfigData));
466 
467     ctx = chewing_new();
468     start_testcase(ctx, fd);
469 
470 BEGIN_IGNORE_DEPRECATIONS
471     chewing_set_hsuSelKeyType(ctx, HSU_SELKEY_TYPE1);
472     type = chewing_get_hsuSelKeyType(ctx);
473     ok(type == 0, "`%d' shall be `%d'", type, 0);
474 
475     chewing_Configure(ctx, &configure);
476 END_IGNORE_DEPRECATIONS
477 
478     chewing_delete(ctx);
479 }
480 
test_new2_syspath_alternative()481 void test_new2_syspath_alternative()
482 {
483     ChewingContext *ctx;
484 
485     printf("#\n# %s\n#\n", __func__);
486     fprintf(fd, "#\n# %s\n#\n", __func__);
487 
488     ctx = chewing_new2(TEST_DATA_DIR, NULL, logger, fd);
489     ok(ctx != NULL, "chewing_new2 returns `%#p' shall not be `%#p'", ctx, NULL);
490 
491     chewing_delete(ctx);
492 }
493 
test_new2_syspath_error()494 void test_new2_syspath_error()
495 {
496     ChewingContext *ctx;
497 
498     printf("#\n# %s\n#\n", __func__);
499     fprintf(fd, "#\n# %s\n#\n", __func__);
500 
501     ctx = chewing_new2("NoSuchPath", NULL, logger, fd);
502     ok(ctx == NULL, "chewing_new2 returns `%#p' shall be `%#p'", ctx, NULL);
503 }
504 
test_new2_syspath()505 void test_new2_syspath()
506 {
507     test_new2_syspath_alternative();
508     test_new2_syspath_error();
509 }
510 
test_new2_userpath_alternative()511 void test_new2_userpath_alternative()
512 {
513     ChewingContext *ctx;
514 
515     printf("#\n# %s\n#\n", __func__);
516     fprintf(fd, "#\n# %s\n#\n", __func__);
517 
518     ctx = chewing_new2(NULL, TEST_HASH_DIR "/test.sqlite3", logger, fd);
519     ok(ctx != NULL, "chewing_new2 returns `%#p' shall not be `%#p'", ctx, NULL);
520 
521     chewing_delete(ctx);
522 }
523 
test_new2_userpath_error()524 void test_new2_userpath_error()
525 {
526     ChewingContext *ctx;
527 
528     printf("#\n# %s\n#\n", __func__);
529     fprintf(fd, "#\n# %s\n#\n", __func__);
530 
531     ctx = chewing_new2(NULL, TEST_HASH_DIR, logger, fd);
532     ok(ctx == NULL, "chewing_new2 returns `%#p' shall be `%#p'", ctx, NULL);
533 }
534 
test_new2_userpath()535 void test_new2_userpath()
536 {
537     test_new2_userpath_alternative();
538     test_new2_userpath_error();
539 }
540 
test_new2()541 void test_new2()
542 {
543     test_new2_syspath();
544     test_new2_userpath();
545 }
546 
main(int argc,char * argv[])547 int main(int argc, char *argv[])
548 {
549     char *logname;
550     int ret;
551 
552     putenv("CHEWING_PATH=" CHEWING_DATA_PREFIX);
553     putenv("CHEWING_USER_PATH=" TEST_HASH_DIR);
554 
555     ret = asprintf(&logname, "%s.log", argv[0]);
556     if (ret == -1)
557         return -1;
558     fd = fopen(logname, "w");
559     assert(fd);
560     free(logname);
561 
562 
563     test_default_value();
564 
565     test_set_candPerPage();
566     test_set_maxChiSymbolLen();
567     test_maxChiSymbolLen();
568     test_set_selKey();
569     test_set_addPhraseDirection();
570     test_set_spaceAsSelection();
571     test_set_escCleanAllBuf();
572     test_set_autoShiftCur();
573     test_set_easySymbolInput();
574     test_set_phraseChoiceRearward();
575     test_set_ChiEngMode();
576     test_set_ShapeMode();
577 
578     test_deprecated();
579 
580     test_new2();
581 
582     fclose(fd);
583 
584     return exit_status();
585 }
586