source: yaz/trunk/fuentes/test/test_icu.c @ 255

Last change on this file since 255 was 255, checked in by mabarracus, 4 years ago

added trusty code to xenial

File size: 27.9 KB
Line 
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
5
6/* DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8 */
7
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#define USE_TIMING 0
14#if USE_TIMING
15#include <yaz/timing.h>
16#endif
17
18#include <yaz/test.h>
19#include <yaz/log.h>
20#include <yaz/wrbuf.h>
21
22#if YAZ_HAVE_ICU
23#include <yaz/icu_I18N.h>
24#include <unicode/uclean.h>
25
26#if YAZ_POSIX_THREADS
27#include <pthread.h>
28#endif
29
30#if YAZ_HAVE_XML2
31#include <libxml/xmlmemory.h>
32#endif
33
34#include <string.h>
35#include <stdlib.h>
36
37#define MAX_KEY_SIZE 256
38struct icu_termmap
39{
40    uint8_t sort_key[MAX_KEY_SIZE]; /* standard C string '\0' terminated */
41    char disp_term[MAX_KEY_SIZE];  /* standard C utf-8 string */
42};
43
44
45static int icu_termmap_cmp(const void *vp1, const void *vp2)
46{
47    struct icu_termmap *itmp1 = *(struct icu_termmap **) vp1;
48    struct icu_termmap *itmp2 = *(struct icu_termmap **) vp2;
49
50    int cmp = 0;
51
52    cmp = strcmp((const char *)itmp1->sort_key,
53                 (const char *)itmp2->sort_key);
54    return cmp;
55}
56
57
58static int test_icu_casemap(const char *locale, char action,
59                            const char *src8cstr, const char *chk8cstr)
60{
61    int success = 0;
62    UErrorCode status = U_ZERO_ERROR;
63
64    struct icu_buf_utf8 *src8 = icu_buf_utf8_create(0);
65    struct icu_buf_utf8 *dest8 = icu_buf_utf8_create(0);
66    struct icu_buf_utf16 *src16 = icu_buf_utf16_create(0);
67    struct icu_buf_utf16 *dest16 = icu_buf_utf16_create(0);
68
69
70    int src8cstr_len = strlen(src8cstr);
71    int chk8cstr_len = strlen(chk8cstr);
72
73    /* converting to UTF16 */
74    icu_utf16_from_utf8_cstr(src16, src8cstr, &status);
75
76    /* perform case mapping */
77    icu_utf16_casemap(dest16, src16, locale, action, &status);
78
79    /* converting to UTF8 */
80    icu_utf16_to_utf8(dest8, dest16, &status);
81
82    /* determine success */
83    if (dest8->utf8
84        && (dest8->utf8_len == strlen(chk8cstr))
85        && !strcmp(chk8cstr, (const char *) dest8->utf8))
86        success = 1;
87    else
88        success = 0;
89
90    /* report failures */
91    if (!success)
92    {
93        yaz_log(YLOG_WARN, "test_icu_casemap failed");
94        yaz_log(YLOG_LOG, "Original string:   '%s' (%d)",
95                src8cstr, src8cstr_len);
96        yaz_log(YLOG_LOG, "icu_casemap '%s:%c' '%s' (%d)",
97                locale, action, dest8->utf8, dest8->utf8_len);
98        yaz_log(YLOG_LOG, "expected string:   '%s' (%d)",
99                chk8cstr, chk8cstr_len);
100    }
101
102    /* clean the buffers */
103    icu_buf_utf8_destroy(src8);
104    icu_buf_utf8_destroy(dest8);
105    icu_buf_utf16_destroy(src16);
106    icu_buf_utf16_destroy(dest16);
107
108    return success;
109}
110
111static void check_icu_casemap(void)
112{
113    /* Locale 'en' */
114
115    /* successful tests */
116    YAZ_CHECK(test_icu_casemap("en", 'l',
117                               "A ReD fOx hunTS sQUirriLs",
118                               "a red fox hunts squirrils"));
119
120    YAZ_CHECK(test_icu_casemap("en", 'u',
121                               "A ReD fOx hunTS sQUirriLs",
122                               "A RED FOX HUNTS SQUIRRILS"));
123
124    YAZ_CHECK(test_icu_casemap("en", 'f',
125                               "A ReD fOx hunTS sQUirriLs",
126                               "a red fox hunts squirrils"));
127
128    YAZ_CHECK(test_icu_casemap("en", 't',
129                               "A ReD fOx hunTS sQUirriLs",
130                               "A Red Fox Hunts Squirrils"));
131
132    /* Locale 'da' */
133
134    /* success expected */
135    YAZ_CHECK(test_icu_casemap("da", 'l',
136                               "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN",
137                               "åh æble, øs fløde i åen efter blåbærgrøden"));
138
139    YAZ_CHECK(test_icu_casemap("da", 'u',
140                               "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN",
141                               "ÅH ÆBLE, ØS FLØDE I ÅEN EFTER BLÅBÆRGRØDEN"));
142
143    YAZ_CHECK(test_icu_casemap("da", 'f',
144                               "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN",
145                               "åh æble, øs fløde i åen efter blåbærgrøden"));
146
147    YAZ_CHECK(test_icu_casemap("da", 't',
148                               "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN",
149                               "Åh Æble, Øs Fløde I Åen Efter Blåbærgrøden"));
150
151    /* Locale 'de' */
152
153    /* success expected */
154    YAZ_CHECK(test_icu_casemap("de", 'l',
155                               "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
156                               "zwölf ärgerliche würste rollen über die straße"));
157
158    YAZ_CHECK(test_icu_casemap("de", 'u',
159                               "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
160                               "ZWÖLF ÄRGERLICHE WÜRSTE ROLLEN ÜBER DIE STRASSE"));
161
162    YAZ_CHECK(test_icu_casemap("de", 'f',
163                               "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
164                               "zwölf ärgerliche würste rollen über die strasse"));
165
166    YAZ_CHECK(test_icu_casemap("de", 't',
167                               "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
168                               "Zwölf Ärgerliche Würste Rollen Über Die Straße"));
169
170}
171
172static int test_icu_sortmap(const char *locale, int src_list_len,
173                            const char **src_list, const char **chk_list)
174{
175    int success = 1;
176
177    UErrorCode status = U_ZERO_ERROR;
178
179    struct icu_buf_utf8 *buf8 = icu_buf_utf8_create(0);
180    struct icu_buf_utf16 *buf16 = icu_buf_utf16_create(0);
181
182    int i;
183
184    struct icu_termmap *list[src_list_len];
185
186    UCollator *coll = ucol_open(locale, &status);
187    icu_check_status(status);
188
189    if (U_FAILURE(status))
190        return 0;
191
192    /* assigning display terms and sort keys using buf 8 and buf16 */
193    for (i = 0; i < src_list_len; i++)
194    {
195
196        list[i] = (struct icu_termmap *) malloc(sizeof(struct icu_termmap));
197
198        /* copy display term */
199        strcpy(list[i]->disp_term, src_list[i]);
200
201        /* transforming to UTF16 */
202        icu_utf16_from_utf8_cstr(buf16, list[i]->disp_term, &status);
203        icu_check_status(status);
204
205        /* computing sortkeys */
206        icu_sortkey8_from_utf16(coll, buf8, buf16, &status);
207        icu_check_status(status);
208
209        /* assigning sortkeys */
210        memcpy(list[i]->sort_key, buf8->utf8, buf8->utf8_len);
211    }
212
213    /* do the sorting */
214    qsort(list, src_list_len, sizeof(struct icu_termmap *), icu_termmap_cmp);
215
216    /* checking correct sorting */
217    for (i = 0; i < src_list_len; i++)
218    {
219        if (0 != strcmp(list[i]->disp_term, chk_list[i])){
220            success = 0;
221        }
222    }
223
224    if (!success)
225    {
226        yaz_log(YLOG_LOG, "ERROR");
227        yaz_log(YLOG_LOG, "Input str:'%s':", locale);
228        for (i = 0; i < src_list_len; i++) {
229            yaz_log(YLOG_LOG, "  '%s'", list[i]->disp_term);
230        }
231        yaz_log(YLOG_LOG, "ICU sort: '%s':", locale);
232        for (i = 0; i < src_list_len; i++) {
233            yaz_log(YLOG_LOG, " '%s'", list[i]->disp_term);
234        }
235        yaz_log(YLOG_LOG, "Expected: '%s':", locale);
236        for (i = 0; i < src_list_len; i++) {
237            yaz_log(YLOG_LOG, " '%s'", chk_list[i]);
238        }
239    }
240
241    for (i = 0; i < src_list_len; i++)
242        free(list[i]);
243
244    ucol_close(coll);
245
246    icu_buf_utf8_destroy(buf8);
247    icu_buf_utf16_destroy(buf16);
248
249    return success;
250}
251
252static void check_icu_sortmap(void)
253{
254    /* successful tests */
255    size_t en_1_len = 6;
256    const char *en_1_src[6] = {"z", "K", "a", "A", "Z", "k"};
257    const char *en_1_cck[6] = {"a", "A", "k", "K", "z", "Z"};
258    YAZ_CHECK(test_icu_sortmap("en", en_1_len, en_1_src, en_1_cck));
259    YAZ_CHECK(test_icu_sortmap("en_AU", en_1_len, en_1_src, en_1_cck));
260    YAZ_CHECK(test_icu_sortmap("en_CA", en_1_len, en_1_src, en_1_cck));
261    YAZ_CHECK(test_icu_sortmap("en_GB", en_1_len, en_1_src, en_1_cck));
262    YAZ_CHECK(test_icu_sortmap("en_US", en_1_len, en_1_src, en_1_cck));
263
264    /* successful tests */
265    {
266        size_t da_1_len = 6;
267        const char *da_1_src[6] = {"z", "å", "o", "æ", "a", "ø"};
268        const char *da_1_cck[6] = {"a", "o", "z", "æ", "ø", "å"};
269        YAZ_CHECK(test_icu_sortmap("da", da_1_len, da_1_src, da_1_cck));
270        YAZ_CHECK(test_icu_sortmap("da_DK", da_1_len, da_1_src, da_1_cck));
271    }
272    /* successful tests */
273    {
274        size_t de_1_len = 9;
275        const char *de_1_src[9] = {"u", "ä", "o", "t", "s", "ß", "ü", "ö", "a"};
276        const char *de_1_cck[9] = {"a","ä", "o", "ö", "s", "ß", "t", "u", "ü"};
277        YAZ_CHECK(test_icu_sortmap("de", de_1_len, de_1_src, de_1_cck));
278        YAZ_CHECK(test_icu_sortmap("de_AT", de_1_len, de_1_src, de_1_cck));
279        YAZ_CHECK(test_icu_sortmap("de_DE", de_1_len, de_1_src, de_1_cck));
280    }
281}
282
283static int test_icu_normalizer(const char *rules8cstr,
284                               const char *src8cstr,
285                               const char *chk8cstr)
286{
287    int success = 0;
288
289    UErrorCode status = U_ZERO_ERROR;
290
291    struct icu_buf_utf16 *src16 = icu_buf_utf16_create(0);
292    struct icu_buf_utf16 *dest16 = icu_buf_utf16_create(0);
293    struct icu_buf_utf8 *dest8 = icu_buf_utf8_create(0);
294    struct icu_transform *transform
295        = icu_transform_create(rules8cstr, 'f', 0, &status);
296    icu_check_status(status);
297
298    icu_utf16_from_utf8_cstr(src16, src8cstr, &status);
299    icu_check_status(status);
300
301    icu_transform_trans(transform, dest16, src16, &status);
302    icu_check_status(status);
303
304    icu_utf16_to_utf8(dest8, dest16, &status);
305    icu_check_status(status);
306
307
308    if (!strcmp((const char *) dest8->utf8,
309               (const char *) chk8cstr))
310        success = 1;
311    else
312    {
313        success = 0;
314        yaz_log(YLOG_LOG, "Normalization");
315        yaz_log(YLOG_LOG, " Rules:      '%s'", rules8cstr);
316        yaz_log(YLOG_LOG, " Input:      '%s'", src8cstr);
317        yaz_log(YLOG_LOG, " Normalized: '%s'", dest8->utf8);
318        yaz_log(YLOG_LOG, " Expected:   '%s'", chk8cstr);
319    }
320
321    icu_transform_destroy(transform);
322    icu_buf_utf16_destroy(src16);
323    icu_buf_utf16_destroy(dest16);
324    icu_buf_utf8_destroy(dest8);
325
326    return success;
327}
328
329static void check_icu_normalizer(void)
330{
331    YAZ_CHECK(test_icu_normalizer("[:Punctuation:] Any-Remove",
332                                  "Don't shoot!",
333                                  "Dont shoot"));
334
335    YAZ_CHECK(test_icu_normalizer("[:Control:] Any-Remove",
336                                  "Don't\n shoot!",
337                                  "Don't shoot!"));
338
339    YAZ_CHECK(test_icu_normalizer("[:Decimal_Number:] Any-Remove",
340                                  "This is 4 you!",
341                                  "This is  you!"));
342
343    YAZ_CHECK(test_icu_normalizer("Lower; [:^Letter:] Remove",
344                                  "Don't shoot!",
345                                  "dontshoot"));
346
347    YAZ_CHECK(test_icu_normalizer("[:^Number:] Remove",
348                                  "Monday 15th of April",
349                                  "15"));
350
351    YAZ_CHECK(test_icu_normalizer("Lower;"
352                                  "[[:WhiteSpace:][:Punctuation:]] Remove",
353                                  " word4you? ",
354                                  "word4you"));
355
356    YAZ_CHECK(test_icu_normalizer("NFD; [:Nonspacing Mark:] Remove; NFC",
357                                  "à côté de l'alcôve ovoïde",
358                                  "a cote de l'alcove ovoide"));
359}
360
361static int test_icu_tokenizer(const char *locale, char action,
362                              const char *src8cstr, int count)
363{
364    int success = 1;
365
366    UErrorCode status = U_ZERO_ERROR;
367    struct icu_buf_utf16 *src16 = icu_buf_utf16_create(0);
368    struct icu_buf_utf16 *tkn16 = icu_buf_utf16_create(0);
369    struct icu_buf_utf8 *tkn8 = icu_buf_utf8_create(0);
370    struct icu_tokenizer *tokenizer = 0;
371    size_t org_start, org_len;
372
373    /* transforming to UTF16 */
374    icu_utf16_from_utf8_cstr(src16, src8cstr, &status);
375    icu_check_status(status);
376
377    /* set up tokenizer */
378    tokenizer = icu_tokenizer_create(locale, action, &status);
379    icu_check_status(status);
380    YAZ_CHECK(tokenizer);
381
382    /* attach text buffer to tokenizer */
383    icu_tokenizer_attach(tokenizer, src16, &status);
384    icu_check_status(status);
385
386    /* perform work on tokens */
387    while (icu_tokenizer_next_token(tokenizer, tkn16, &status,
388                                    &org_start, &org_len))
389    {
390        icu_check_status(status);
391
392        /* converting to UTF8 */
393        icu_utf16_to_utf8(tkn8, tkn16, &status);
394    }
395
396    if (count != icu_tokenizer_token_count(tokenizer))
397    {
398        success = 0;
399        yaz_log(YLOG_LOG, "Tokenizer '%s:%c' Error:", locale, action);
400        yaz_log(YLOG_LOG, " Input:  '%s'", src8cstr);
401        yaz_log(YLOG_LOG, " Tokens: %d", icu_tokenizer_token_count(tokenizer));
402        yaz_log(YLOG_LOG, " Expected: %d", count);
403    }
404
405    icu_tokenizer_destroy(tokenizer);
406    icu_buf_utf16_destroy(src16);
407    icu_buf_utf16_destroy(tkn16);
408    icu_buf_utf8_destroy(tkn8);
409
410    return success;
411}
412
413static void check_icu_tokenizer(void)
414{
415    const char *en_str
416        = "O Romeo, Romeo! wherefore art thou Romeo?";
417
418    YAZ_CHECK(test_icu_tokenizer("en", 's', en_str, 2));
419    YAZ_CHECK(test_icu_tokenizer("en", 'l', en_str, 7));
420    YAZ_CHECK(test_icu_tokenizer("en", 'w', en_str, 16));
421    YAZ_CHECK(test_icu_tokenizer("en", 'c', en_str, 41));
422
423    {
424        const char *da_str
425            = "Blåbærtærte. Denne kage stammer fra Finland. "
426            "Den er med blåbær, men alle sommerens forskellige bær kan bruges.";
427
428        YAZ_CHECK(test_icu_tokenizer("da", 's', da_str, 3));
429        YAZ_CHECK(test_icu_tokenizer("dar", 'l', da_str, 17));
430        YAZ_CHECK(test_icu_tokenizer("da", 'w', da_str, 37));
431        YAZ_CHECK(test_icu_tokenizer("da", 'c', da_str, 110));
432    }
433}
434
435static void check_icu_chain(void)
436{
437    const char *en_str
438        = "O Romeo, Romeo! wherefore art thou\t Romeo?";
439
440    UErrorCode status = U_ZERO_ERROR;
441    struct icu_chain *chain = 0;
442
443    const char *xml_str = "<icu locale=\"en\">"
444        "<transform rule=\"[:Control:] Any-Remove\"/>"
445        "<tokenize rule=\"l\"/>"
446        "<transform rule=\"[[:WhiteSpace:][:Punctuation:]] Remove\"/>"
447        "<display/>"
448        "<casemap rule=\"l\"/>"
449        "</icu>";
450
451
452    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
453    xmlNode *xml_node = xmlDocGetRootElement(doc);
454    YAZ_CHECK(xml_node);
455
456    chain = icu_chain_xml_config(xml_node, 0, &status);
457
458    xmlFreeDoc(doc);
459    YAZ_CHECK(chain);
460    if (!chain)
461        return;
462
463    YAZ_CHECK(icu_chain_assign_cstr(chain, en_str, &status));
464
465    while (icu_chain_next_token(chain, &status))
466    {
467        yaz_log(YLOG_LOG, "%d '%s' '%s'",
468                icu_chain_token_number(chain),
469                icu_chain_token_norm(chain),
470                icu_chain_token_display(chain));
471    }
472
473    YAZ_CHECK_EQ(icu_chain_token_number(chain), 7);
474
475
476    YAZ_CHECK(icu_chain_assign_cstr(chain, "what is this?", &status));
477
478    while (icu_chain_next_token(chain, &status))
479    {
480        yaz_log(YLOG_LOG, "%d '%s' '%s'",
481                icu_chain_token_number(chain),
482                icu_chain_token_norm(chain),
483                icu_chain_token_display(chain));
484    }
485
486
487    YAZ_CHECK_EQ(icu_chain_token_number(chain), 3);
488
489    icu_chain_destroy(chain);
490}
491
492
493static void check_bug_1140(void)
494{
495    UErrorCode status = U_ZERO_ERROR;
496    struct icu_chain *chain = 0;
497
498    const char *xml_str = "<icu locale=\"en\">"
499
500        /* if the first rule is normalize instead. Then it works */
501#if 0
502        "<transform rule=\"[:Control:] Any-Remove\"/>"
503#endif
504        "<tokenize rule=\"l\"/>"
505        "<transform rule=\"[[:WhiteSpace:][:Punctuation:]] Remove\"/>"
506        "<display/>"
507        "<casemap rule=\"l\"/>"
508        "</icu>";
509
510
511    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
512    xmlNode *xml_node = xmlDocGetRootElement(doc);
513    YAZ_CHECK(xml_node);
514
515    chain = icu_chain_xml_config(xml_node, 0, &status);
516
517    xmlFreeDoc(doc);
518    YAZ_CHECK(chain);
519    if (!chain)
520        return;
521
522    YAZ_CHECK(icu_chain_assign_cstr(
523                  chain,  "O Romeo, Romeo! wherefore art thou\t Romeo?",
524                  &status));
525
526    while (icu_chain_next_token(chain, &status))
527    {
528        ;
529        /* printf("%d '%s' '%s'\n",
530           icu_chain_token_number(chain),
531           icu_chain_token_norm(chain),
532           icu_chain_token_display(chain)); */
533    }
534
535
536    YAZ_CHECK_EQ(icu_chain_token_number(chain), 7);
537
538    YAZ_CHECK(icu_chain_assign_cstr(chain, "what is this?", &status));
539
540    while (icu_chain_next_token(chain, &status))
541    {
542        ;
543        /* printf("%d '%s' '%s'\n",
544           icu_chain_token_number(chain),
545           icu_chain_token_norm(chain),
546           icu_chain_token_display(chain)); */
547    }
548
549    /* we expect 'what' 'is' 'this', i.e. 3 tokens */
550    YAZ_CHECK_EQ(icu_chain_token_number(chain), 3);
551
552    icu_chain_destroy(chain);
553}
554
555
556static void check_chain_empty_token(void)
557{
558    UErrorCode status = U_ZERO_ERROR;
559    struct icu_chain *chain = 0;
560
561    const char *xml_str = "<icu locale=\"en\">"
562        "<tokenize rule=\"w\"/>"
563        "<transform rule=\"[[:WhiteSpace:][:Punctuation:]] Remove\"/>"
564        "</icu>";
565
566    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
567    xmlNode *xml_node = xmlDocGetRootElement(doc);
568    YAZ_CHECK(xml_node);
569
570    chain = icu_chain_xml_config(xml_node, 0, &status);
571
572    xmlFreeDoc(doc);
573    YAZ_CHECK(chain);
574
575    YAZ_CHECK(icu_chain_assign_cstr(
576                  chain,  "a string with 15 tokenss and 8 displays",
577                  &status));
578
579    while (icu_chain_next_token(chain, &status))
580    {
581        ;
582        /* printf("%d '%s' '%s'\n",
583           icu_chain_token_number(chain),
584           icu_chain_token_norm(chain),
585           icu_chain_token_display(chain)); */
586    }
587
588    YAZ_CHECK_EQ(icu_chain_token_number(chain), 15);
589
590    icu_chain_destroy(chain);
591}
592
593static void check_chain_empty_chain(void)
594{
595    UErrorCode status = U_ZERO_ERROR;
596    struct icu_chain *chain = 0;
597
598    const char *xml_str = "<icu locale=\"en\">"
599        "</icu>";
600
601    const char *src8 = "some 5487 weired !¤%&(/& sTuFf";
602    char *dest8 = 0;
603
604    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
605    xmlNode *xml_node = xmlDocGetRootElement(doc);
606    YAZ_CHECK(xml_node);
607
608    chain = icu_chain_xml_config(xml_node, 0, &status);
609
610    xmlFreeDoc(doc);
611    YAZ_CHECK(chain);
612
613    YAZ_CHECK(icu_chain_assign_cstr(
614                  chain,  src8,
615                  &status));
616
617    while (icu_chain_next_token(chain, &status))
618    {
619        ;
620        /* printf("%d '%s' '%s'\n",
621           icu_chain_token_number(chain),
622           icu_chain_token_norm(chain),
623           icu_chain_token_display(chain)); */
624    }
625
626    YAZ_CHECK_EQ(icu_chain_token_number(chain), 1);
627
628    dest8 = (char *) icu_chain_token_norm(chain);
629    YAZ_CHECK_EQ(strcmp(src8, dest8), 0);
630
631    icu_chain_destroy(chain);
632}
633
634static void check_icu_iter1(void)
635{
636    UErrorCode status = U_ZERO_ERROR;
637    struct icu_chain *chain = 0;
638    xmlNode *xml_node;
639    yaz_icu_iter_t iter;
640
641    const char *xml_str = "<icu locale=\"en\">"
642        "<tokenize rule=\"w\"/>"
643        "<transform rule=\"[[:WhiteSpace:][:Punctuation:]] Remove\"/>"
644        "</icu>";
645
646    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
647    YAZ_CHECK(doc);
648    if (!doc)
649        return;
650    xml_node = xmlDocGetRootElement(doc);
651    YAZ_CHECK(xml_node);
652    if (!xml_node)
653        return ;
654
655    chain = icu_chain_xml_config(xml_node, 1, &status);
656
657    xmlFreeDoc(doc);
658    YAZ_CHECK(chain);
659
660    iter = icu_iter_create(chain);
661    icu_iter_first(iter, "a string with 15 tokens and 8 displays");
662    YAZ_CHECK(iter);
663    if (!iter)
664        return;
665    while (icu_iter_next(iter))
666    {
667        yaz_log(YLOG_LOG, "[%s]", icu_iter_get_norm(iter));
668    }
669    icu_iter_destroy(iter);
670    icu_chain_destroy(chain);
671}
672
673static int test_iter(struct icu_chain *chain, const char *input,
674                     const char *expected)
675{
676    yaz_icu_iter_t iter = icu_iter_create(chain);
677    WRBUF result, second, sort_result;
678    int success = 1;
679
680    if (!iter)
681    {
682        yaz_log(YLOG_WARN, "test_iter: input=%s !iter", input);
683        return 0;
684    }
685
686    if (icu_iter_next(iter))
687    {
688        yaz_log(YLOG_WARN, "test_iter: expecting 0 before icu_iter_first");
689        return 0;
690    }
691
692    sort_result = wrbuf_alloc();
693    result = wrbuf_alloc();
694    icu_iter_first(iter, input);
695    while (icu_iter_next(iter))
696    {
697        const char *sort_str = icu_iter_get_sortkey(iter);
698        if (sort_str)
699        {
700            wrbuf_puts(sort_result, "[");
701            wrbuf_puts_escaped(sort_result, sort_str);
702            wrbuf_puts(sort_result, "]");
703        }
704        else
705        {
706            wrbuf_puts(sort_result, "[NULL]");
707        }
708        wrbuf_puts(result, "[");
709        wrbuf_puts(result, icu_iter_get_norm(iter));
710        wrbuf_puts(result, "]");
711    }
712    yaz_log(YLOG_LOG, "sortkey=%s", wrbuf_cstr(sort_result));
713    second = wrbuf_alloc();
714    icu_iter_first(iter, input);
715    while (icu_iter_next(iter))
716    {
717        wrbuf_puts(second, "[");
718        wrbuf_puts(second, icu_iter_get_norm(iter));
719        wrbuf_puts(second, "]");
720    }
721
722    icu_iter_destroy(iter);
723
724    if (strcmp(expected, wrbuf_cstr(result)))
725    {
726        yaz_log(YLOG_WARN, "test_iter: input=%s expected=%s got=%s",
727                input, expected, wrbuf_cstr(result));
728        success = 0;
729    }
730
731    if (strcmp(expected, wrbuf_cstr(second)))
732    {
733        yaz_log(YLOG_WARN, "test_iter: input=%s expected=%s got=%s (2nd)",
734                input, expected, wrbuf_cstr(second));
735        success = 0;
736    }
737
738    wrbuf_destroy(result);
739    wrbuf_destroy(second);
740    wrbuf_destroy(sort_result);
741    return success;
742}
743
744static void *iter_thread(void *p)
745{
746    struct icu_chain *chain = (struct icu_chain *) p;
747    int i;
748
749    for (i = 0; i < 1000; i++)
750    {
751        YAZ_CHECK(test_iter(chain, "Adobe Acrobat Reader, 1991-1999.",
752                            "[adobe][acrobat][reader][1991][][1999][]"));
753    }
754    return 0;
755}
756
757static void check_iter_threads(struct icu_chain *chain)
758{
759#if YAZ_POSIX_THREADS
760#define NO_THREADS 1
761
762    pthread_t t[NO_THREADS];
763    int i;
764
765    for (i = 0; i < NO_THREADS; i++)
766        pthread_create(t + i, 0, iter_thread, chain);
767
768    for (i = 0; i < NO_THREADS; i++)
769        pthread_join(t[i], 0);
770#endif
771}
772
773static void check_icu_iter2(void)
774{
775    UErrorCode status = U_ZERO_ERROR;
776    struct icu_chain *chain = 0;
777    xmlNode *xml_node;
778
779    const char *xml_str = "<icu locale=\"en\">"
780        "<transform rule=\"[:Control:] Any-Remove\"/>"
781        "<tokenize rule=\"l\"/>"
782        "<tokenize rule=\"w\"/>"
783        "<transform rule=\"[[:WhiteSpace:][:Punctuation:]] Remove\"/>"
784        "<display/>"
785        "<casemap rule=\"l\"/>"
786        "</icu>";
787
788    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
789    YAZ_CHECK(doc);
790    if (!doc)
791        return;
792    xml_node = xmlDocGetRootElement(doc);
793    YAZ_CHECK(xml_node);
794    if (!xml_node)
795        return ;
796
797    chain = icu_chain_xml_config(xml_node, 1, &status);
798
799    xmlFreeDoc(doc);
800    YAZ_CHECK(chain);
801    if (!chain)
802        return;
803
804    YAZ_CHECK(test_iter(chain, "Adobe Acrobat Reader, 1991-1999.",
805                        "[adobe][acrobat][reader][1991][][1999][]"));
806
807    YAZ_CHECK(test_iter(chain, "Νόταρης, Γιάννης Σωτ",
808                        "[νόταρης][γιάννης][σωτ]"));
809
810    check_iter_threads(chain);
811
812    icu_chain_destroy(chain);
813}
814
815static void check_icu_iter3(void)
816{
817    UErrorCode status = U_ZERO_ERROR;
818    struct icu_chain *chain = 0;
819    xmlNode *xml_node;
820
821    const char *xml_str =
822        "<icu_chain id=\"sort\" locale=\"el\">\n"
823        "<transform rule=\"[:Control:] Any-Remove\"/>\n"
824        "<transform rule=\"[[:Control:][:WhiteSpace:][:Punctuation:]] Remove\"/>\n"
825        "<transform rule=\"NFD; [:Nonspacing Mark:] Remove; NFC\"/>\n"
826        "<casemap rule=\"l\"/>\n"
827        "<display/>\n"
828        "</icu_chain>\n";
829
830    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
831    YAZ_CHECK(doc);
832    if (!doc)
833        return;
834    xml_node = xmlDocGetRootElement(doc);
835    YAZ_CHECK(xml_node);
836    if (!xml_node)
837        return ;
838
839    chain = icu_chain_xml_config(xml_node, 1, &status);
840
841    xmlFreeDoc(doc);
842    YAZ_CHECK(chain);
843    if (!chain)
844        return;
845
846    YAZ_CHECK(test_iter(chain, "Adobe Acrobat Reader, 1991-1999.",
847                        "[adobeacrobatreader19911999]"));
848
849    YAZ_CHECK(test_iter(chain, "Νόταρης, Γιάννης Σωτ",
850                        "[νοταρηςγιαννηςσωτ]"));
851
852    icu_chain_destroy(chain);
853}
854
855
856static void check_icu_iter4(void)
857{
858    UErrorCode status = U_ZERO_ERROR;
859    struct icu_chain *chain = 0;
860    xmlNode *xml_node;
861
862    const char *xml_str = "<icu locale=\"en\">"
863        "<transform rule=\"[:Control:] Any-Remove\"/>"
864        "<tokenize rule=\"l\"/>"
865        "<tokenize rule=\"w\"/>"
866        "<transform rule=\"[[:WhiteSpace:][:Punctuation:]] Remove\"/>"
867        "<display/>"
868        "<casemap rule=\"l\"/>"
869        "<join rule=\"\"/>"
870        "</icu>";
871
872    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
873    YAZ_CHECK(doc);
874    if (!doc)
875        return;
876    xml_node = xmlDocGetRootElement(doc);
877    YAZ_CHECK(xml_node);
878    if (!xml_node)
879        return ;
880
881    chain = icu_chain_xml_config(xml_node, 1, &status);
882
883    xmlFreeDoc(doc);
884    YAZ_CHECK(chain);
885    if (!chain)
886        return;
887
888    YAZ_CHECK(test_iter(chain, "Adobe Acrobat Reader, 1991-1999.",
889                        "[adobeacrobatreader19911999]"));
890
891    YAZ_CHECK(test_iter(chain, "Νόταρης, Γιάννης Σωτ",
892                        "[νόταρηςγιάννηςσωτ]"));
893
894    // check_iter_threads(chain);
895
896    icu_chain_destroy(chain);
897}
898
899
900static void check_norm(void)
901{
902    UErrorCode status = U_ZERO_ERROR;
903    struct icu_chain *chain = 0;
904    xmlNode *xml_node;
905    yaz_icu_iter_t it;
906
907    const char *xml_str =
908        "  <icu_chain id=\"relevance\" locale=\"en\">"
909        "    <transform rule=\"[:Control:] Any-Remove\"/>"
910        "    <tokenize rule=\"l\"/>"
911        "    <transform rule=\"[[:WhiteSpace:][:Punctuation:]`] Remove\"/>"
912        "    <casemap rule=\"l\"/>"
913        "  </icu_chain>";
914
915    xmlDoc *doc = xmlParseMemory(xml_str, strlen(xml_str));
916    YAZ_CHECK(doc);
917    if (!doc)
918        return;
919    xml_node = xmlDocGetRootElement(doc);
920    YAZ_CHECK(xml_node);
921    if (!xml_node)
922        return ;
923    chain = icu_chain_xml_config(xml_node, 1, &status);
924
925    it = icu_iter_create(chain);
926    if (it)
927    {
928        icu_iter_first(it, " y😄");
929        while (icu_iter_next(it))
930        {
931            const char *norm_str = icu_iter_get_norm(it);
932            size_t start, len;
933
934            YAZ_CHECK(norm_str);
935            if (norm_str)
936                yaz_log(YLOG_LOG, "norm_str len=%ld=%s",
937                        (long) strlen(norm_str), norm_str);
938            icu_iter_get_org_info(it, &start, &len);
939            YAZ_CHECK(start <= 1000);
940            YAZ_CHECK(len <= 1000);
941        }
942
943        icu_iter_first(it, "\n y😄");
944        while (icu_iter_next(it))
945        {
946            const char *norm_str = icu_iter_get_norm(it);
947            size_t start, len;
948
949            YAZ_CHECK(norm_str);
950            if (norm_str)
951                yaz_log(YLOG_LOG, "norm_str len=%ld=%s",
952                        (long) strlen(norm_str), norm_str);
953            icu_iter_get_org_info(it, &start, &len);
954            YAZ_CHECK(start <= 1000);
955            YAZ_CHECK(len <= 1000);
956        }
957    }
958    icu_iter_destroy(it);
959    icu_chain_destroy(chain);
960    xmlFreeDoc(doc);
961}
962#endif /* YAZ_HAVE_ICU */
963
964int main(int argc, char **argv)
965{
966    YAZ_CHECK_INIT(argc, argv);
967    YAZ_CHECK_LOG();
968
969#if YAZ_HAVE_ICU
970
971    check_icu_casemap();
972    check_icu_sortmap();
973    check_icu_normalizer();
974    check_icu_tokenizer();
975    check_icu_chain();
976    check_chain_empty_token();
977    check_chain_empty_chain();
978    check_icu_iter1();
979    check_icu_iter2();
980    check_icu_iter3();
981    check_icu_iter4();
982
983    check_bug_1140();
984    check_norm();
985
986    u_cleanup();
987#if YAZ_HAVE_XML2
988    xmlCleanupParser();
989#endif
990
991#else /* YAZ_HAVE_ICU */
992
993    yaz_log(YLOG_LOG, "ICU unit tests omitted");
994    YAZ_CHECK(0 == 0);
995
996#endif /* YAZ_HAVE_ICU */
997
998    YAZ_CHECK_TERM;
999}
1000
1001/*
1002 * Local variables:
1003 * c-basic-offset: 4
1004 * c-file-style: "Stroustrup"
1005 * indent-tabs-mode: nil
1006 * End:
1007 * vim: shiftwidth=4 tabstop=8 expandtab
1008 */
1009
Note: See TracBrowser for help on using the repository browser.