moved working ICU sorting into YAZ unittest test_icu_I18N.c
[pazpar2-moved-to-github.git] / src / test_icu_I18N.c
1 /* $Id: test_icu_I18N.c,v 1.8 2007-05-07 09:31:36 marc Exp $
2    Copyright (c) 2006-2007, Index Data.
3
4 This file is part of Pazpar2.
5
6 Pazpar2 is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Pazpar2; see the file LICENSE.  If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20  */
21
22 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
23  
24
25 #if HAVE_CONFIG_H
26 #include "cconfig.h"
27 #endif
28
29 #define USE_TIMING 0
30 #if USE_TIMING
31 #include <yaz/timing.h>
32 #endif
33
34 #include <yaz/test.h>
35
36
37
38 #ifdef HAVE_ICU
39 #include "icu_I18N.h"
40 #include <string.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43
44
45 #include <unicode/ustring.h>  /* some more string fcns*/
46 #include <unicode/uchar.h>    /* char names           */
47 //#include <unicode/ustdio.h>
48 //#include <unicode/utypes.h>   /* Basic ICU data types */
49 #include <unicode/ucol.h> 
50
51
52 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
53
54
55 #define MAX_KEY_SIZE 256
56
57 struct icu_termmap
58 {
59   uint8_t sort_key[MAX_KEY_SIZE]; // standard C string '\0' terminated
60   char disp_term[MAX_KEY_SIZE];  // standard C utf-8 string
61 };
62
63
64
65 int icu_termmap_cmp(const void *vp1, const void *vp2)
66 {
67   struct icu_termmap *itmp1 = *(struct icu_termmap **) vp1;
68   struct icu_termmap *itmp2 = *(struct icu_termmap **) vp2;
69
70   int cmp = 0;
71     
72   cmp = strcmp((const char *)itmp1->sort_key, 
73                (const char *)itmp2->sort_key);
74   return cmp;
75 }
76
77
78
79 #if 0
80
81 int test_icu_casemap(const char * locale, char action,
82                      const char * src8, const char * check8)
83 {
84     NMEM nmem = nmem_create();    
85     size_t buf_cap = 128;
86     char buf[buf_cap];
87     const char * dest8 = 0;
88     size_t dest8_len = 0;
89     //size_t src8_len = strlen(src8);
90     int sucess = 0;
91
92     //printf("original string:   '%s' (%d)\n", src8, (int) src8_len);
93
94     //these shall succeed
95     dest8 = icu_casemap(nmem, buf, buf_cap, &dest8_len,
96                         src8, locale, action);
97
98
99     //printf("icu_casemap '%s:%c' '%s' (%d)\n", 
100     //       locale, action, dest8, (int) dest8_len);
101
102     if (dest8 
103         && (dest8_len == strlen(check8))
104         && !strcmp(check8, dest8))
105         sucess = dest8_len;
106
107     nmem_destroy(nmem);
108
109     return sucess;
110 }
111
112 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
113
114 void test_icu_I18N_casemap(int argc, char **argv)
115 {
116
117     // Locale 'en'
118
119     // sucessful tests
120     YAZ_CHECK(test_icu_casemap("en", 'l',
121                                "A ReD fOx hunTS sQUirriLs", 
122                                "a red fox hunts squirrils"));
123     
124     YAZ_CHECK(test_icu_casemap("en", 'u',
125                                "A ReD fOx hunTS sQUirriLs", 
126                                "A RED FOX HUNTS SQUIRRILS"));
127     
128     YAZ_CHECK(test_icu_casemap("en", 'f',
129                                "A ReD fOx hunTS sQUirriLs", 
130                                "a red fox hunts squirrils"));
131     
132     // this one fails and needs more investigation ..
133     YAZ_CHECK(0 == test_icu_casemap("en", 't',
134                                "A ReD fOx hunTS sQUirriLs", 
135                                "A Red Fox Hunts Squirrils"));
136
137
138     // Locale 'da'
139
140     // sucess expected    
141     YAZ_CHECK(test_icu_casemap("da", 'l',
142                                "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN", 
143                                "åh æble, øs fløde i åen efter blåbærgrøden"));
144
145     YAZ_CHECK(test_icu_casemap("da", 'u',
146                                "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN", 
147                                "ÅH ÆBLE, ØS FLØDE I ÅEN EFTER BLÅBÆRGRØDEN"));
148
149     YAZ_CHECK(test_icu_casemap("da", 'f',
150                                "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN", 
151                                "åh æble, øs fløde i åen efter blåbærgrøden"));
152
153     YAZ_CHECK(test_icu_casemap("da", 't',
154                                "åh ÆbLE, øs fLØde i Åen efter bLåBærGRødeN", 
155                                "Åh Æble, Øs Fløde I Åen Efter Blåbærgrøden"));
156
157     // Locale 'de'
158
159     // sucess expected    
160     YAZ_CHECK(test_icu_casemap("de", 'l',
161                           "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
162                           "zwölf ärgerliche würste rollen über die straße"));
163
164     YAZ_CHECK(test_icu_casemap("de", 'u',
165                            "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
166                            "ZWÖLF ÄRGERLICHE WÜRSTE ROLLEN ÜBER DIE STRASSE"));
167
168     YAZ_CHECK(test_icu_casemap("de", 'f',
169                            "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
170                            "zwölf ärgerliche würste rollen über die strasse"));
171
172     YAZ_CHECK(test_icu_casemap("de", 't',
173                            "zWÖlf ärgerliche Würste rollen ÜBer die StRAße",
174                            "Zwölf Ärgerliche Würste Rollen Über Die Straße"));
175
176 }
177
178
179 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
180
181 void test_icu_I18N_casemap_failures(int argc, char **argv)
182 {
183
184     size_t buf_cap = 128;
185     char buf[buf_cap];
186     size_t dest8_len = 0;
187     NMEM nmem = nmem_create();
188     char * dest8 = 0;
189
190     const char * src8 =  "A ReD fOx hunTS sQUirriLs";
191     //size_t src8_len = strlen(src8);
192     
193     //printf("original string:   '%s' (%d)\n", src8, (int) src8_len);
194
195     // some calling error needs investigation
196     dest8 = icu_casemap(nmem, buf, buf_cap, &dest8_len,
197                         src8, "en", 't');
198     YAZ_CHECK(0 == dest8_len);
199     //printf("icu_casemap 'en:t' '%s' (%d)\n", dest8, (int) dest8_len);
200
201
202     // attention: does not fail even if no locale 'xy_zz' defined
203     // it seems to default to english locale
204     dest8 = icu_casemap(nmem, buf, buf_cap, &dest8_len,
205                         src8, "zz_abc", 'l');
206     YAZ_CHECK(dest8_len);
207     //printf("icu_casemap 'zz:l' '%s' (%d)\n", dest8, (int) dest8_len);
208
209
210     // shall fail - no buf buffer defined
211     dest8 = icu_casemap(nmem, 0, buf_cap, &dest8_len,
212                         src8, "en", 'l');
213     YAZ_CHECK(0 == dest8_len);
214     //printf("icu_casemap 'en:l' '%s' (%d)\n", dest8, (int) dest8_len);
215
216     // shall fail - no buf_cap  defined
217     dest8 = icu_casemap(nmem, buf, 0, &dest8_len,
218                         src8, "en", 'l');
219     YAZ_CHECK(0 == dest8_len);
220     //printf("icu_casemap 'en:l' '%s' (%d)\n", dest8, (int) dest8_len);
221
222     // shall fail - no action 'x' defined
223     dest8 = icu_casemap(nmem, buf, buf_cap, &dest8_len,
224                         src8, "en", 'x');
225     YAZ_CHECK(0 == dest8_len);
226     //printf("icu_casemap 'en:x' '%s' (%d)\n", dest8, (int) dest8_len);
227
228     nmem_destroy(nmem);
229 }
230
231 #endif
232
233 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
234
235 #if 0
236 int test_icu_sortmap(const char * locale, size_t list_len,
237                      const char ** src8_list, const char ** check8_list)
238 {
239     int sucess = 1;
240
241     size_t i = 0;
242
243
244     NMEM nmem = nmem_create();    
245     size_t buf_cap = 128;
246     char buf[buf_cap];
247     struct icu_termmap ** dest8_list 
248         = nmem_malloc(nmem, sizeof(struct icu_termmap *) * list_len);
249     //size_t dest8_len = 0;
250     //size_t src8_len = strlen(src8);
251
252     // initializing icu_termmap
253     for (i = 0; i < list_len; i++){
254         dest8_list[i] = icu_termmap_create(nmem);
255         dest8_list[i]->norm_term = nmem_strdup(nmem, src8_list[i]); 
256         dest8_list[i]->disp_term = nmem_strdup(nmem, src8_list[i]);
257         //dest8_list[i]->sort_key =  nmem_strdup(nmem, src8_list[i]);
258         //dest8_list[i]->sort_len =  strlen(src8_list[i]);
259         dest8_list[i]->sort_key 
260             = icu_sortmap(nmem, buf, buf_cap, 0, src8_list[i], locale);
261         // = icu_sortmap(nmem, buf, buf_cap, &(dest8_list[i]->sort_len),
262         //                  src8_list[i], locale);
263     }
264
265     // do the sorting
266     qsort(dest8_list, list_len, 
267           sizeof(struct icu_termmap *), icu_termmap_cmp);
268
269     // checking correct sorting
270     for (i = 0; i < list_len; i++){
271         if (0 != strcmp(dest8_list[i]->disp_term, check8_list[i])){
272             sucess = 0;
273         }
274     }
275
276     if (1 || !sucess){
277         printf("\n");
278         printf("Input    '%s':", locale);
279         for (i = 0; i < list_len; i++)
280             printf(" '%s'", src8_list[i]);
281         printf("\n");        
282         printf("ICU sort '%s':", locale);
283         for (i = 0; i < list_len; i++)
284             printf(" '%s'", dest8_list[i]->disp_term);
285         if (sucess)
286             printf(" OK");
287         else
288             printf(" ERROR ??");
289         printf("\n");
290         printf("Expected '%s':", locale);
291         for (i = 0; i < list_len; i++)
292             printf(" '%s'", check8_list[i]);
293         printf("\n");        
294     }
295     
296     nmem_destroy(nmem);
297
298     return sucess;
299 }
300
301 #else
302
303 int test_icu_sortmap(const char * locale, int src_list_len,
304                      const char ** src_list, const char ** chk_list)
305 {
306     int success = 1;
307
308     UErrorCode status = U_ZERO_ERROR;
309
310   struct icu_buf_utf8 * buf8 = icu_buf_utf8_create(0);
311   struct icu_buf_utf16 * buf16 = icu_buf_utf16_create(0);
312
313   int i;
314
315   struct icu_termmap * list[src_list_len];
316
317   UCollator *coll = ucol_open(locale, &status); 
318   icu_check_status(status);
319
320   if(!U_SUCCESS(status))
321     return 0;
322
323   // assigning display terms and sort keys using buf 8 and buf16
324   for( i = 0; i < src_list_len; i++) 
325     {
326
327       list[i] = (struct icu_termmap *) malloc(sizeof(struct icu_termmap));
328
329       // copy display term
330       strcpy(list[i]->disp_term, src_list[i]);    
331
332       // transforming to UTF16
333       icu_utf16_from_utf8_cstr(buf16, list[i]->disp_term, &status);
334       icu_check_status(status);
335
336       // computing sortkeys
337       icu_sortkey8_from_utf16(coll, buf8, buf16, &status);
338       icu_check_status(status);
339     
340       // assigning sortkeys
341       memcpy(list[i]->sort_key, buf8->utf8, buf8->utf8_len);    
342       //strncpy(list[i]->sort_key, buf8->utf8, buf8->utf8_len);    
343       //strcpy((char *) list[i]->sort_key, (const char *) buf8->utf8);
344     } 
345
346
347   // do the sorting
348   qsort(list, src_list_len, 
349         sizeof(struct icu_termmap *), icu_termmap_cmp);
350
351   // checking correct sorting
352   for (i = 0; i < src_list_len; i++){
353     if (0 != strcmp(list[i]->disp_term, chk_list[i])){
354       success = 0;
355     }
356   }
357
358   if(!success){
359   printf("\nERROR\n"); 
360   printf("Input str: '%s' : ", locale); 
361   for (i = 0; i < src_list_len; i++) {
362     printf(" '%s'", list[i]->disp_term); 
363   }
364   printf("\n");
365   printf("ICU sort:  '%s' : ", locale); 
366   for (i = 0; i < src_list_len; i++) {
367     printf(" '%s'", list[i]->disp_term); 
368     //printf("(%d|%d)", list[i]->sort_key[0],list[i]->sort_key[1]); 
369   }
370   printf("\n"); 
371   printf("Expected:  '%s' : ", locale); 
372   for (i = 0; i < src_list_len; i++) {
373     printf(" '%s'", chk_list[i]); 
374   }
375   printf("\n"); 
376   }
377   
378   
379   ucol_close(coll);
380
381   icu_buf_utf8_destroy(buf8);
382   icu_buf_utf16_destroy(buf16);
383
384
385
386     return success;  
387 }
388
389
390 #endif
391
392
393 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
394
395 void test_icu_I18N_sortmap(int argc, char **argv)
396 {
397
398     // sucessful tests
399     size_t en_1_len = 6;
400     const char * en_1_src[6] = {"z", "K", "a", "A", "Z", "k"};
401     const char * en_1_cck[6] = {"a", "A", "k", "K", "z", "Z"};
402     YAZ_CHECK(test_icu_sortmap("en", en_1_len, en_1_src, en_1_cck));
403     YAZ_CHECK(test_icu_sortmap("en_AU", en_1_len, en_1_src, en_1_cck));
404     YAZ_CHECK(test_icu_sortmap("en_CA", en_1_len, en_1_src, en_1_cck));
405     YAZ_CHECK(test_icu_sortmap("en_GB", en_1_len, en_1_src, en_1_cck));
406     YAZ_CHECK(test_icu_sortmap("en_US", en_1_len, en_1_src, en_1_cck));
407     
408     // sucessful tests 
409     size_t da_1_len = 6;
410     const char * da_1_src[6] = {"z", "å", "o", "æ", "a", "ø"};
411     const char * da_1_cck[6] = {"a", "o", "z", "æ", "ø", "å"};
412     YAZ_CHECK(test_icu_sortmap("da", da_1_len, da_1_src, da_1_cck));
413     YAZ_CHECK(test_icu_sortmap("da_DK", da_1_len, da_1_src, da_1_cck));
414     
415     // sucessful tests
416     size_t de_1_len = 9;
417     const char * de_1_src[9] = {"u", "ä", "o", "t", "s", "ß", "ü", "ö", "a"};
418     const char * de_1_cck[9] = {"a","ä", "o", "ö", "s", "ß", "t", "u", "ü"};
419     YAZ_CHECK(test_icu_sortmap("de", de_1_len, de_1_src, de_1_cck));
420     YAZ_CHECK(test_icu_sortmap("de_AT", de_1_len, de_1_src, de_1_cck));
421     YAZ_CHECK(test_icu_sortmap("de_DE", de_1_len, de_1_src, de_1_cck));
422     
423 }
424
425
426 #endif    
427
428 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
429
430 int main(int argc, char **argv)
431 {
432
433     YAZ_CHECK_INIT(argc, argv); 
434     YAZ_CHECK_LOG();
435
436 #ifdef HAVE_ICU
437
438     //test_icu_I18N_casemap_failures(argc, argv);
439     //test_icu_I18N_casemap(argc, argv);
440     test_icu_I18N_sortmap(argc, argv);
441  
442 #else
443
444     printf("ICU unit tests omitted.\n"
445            "Please install libicu36-dev and icu-doc or similar\n");
446     YAZ_CHECK(0 == 0);
447
448 #endif    
449    
450     YAZ_CHECK_TERM;
451 }
452
453
454 // DO NOT EDIT THIS FILE IF YOUR EDITOR DOES NOT SUPPORT UTF-8
455
456 /*
457  * Local variables:
458  * c-basic-offset: 4
459  * indent-tabs-mode: nil
460  * End:
461  * vim: shiftwidth=4 tabstop=8 expandtab
462  */