EFL 1.7 svn doobies
[profile/ivi/eina.git] / src / tests / eina_test_ustr.c
1 /* EINA - EFL data type library
2  * Copyright (C) 2010 Brett Nash
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library;
16  * if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <time.h>
27
28 #include "eina_suite.h"
29 #include "Eina.h"
30
31 #ifdef EINA_SAFETY_CHECKS
32 struct log_ctx {
33    const char *msg;
34    const char *fnc;
35    Eina_Bool did;
36 };
37
38 /* tests should not output on success, just uncomment this for debugging */
39 //#define SHOW_LOG 1
40
41 static void
42 _eina_test_safety_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args __UNUSED__)
43 {
44    struct log_ctx *ctx = data;
45    va_list cp_args;
46    const char *str;
47
48    va_copy(cp_args, args);
49    str = va_arg(cp_args, const char *);
50    va_end(cp_args);
51
52    ck_assert_int_eq(level, EINA_LOG_LEVEL_ERR);
53    ck_assert_str_eq(fmt, "%s");
54    ck_assert_str_eq(ctx->msg, str);
55    ck_assert_str_eq(ctx->fnc, fnc);
56    ctx->did = EINA_TRUE;
57
58 #ifdef SHOW_LOG
59    eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
60 #else
61    (void)d;
62    (void)file;
63    (void)line;
64 #endif
65 }
66 #endif
67
68 static const Eina_Unicode STR1[] = {'P', 'a', 'n', 't', 's',' ', 'O', 'n', 0};
69 static const Eina_Unicode STR2[] = {'P', 'a', 'n', 't', 's',' ', 'O', 'f', 'f', 0};
70 static const Eina_Unicode STR3[] = {'P', 'a', 'n', 't', 's',' ', 'O', 'n', 0};
71 static const Eina_Unicode STR4[] = {'A', 0};
72 static const Eina_Unicode EMPTYSTR[] = {0};
73
74 START_TEST(eina_unicode_strcmp_test)
75 {
76    eina_init();
77
78    /* 1 & 2 */
79    fail_if(eina_unicode_strcmp(STR1,STR2) == 0);
80    fail_if(eina_unicode_strcmp(STR1,STR2) < 1);
81
82    /* 1 & 3 */
83    fail_if(eina_unicode_strcmp(STR1, STR3) != 0);
84
85    /* 1 & 4 */
86    fail_if(eina_unicode_strcmp(STR1, STR4) == 0);
87    fail_if(eina_unicode_strcmp(STR1, STR4) > 1);
88
89    /* 1 & empty */
90    fail_if(eina_unicode_strcmp(STR1, EMPTYSTR) < 1);
91
92    /* Self tests */
93    fail_if(eina_unicode_strcmp(STR1, STR1) != 0);
94    fail_if(eina_unicode_strcmp(STR2, STR2) != 0);
95    fail_if(eina_unicode_strcmp(STR3, STR3) != 0);
96    fail_if(eina_unicode_strcmp(STR4, STR4) != 0);
97    fail_if(eina_unicode_strcmp(EMPTYSTR, EMPTYSTR) != 0);
98
99    eina_shutdown();
100 }
101 END_TEST
102
103 START_TEST(eina_unicode_strcpy_test)
104 {
105    Eina_Unicode buf[10] = { 0 };
106    Eina_Unicode *rv;
107
108    eina_init();
109
110    rv = eina_unicode_strcpy(buf,STR1);
111    fail_if(rv != buf);
112    fail_if(eina_unicode_strcmp(buf,STR1) != 0);
113
114    rv = eina_unicode_strcpy(buf,STR2);
115    fail_if(rv != buf);
116    fail_if(eina_unicode_strcmp(buf,STR2) != 0);
117
118    /* Now a shorter string */
119    rv = eina_unicode_strcpy(buf,STR2);
120    fail_if(rv != buf);
121    fail_if(eina_unicode_strcmp(buf,STR2) != 0);
122
123    /* Really short string */
124    rv = eina_unicode_strcpy(buf,STR4);
125    fail_if(rv != buf);
126    fail_if(eina_unicode_strcmp(buf,STR4) != 0);
127    fail_if(buf[2] != 'n'); /* check old buf is there */
128
129    buf[1] = '7';
130    rv = eina_unicode_strcpy(buf,EMPTYSTR);
131    fail_if(rv != buf);
132    fail_if(buf[0] != 0);
133    fail_if(buf[1] != '7');
134
135    eina_shutdown();
136 }
137 END_TEST
138
139 START_TEST(eina_unicode_strncpy_test)
140 {
141    Eina_Unicode buf[10] = { 0 };
142    Eina_Unicode *rv;
143
144    eina_init();
145
146    rv = eina_unicode_strncpy(buf,STR1,9);
147    fail_if(rv != buf);
148    fail_if(eina_unicode_strcmp(buf,STR1) != 0);
149
150    buf[1] = '7';
151    rv = eina_unicode_strncpy(buf,STR1,1);
152    fail_if(rv != buf);
153    fail_if(buf[1] != '7');
154    fail_if(buf[0] != STR1[0]);
155
156    buf[9] = '7';
157    rv = eina_unicode_strncpy(buf, STR4, 10);
158    fail_if(rv != buf);
159    fail_if(eina_unicode_strcmp(buf,STR4) != 0);
160    fail_if(buf[9] != 0);
161
162    buf[0] = '7';
163    rv = eina_unicode_strncpy(buf, STR1, 0);
164    fail_if(buf[0] != '7');
165
166 #ifdef EINA_SAFETY_CHECKS
167    {
168       struct log_ctx ctx;
169
170 #define TEST_MAGIC_SAFETY(fn, _msg)             \
171       ctx.msg = _msg;                           \
172       ctx.fnc = fn;                             \
173       ctx.did = EINA_FALSE
174
175       eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
176
177       /* may segfault */
178       buf[0] = '7';
179 #ifdef SHOW_LOG
180       fprintf(stderr, "you should have a safety check failure below:\n");
181 #endif
182       TEST_MAGIC_SAFETY("eina_unicode_strncpy",
183                         "safety check failed: source == NULL");
184       rv = eina_unicode_strncpy(buf, NULL, 0);
185       fail_if(buf[0] != '7');
186       fail_unless(ctx.did);
187
188       /* Hopefully won't segfault */
189 #ifdef SHOW_LOG
190       fprintf(stderr, "you should have a safety check failure below:\n");
191 #endif
192       TEST_MAGIC_SAFETY("eina_unicode_strncpy",
193                         "safety check failed: dest == NULL");
194       rv = eina_unicode_strncpy(NULL, STR1, 0);
195       fail_if(rv != NULL);
196       fail_unless(ctx.did);
197
198       eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
199 #undef TEST_MAGIC_SAFETY
200    }
201 #endif
202
203    eina_shutdown();
204 }
205 END_TEST
206
207
208
209 START_TEST(eina_ustr_strlen_test)
210 {
211
212    eina_init();
213
214    fail_if(eina_unicode_strlen(STR1) != 8);
215    fail_if(eina_unicode_strlen(STR2) != 9);
216    fail_if(eina_unicode_strlen(STR3) != 8);
217    fail_if(eina_unicode_strlen(STR4) != 1);
218    fail_if(eina_unicode_strlen(EMPTYSTR) != 0);
219
220 #ifdef EINA_SAFETY_CHECKS
221    {
222       struct log_ctx ctx;
223
224 #define TEST_MAGIC_SAFETY(fn, _msg)             \
225       ctx.msg = _msg;                           \
226       ctx.fnc = fn;                             \
227       ctx.did = EINA_FALSE
228
229       eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
230
231 #ifdef SHOW_LOG
232       fprintf(stderr, "you should have a safety check failure below:\n");
233 #endif
234       TEST_MAGIC_SAFETY("eina_unicode_strlen",
235                         "safety check failed: ustr == NULL");
236       fail_if(eina_unicode_strlen(NULL));
237       fail_unless(ctx.did);
238
239       eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
240 #undef TEST_MAGIC_SAFETY
241    }
242 #endif
243
244    eina_shutdown();
245 }
246 END_TEST
247
248 START_TEST(eina_unicode_strnlen_test)
249 {
250    eina_init();
251
252    /* Strlen style tests*/
253    fail_if(eina_unicode_strnlen(STR1,10) != 8);
254    fail_if(eina_unicode_strnlen(STR2,10) != 9);
255    fail_if(eina_unicode_strnlen(STR3,10) != 8);
256    fail_if(eina_unicode_strnlen(STR4,10) != 1);
257    fail_if(eina_unicode_strnlen(EMPTYSTR,10) != 0);
258
259    /* Too short tests */
260    fail_if(eina_unicode_strnlen(STR1,3) != 3);
261    fail_if(eina_unicode_strnlen(STR2,3) != 3);
262    fail_if(eina_unicode_strnlen(STR3,3) != 3);
263    fail_if(eina_unicode_strnlen(EMPTYSTR,1) != 0);
264
265 #ifdef EINA_SAFETY_CHECKS
266    {
267       struct log_ctx ctx;
268
269 #define TEST_MAGIC_SAFETY(fn, _msg)             \
270       ctx.msg = _msg;                           \
271       ctx.fnc = fn;                             \
272       ctx.did = EINA_FALSE
273
274       eina_log_print_cb_set(_eina_test_safety_print_cb, &ctx);
275
276 #ifdef SHOW_LOG
277       fprintf(stderr, "you should have a safety check failure below:\n");
278 #endif
279       TEST_MAGIC_SAFETY("eina_unicode_strnlen",
280                         "safety check failed: ustr == NULL");
281       fail_if(eina_unicode_strnlen(NULL,0) != 0);
282       fail_unless(ctx.did);
283
284       eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
285 #undef TEST_MAGIC_SAFETY
286    }
287 #endif
288
289    eina_shutdown();
290 }
291 END_TEST
292
293 START_TEST(eina_unicode_strdup_test)
294 {
295    Eina_Unicode *buf;
296
297    eina_init();
298
299    buf = eina_unicode_strdup(STR1);
300    fail_if(!buf);
301    fail_if(eina_unicode_strlen(buf) != eina_unicode_strlen(STR1));
302    fail_if(eina_unicode_strcmp(buf, STR1));
303    free(buf);
304
305    buf = eina_unicode_strdup(EMPTYSTR);
306    fail_if(!buf);
307    fail_if(buf[0] != 0);
308
309    eina_shutdown();
310 }
311 END_TEST
312
313 START_TEST(eina_unicode_strstr_test)
314 {
315    Eina_Unicode *buf;
316    Eina_Unicode on[] = { 'O', 'n', 0 };
317
318    eina_init();
319
320    buf = eina_unicode_strstr(STR1,on);
321    fail_if(!buf);
322    fail_if(buf != STR1 + 6);
323    fail_if(eina_unicode_strcmp(buf,on) != 0);
324
325    buf = eina_unicode_strstr(STR2,on);
326    fail_if(buf);
327
328    buf = eina_unicode_strstr(EMPTYSTR, on);
329    fail_if(buf);
330
331    buf = eina_unicode_strstr(STR1, EMPTYSTR);
332    fail_if(!buf);
333    fail_if(buf != STR1);
334
335    eina_shutdown();
336 }
337 END_TEST
338
339 START_TEST(eina_unicode_utf8)
340 {
341    int ind;
342    unsigned char ch;
343    eina_init();
344
345    /* Valid utf-8 cases */
346    /* First possible sequence of a certain length */
347    ind = 0;
348    fail_if((eina_unicode_utf8_get_next("\x00", &ind) != 0x00) ||
349            (ind != 0));
350    ind = 0;
351    fail_if((eina_unicode_utf8_get_next("\x01", &ind) != 0x01) ||
352            (ind != 1));
353    ind = 0;
354    fail_if((eina_unicode_utf8_get_next("\xC2\x80", &ind) != 0x80) ||
355            (ind != 2));
356    ind = 0;
357    fail_if((eina_unicode_utf8_get_next("\xE0\xA0\x80", &ind) != 0x800) ||
358            (ind != 3));
359    ind = 0;
360    fail_if((eina_unicode_utf8_get_next("\xF0\x90\x80\x80", &ind) != 0x10000) ||
361            (ind != 4));
362    ind = 0;
363    fail_if((eina_unicode_utf8_get_next("\xF8\x88\x80\x80\x80", &ind) != 0x200000) || (ind != 5));
364    ind = 0;
365    fail_if((eina_unicode_utf8_get_next("\xFC\x84\x80\x80\x80\x80", &ind) != 0x4000000) || (ind != 6));
366
367    /* Last possible sequence of a certain length */
368    ind = 0;
369    fail_if((eina_unicode_utf8_get_next("\x7F", &ind) != 0x7F) ||
370            (ind != 1));
371    ind = 0;
372    fail_if((eina_unicode_utf8_get_next("\xDF\xBF", &ind) != 0x7FF) ||
373            (ind != 2));
374    ind = 0;
375    fail_if((eina_unicode_utf8_get_next("\xEF\xBF\xBF", &ind) != 0xFFFF) ||
376            (ind != 3));
377    ind = 0;
378    fail_if((eina_unicode_utf8_get_next("\xF7\xBF\xBF\xBF", &ind) != 0x1FFFFF) ||
379            (ind != 4));
380    ind = 0;
381    fail_if((eina_unicode_utf8_get_next("\xFB\xBF\xBF\xBF\xBF", &ind) != 0x3FFFFFF) || (ind != 5));
382    ind = 0;
383    fail_if((eina_unicode_utf8_get_next("\xFD\xBF\xBF\xBF\xBF\xBF", &ind) != 0x7FFFFFFF) || (ind != 6));
384
385    /* Other boundary conditions */
386    ind = 0;
387    fail_if((eina_unicode_utf8_get_next("\xED\x9F\xBF", &ind) != 0xD7FF) ||
388            (ind != 3));
389    ind = 0;
390    fail_if((eina_unicode_utf8_get_next("\xEE\x80\x80", &ind) != 0xE000) ||
391            (ind != 3));
392    ind = 0;
393    fail_if((eina_unicode_utf8_get_next("\xEF\xBF\xBD", &ind) != 0xFFFD) ||
394            (ind != 3));
395    ind = 0;
396    fail_if((eina_unicode_utf8_get_next("\xF4\x8F\xBF\xBF", &ind) != 0x10FFFF) ||
397            (ind != 4));
398    ind = 0;
399    fail_if((eina_unicode_utf8_get_next("\xF4\x90\x80\x80", &ind) != 0x110000) ||
400            (ind != 4));
401
402    /* Error cases */
403    /* Standalone continuation bytes */
404    ind = 0;
405    fail_if((eina_unicode_utf8_get_next("\x80", &ind) != 0xDC80) ||
406            (ind != 1));
407    ind = 0;
408    fail_if((eina_unicode_utf8_get_next("\xBF", &ind) != 0xDCBF) ||
409            (ind != 1));
410    ind = 0;
411    fail_if((eina_unicode_utf8_get_next("\x80\xBF", &ind) != 0xDC80) ||
412            (ind != 1));
413    ind = 0;
414    fail_if((eina_unicode_utf8_get_next("\xBF\x80", &ind) != 0xDCBF) ||
415            (ind != 1));
416    /* All possible continuation bytes */
417    for (ch = 0x80 ; ch <= 0xBF ; ch++)
418      {
419         char buf[] = {ch, 0};
420         ind = 0;
421         fail_if((eina_unicode_utf8_get_next(buf, &ind) != (0xDC00 | ch)) ||
422                 (ind != 1));
423      }
424
425    /* Isolated starting sequences */
426 #define _FIRST_SEQUENCES(start, end) \
427    do \
428      { \
429         int i; \
430         char *buf = alloca(((end - start + 1) * 2) + 1); \
431         for (i = 0, ch = start ; ch <= end ; i++, ch++) \
432           { \
433              buf[i * 2] = ch; \
434              buf[(i * 2) + 1] = ' '; \
435           } \
436         ind = 0; \
437         for (i = 0, ch = start ; ch <= end ; ch++) \
438           { \
439              fail_if((eina_unicode_utf8_get_next(buf, &ind) != (0xDC00 | ch)) || \
440                      (ind != ++i)); \
441              fail_if((eina_unicode_utf8_get_next(buf, &ind) != 0x20) || \
442                      (ind != ++i)); \
443           } \
444      } \
445    while (0)
446    /* all first bytes of 2-byte sequences separated by spaces. */
447    _FIRST_SEQUENCES(0xC0, 0xDF);
448    /* all first bytes of 3-byte sequences separated by spaces. */
449    _FIRST_SEQUENCES(0xE0, 0xEF);
450    /* all first bytes of 4-byte sequences separated by spaces. */
451    _FIRST_SEQUENCES(0xF0, 0xF7);
452    /* all first bytes of 5-byte sequences separated by spaces. */
453    _FIRST_SEQUENCES(0xF8, 0xFB);
454    /* all first bytes of 6-byte sequences separated by spaces. */
455    _FIRST_SEQUENCES(0xFC, 0xFD);
456
457    /* Incomplete sequences first means the first utf8 char, len means
458     * the correct length */
459 #define _INCOMPLETE_SEQUENCES(first, conti, len) \
460    do \
461      { \
462         int i, j; \
463         char *buf = alloca(len + 1); \
464         i = 0; \
465         buf[i++] = first; \
466         for ( ; i < len ; i++) \
467           { \
468              Eina_Unicode val; \
469              for (j = 1 ; j < i ; j++) \
470                { \
471                   buf[j] = conti; \
472                } \
473              buf[j] = 0; \
474              ind = 0; \
475              fail_if( \
476                 (eina_unicode_utf8_get_next(buf, &ind) != (0xDC00 | first))); \
477              while ((val = eina_unicode_utf8_get_next(buf, &ind))) \
478                { \
479                   fail_if(val != (0xDC00 | conti)); \
480                } \
481              fail_if(ind != i); \
482           } \
483      } \
484    while (0)
485
486    /* Sequences with missing continuation */
487    _INCOMPLETE_SEQUENCES(0xC0, 0x81, 2);
488    _INCOMPLETE_SEQUENCES(0xDF, 0xBF, 2);
489    _INCOMPLETE_SEQUENCES(0xE0, 0x81, 3);
490    _INCOMPLETE_SEQUENCES(0xEF, 0xBF, 3);
491    _INCOMPLETE_SEQUENCES(0xF0, 0x81, 4);
492    _INCOMPLETE_SEQUENCES(0xF7, 0xBF, 4);
493    _INCOMPLETE_SEQUENCES(0xF8, 0x81, 5);
494    _INCOMPLETE_SEQUENCES(0xFB, 0xBF, 5);
495    _INCOMPLETE_SEQUENCES(0xFC, 0x81, 6);
496    _INCOMPLETE_SEQUENCES(0xFD, 0xBF, 6);
497
498    /* Impossible bytes */
499    ind = 0;
500    fail_if((eina_unicode_utf8_get_next("\xFE", &ind) != 0xDCFE) ||
501            (ind != 1));
502    ind = 0;
503    fail_if((eina_unicode_utf8_get_next("\xFF", &ind) != 0xDCFF) ||
504            (ind != 1));
505
506    /* Overlong sequences */
507    ind = 0;
508    fail_if((eina_unicode_utf8_get_next("\xC0\xAF", &ind) != 0xDCC0) ||
509            (ind != 1));
510    ind = 0;
511    fail_if((eina_unicode_utf8_get_next("\xE0\x80\xAF", &ind) != 0xDCE0) ||
512            (ind != 1));
513    ind = 0;
514    fail_if((eina_unicode_utf8_get_next("\xF0\x80\x80\xAF", &ind) != 0xDCF0) ||
515            (ind != 1));
516    ind = 0;
517    fail_if((eina_unicode_utf8_get_next("\xF8\x80\x80\x80\xAF", &ind) != 0xDCF8) ||
518            (ind != 1));
519    ind = 0;
520    fail_if((eina_unicode_utf8_get_next("\xFC\x80\x80\x80\x80\xAF", &ind) != 0xDCFC) ||
521            (ind != 1));
522
523    /* Maximum overlong sequences */
524    ind = 0;
525    fail_if((eina_unicode_utf8_get_next("\xC1\xBF", &ind) != 0xDCC1) ||
526            (ind != 1));
527    ind = 0;
528    fail_if((eina_unicode_utf8_get_next("\xE0\x9F\xBF", &ind) != 0xDCE0) ||
529            (ind != 1));
530    ind = 0;
531    fail_if((eina_unicode_utf8_get_next("\xF0\x8F\xBF\xBF", &ind) != 0xDCF0) ||
532            (ind != 1));
533    ind = 0;
534    fail_if((eina_unicode_utf8_get_next("\xF8\x87\xBF\xBF\xBF", &ind) != 0xDCF8) ||
535            (ind != 1));
536    ind = 0;
537    fail_if((eina_unicode_utf8_get_next("\xFC\x83\xBF\xBF\xBF\xBF", &ind) != 0xDCFC) ||
538            (ind != 1));
539    /* Add some more error cases here */
540
541    /* Just to cover prev/len. General utf-8 parsing was covered above */
542    fail_if(eina_unicode_utf8_get_len("\xF4\x90\x80\x80\xF4\x8F\xBF\xBF") != 2);
543    ind = 0;
544    fail_if((eina_unicode_utf8_get_prev("\xED\x9F\xBF", &ind) != 0xD7FF) ||
545            (ind != 0));
546    ind = 3;
547    fail_if((eina_unicode_utf8_get_prev("\xED\x9F\xBF", &ind) != 0x00) ||
548            (ind != 0));
549
550    eina_shutdown();
551 }
552 END_TEST
553
554 START_TEST(eina_unicode_utf8_conversion)
555 {
556    Eina_Unicode uni_in[] = {0x5D0, 0xFDF6, 0xDC80, 0x1F459, 0x3FFFFFF,
557         0x7FFFFFFF, 'a', 'b', 'c', 0};
558    Eina_Unicode *uni_out;
559    char c_in[] = "\xD7\x90""\xEF\xB7\xB6""\x80""\xF0\x9F\x91\x99"
560       "\xFB\xBF\xBF\xBF\xBF""\xFD\xBF\xBF\xBF\xBF\xBF""abc";
561    char *c_out;
562    int len;
563
564    eina_init();
565
566    uni_out = eina_unicode_utf8_to_unicode(c_in, &len);
567    fail_if((len != 9) || eina_unicode_strcmp(uni_in, uni_out));
568    free(uni_out);
569
570    c_out = eina_unicode_unicode_to_utf8(uni_in, &len);
571    fail_if((len != 24) || strcmp(c_in, c_out));
572    free(c_out);
573
574    eina_shutdown();
575 }
576 END_TEST
577
578 void
579 eina_test_ustr(TCase *tc)
580 {
581    printf("ustr test\n");
582    tcase_add_test(tc,eina_unicode_strcmp_test);
583    tcase_add_test(tc,eina_unicode_strcpy_test);
584    tcase_add_test(tc,eina_unicode_strncpy_test);
585    tcase_add_test(tc,eina_ustr_strlen_test);
586    tcase_add_test(tc,eina_unicode_strnlen_test);
587    tcase_add_test(tc,eina_unicode_strdup_test);
588    tcase_add_test(tc,eina_unicode_strstr_test);
589    tcase_add_test(tc,eina_unicode_utf8);
590    tcase_add_test(tc,eina_unicode_utf8_conversion);
591
592 }
593