• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1998-2016, International Business Machines Corporation and
6  * others. All Rights Reserved.
7  ********************************************************************/
8 /*
9 * File udatatst.c
10 *
11 * Modification History:
12 *
13 *   Date          Name        Description
14 *   02/22/2000    Madhu       Creation
15 ******************************************************************************
16 */
17 
18 #include "unicode/utypes.h"
19 #include "unicode/putil.h"
20 #include "unicode/udata.h"
21 #include "unicode/ucal.h"
22 #include "unicode/uchar.h"
23 #include "unicode/ucnv.h"
24 #include "unicode/ures.h"
25 #include "unicode/ustring.h"
26 #include "unicode/uclean.h"
27 #include "cmemory.h"
28 #include "cstring.h"
29 #include "filestrm.h"
30 #include "udatamem.h"
31 #include "cintltst.h"
32 #include "ubrkimpl.h"
33 #include "toolutil.h" /* for uprv_fileExists() */
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 /* includes for TestSwapData() */
39 #include "udataswp.h"
40 
41 /* swapping implementations in common */
42 #include "uresdata.h"
43 #include "ucnv_io.h"
44 #include "uprops.h"
45 #include "ucase.h"
46 #include "ucol_imp.h"
47 #include "ucol_swp.h"
48 #include "ucnv_bld.h"
49 #include "sprpimpl.h"
50 #include "rbbidata.h"
51 
52 /* swapping implementation in i18n */
53 #include "uspoof_impl.h"
54 
55 U_CAPI int32_t U_EXPORT2
56 unorm2_swap(const UDataSwapper *ds,
57             const void *inData, int32_t length, void *outData,
58             UErrorCode *pErrorCode);
59 
60 /* other definitions and prototypes */
61 
62 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
63 static void TestUDataOpen(void);
64 static void TestUDataOpenChoiceDemo1(void);
65 static void TestUDataOpenChoiceDemo2(void);
66 static void TestUDataGetInfo(void);
67 static void TestUDataGetMemory(void);
68 static void TestErrorConditions(void);
69 static void TestAppData(void);
70 static void TestSwapData(void);
71 #endif
72 static void TestUDataSetAppData(void);
73 static void TestICUDataName(void);
74 static void PointerTableOfContents(void);
75 static void SetBadCommonData(void);
76 static void TestUDataFileAccess(void);
77 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
78 static void TestTZDataDir(void);
79 #endif
80 
81 void addUDataTest(TestNode** root);
82 
83 void
addUDataTest(TestNode ** root)84 addUDataTest(TestNode** root)
85 {
86 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
87     addTest(root, &TestUDataOpen,       "udatatst/TestUDataOpen"      );
88     addTest(root, &TestUDataOpenChoiceDemo1, "udatatst/TestUDataOpenChoiceDemo1");
89     addTest(root, &TestUDataOpenChoiceDemo2, "udatatst/TestUDataOpenChoiceDemo2");
90     addTest(root, &TestUDataGetInfo,    "udatatst/TestUDataGetInfo"   );
91     addTest(root, &TestUDataGetMemory,  "udatatst/TestUDataGetMemory" );
92     addTest(root, &TestErrorConditions, "udatatst/TestErrorConditions");
93     addTest(root, &TestAppData, "udatatst/TestAppData" );
94     addTest(root, &TestSwapData, "udatatst/TestSwapData" );
95 #endif
96     addTest(root, &TestUDataSetAppData, "udatatst/TestUDataSetAppData" );
97     addTest(root, &TestICUDataName, "udatatst/TestICUDataName" );
98     addTest(root, &PointerTableOfContents, "udatatst/PointerTableOfContents" );
99     addTest(root, &SetBadCommonData, "udatatst/SetBadCommonData" );
100     addTest(root, &TestUDataFileAccess, "udatatst/TestUDataFileAccess" );
101 #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
102     addTest(root, &TestTZDataDir, "udatatst/TestTZDataDir" );
103 #endif
104 }
105 
106 #if 0
107 static void lots_of_mallocs()
108 {
109     int q;
110     for(q=1;q<100;q++)
111     {
112         free(malloc(q));
113         malloc(q*2);
114     }
115 
116 }
117 #endif
118 
119 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
TestUDataOpen(void)120 static void TestUDataOpen(void){
121     UDataMemory *result;
122     UErrorCode status=U_ZERO_ERROR;
123     const char* memMap[][2]={
124         {"root", "res"},
125         {"cnvalias", "icu"},
126         {"unames",   "icu"},
127         {"ibm-37_P100-1995",   "cnv"}
128     };
129     const char* name            = "test";
130     const char* type            = "icu";
131     const char  dirSepString[]  = {U_FILE_SEP_CHAR, 0};
132     const char  pathSepString[] = {U_PATH_SEP_CHAR, 0};
133 
134 
135     char* path=(char*)malloc(sizeof(char) * (strlen(ctest_dataOutDir())
136                                            + strlen(U_ICUDATA_NAME)
137                                            + strlen("/build/tmp/..")+1 ) );
138 
139     char        *icuDataFilePath = 0;
140 
141     const char* testPath=loadTestData(&status);
142     if(U_FAILURE(status)) {
143         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
144         free(path);
145         return;
146     }
147 
148     /* lots_of_mallocs(); */
149     log_verbose("Testing udata_open(%s)\n", testPath);
150     result=udata_open(testPath, type, name, &status);
151     if(U_FAILURE(status)){
152         log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", testPath, name, type, myErrorName(status));
153     } else {
154         log_verbose("PASS: udata_open worked\n");
155         udata_close(result);
156     }
157 
158     {
159       strcat(strcpy(path, ctest_dataOutDir()), U_ICUDATA_NAME);
160 
161       /* If the ICU system common data file is present in this confiugration,
162        *   verify that udata_open can explicitly fetch items from it.
163        *   If packaging mode == dll, the file may not exist.  So, if the file is
164        *   missing, skip this test without error.
165        */
166       icuDataFilePath = (char *)uprv_malloc(strlen(path) + 10);
167       strcpy(icuDataFilePath, path);
168       strcat(icuDataFilePath, ".dat");
169       /* lots_of_mallocs(); */
170       if (uprv_fileExists(icuDataFilePath))
171       {
172           int i;
173           log_verbose("Testing udata_open() on %s\n", icuDataFilePath);
174           for(i=0; i<UPRV_LENGTHOF(memMap); i++){
175             /* lots_of_mallocs(); */
176             status=U_ZERO_ERROR;
177             result=udata_open(path, memMap[i][1], memMap[i][0], &status);
178             if(U_FAILURE(status)) {
179                 log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", path, memMap[i][0], memMap[i][1], myErrorName(status));
180             } else {
181                 log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n",  path, memMap[i][0], memMap[i][1]);
182                 udata_close(result);
183             }
184           }
185       }
186       else
187       {
188           /* lots_of_mallocs(); */
189           log_verbose("Skipping tests of udata_open() on %s.  File not present in this configuration.\n",
190                   icuDataFilePath);
191       }
192       uprv_free(icuDataFilePath);
193     }
194     /* try again, adding /tmp */
195     {
196       strcpy(path, ctest_dataOutDir());
197       strcat(path, "tmp");
198       strcat(path, dirSepString);
199       strcat(path, U_ICUDATA_NAME);
200 
201       /* If the ICU system common data file is present in this confiugration,
202        *   verify that udata_open can explicitly fetch items from it.
203        *   If packaging mode == dll, the file may not exist.  So, if the file is
204        *   missing, skip this test without error.
205        */
206       icuDataFilePath = (char *)malloc(strlen(path) + 10);
207       strcpy(icuDataFilePath, path);
208       strcat(icuDataFilePath, ".dat");
209       /* lots_of_mallocs(); */
210       if (uprv_fileExists(icuDataFilePath))
211 	{
212 	  int i;
213 	  log_verbose("Testing udata_open() on %s\n", icuDataFilePath);
214 	  for(i=0; i<UPRV_LENGTHOF(memMap); i++){
215             /* lots_of_mallocs(); */
216             status=U_ZERO_ERROR;
217             result=udata_open(path, memMap[i][1], memMap[i][0], &status);
218             if(U_FAILURE(status)) {
219 	      log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", path, memMap[i][0], memMap[i][1], myErrorName(status));
220             } else {
221 	      log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n",  path, memMap[i][0], memMap[i][1]);
222 	      udata_close(result);
223             }
224 	  }
225 	}
226       else
227 	{
228 	  /* lots_of_mallocs(); */
229 	  log_verbose("Skipping tests of udata_open() on %s.  File not present in this configuration.\n",
230 		      icuDataFilePath);
231 	}
232     }
233 
234     free(icuDataFilePath);
235     icuDataFilePath = NULL;
236     /* lots_of_mallocs(); */
237 
238     /* If the ICU individual files used to build the ICU system common data are
239      *   present in this configuration,
240      *   verify that udata_open can explicitly open them.
241      *   These data files are present in the ICU data/build directory after a build
242      *    completes.  Tests are most commonly run with the data directory pointing
243      *    back into this directory structure, but this is not required.  Soooo, if
244      *    the files are missing, skip this test without error.
245      */
246     /* lots_of_mallocs(); */
247     icuDataFilePath = (char *)malloc(strlen(ctest_dataOutDir()) + 50);
248     strcpy(icuDataFilePath, ctest_dataOutDir());
249     strcat(icuDataFilePath, "build");
250     strcat(icuDataFilePath, dirSepString);
251     strcat(icuDataFilePath, U_ICUDATA_NAME);
252     strcat(icuDataFilePath, dirSepString);
253     strcat(icuDataFilePath, "cnvalias.icu");
254 
255     /* lots_of_mallocs(); */
256     if (uprv_fileExists(icuDataFilePath))
257     {
258         int i;
259         log_verbose("%s exists, so..\n", icuDataFilePath);
260         strcpy(icuDataFilePath, ctest_dataOutDir());
261         strcat(icuDataFilePath, "build");
262         strcat(icuDataFilePath, dirSepString);
263         strcat(icuDataFilePath, U_ICUDATA_NAME);
264         log_verbose("Testing udata_open() on %s\n", icuDataFilePath);
265         for(i=0; i<UPRV_LENGTHOF(memMap); i++){
266             status=U_ZERO_ERROR;
267             result=udata_open(icuDataFilePath, memMap[i][1], memMap[i][0], &status);
268             if(U_FAILURE(status)) {
269                 log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1], myErrorName(status));
270             } else {
271                 log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n",  icuDataFilePath, memMap[i][0], memMap[i][1]);
272                 udata_close(result);
273             }
274         }
275     }
276     else
277     {
278          log_verbose("Skipping tests of udata_open() on %s.  File not present in this configuration.\n",
279              icuDataFilePath);
280     }
281 
282     free(icuDataFilePath);
283     icuDataFilePath = NULL;
284 
285     /*
286      * Test fallback file names for open of separate data files.
287      *    With these params to udata_open:
288      *       path = wherever/testdata
289      *       type = typ
290      *       name = nam
291      *     these files will be tried first:
292      *              wherever/testudata_nam.typ
293      *              testudata_nam.typ
294      *  A test data file named testudata_nam.typ exists for the purpose of testing this.
295      */
296     log_verbose("Testing udata_open, with base_name.type style fallback to individual file.\n");
297 
298     status = U_ZERO_ERROR;
299     result = udata_open( testPath, "typ", "nam", &status);
300     if (status != U_ZERO_ERROR) {
301         log_data_err("FAIL: udata_open( \"%s\", \"typ\", \"nam\") returned status %s\n", testPath, u_errorName(status));
302     }
303     udata_close(result);
304     free(icuDataFilePath);
305 
306 
307     /* This type of path is deprecated */
308     /*
309      * Another fallback test.   Paths ending with a trailing directory separator
310      *    take a slightly different code path, with the "base name" from the path
311      *    being empty in the internal udata_open logic.
312      */
313 
314 /*      log_verbose("Testing udata_open, with path containing a trailing directory separator.\n"); */
315 /*      icuDataFilePath = (char *)malloc(strlen(u_getDataDirectory()) + 50); */
316 /*      strcpy(icuDataFilePath, testPath); */
317 /*      status = U_ZERO_ERROR; */
318 /*      result = udata_open( icuDataFilePath, "cnv", "test1", &status); */
319 /*      if (status != U_ZERO_ERROR) { */
320 /*          log_err("FAIL: udata_open( \"%s\", \"cnv\", \"test1\") returned status %s\n", icuDataFilePath, u_errorName(status)); */
321 /*      } */
322 /*      udata_close(result); */
323 /*      free(icuDataFilePath); */
324 
325 
326     log_verbose("Testing udata_open() with a non existing binary file\n");
327     result=udata_open("testdata", "tst", "nonexist", &status);
328     if(status==U_FILE_ACCESS_ERROR){
329         log_verbose("Opening udata_open with non-existing file handled correctly.\n");
330         status=U_ZERO_ERROR;
331     } else {
332         log_err("calling udata_open with non-existing file  [testdata | nonexist.tst] not handled correctly\n.  Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status));
333         if(U_SUCCESS(status)) {
334             udata_close(result);
335         }
336     }
337 
338     if(result != NULL){
339         log_err("calling udata_open with non-existing file didn't return a null value\n");
340     } else {
341         log_verbose("calling udat_open with non-existing file returned null as expected\n");
342     }
343 
344     /*
345      *  Try opening data with absurdly long path and name, to trigger buffer size
346      *   overflow handling code.
347      */
348     {
349         char longTestPath[1024];    /* Implementation goes to heap at length of 128.  */
350         char longName[1024];
351 
352         /* Try a very long nonexistent directory path.
353          * udata_open should still succeed.  Opening with the path will fail,
354          * then fall back to skipping the directory portion of the path.
355          */
356         log_verbose("Testing udata_open() with really long names\n");
357         longTestPath[0] = 0;
358         strcat(longTestPath, "bogus_directory_name");
359         while (strlen(longTestPath) < 500) {
360             strcat(longTestPath, dirSepString);
361             strcat(longTestPath, "bogus_directory_name");
362         }
363         strcat(longTestPath, pathSepString);
364         strcat(longTestPath, testPath);
365         result=udata_open(longTestPath, type, name, &status);
366         if(U_FAILURE(status)){
367             log_data_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n",
368                 longTestPath, name, type, myErrorName(status));
369         } else {
370             log_verbose("PASS: udata_open worked\n");
371             udata_close(result);
372         }
373 
374         /* Try a very long name.  Won't open, but shouldn't blow up.
375          */
376         longName[0] = 0;
377         while (strlen(longName) < 500) {
378             strcat(longName, name);
379             strcat(longName, "_");
380         }
381         strcat(longName, dirSepString);
382         strcat(longName, name);
383 
384         result=udata_open(longTestPath, type, longName, &status);
385         if (status != U_FILE_ACCESS_ERROR) {
386             log_data_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n",
387                 longTestPath, longName, type, myErrorName(status));
388         }
389         udata_close(result);
390     }
391 
392     free(path);
393 }
394 #endif
395 
396 typedef struct {
397     uint16_t headerSize;
398     uint8_t magic1, magic2;
399     UDataInfo info;
400     char padding[8];
401     uint32_t count, reserved;
402     /*
403     const struct {
404     const char *const name;
405     const void *const data;
406     } toc[1];
407     */
408    int32_t   fakeNameAndData[4];
409 } ICU_COMMON_Data_Header;
410 
411 static const ICU_COMMON_Data_Header gEmptyHeader = {
412     32,          /* headerSize */
413     0xda,        /* magic1,  (see struct MappedData in udata.c)  */
414     0x27,        /* magic2     */
415     {            /*UDataInfo   */
416         sizeof(UDataInfo),      /* size        */
417         0,                      /* reserved    */
418 
419 #if U_IS_BIG_ENDIAN
420         1,
421 #else
422         0,
423 #endif
424 
425         U_CHARSET_FAMILY,
426         sizeof(UChar),
427         0,               /* reserved      */
428         {                /* data format identifier */
429            0x43, 0x6d, 0x6e, 0x44}, /* "CmnD" */
430            {1, 0, 0, 0},   /* format version major, minor, milli, micro */
431            {0, 0, 0, 0}    /* dataVersion   */
432     },
433     {0,0,0,0,0,0,0,0},  /* Padding[8]   */
434     0,                  /* count        */
435     0,                  /* Reserved     */
436     {                   /*  TOC structure */
437 /*        {    */
438           0 , 0 , 0, 0  /* name and data entries.  Count says there are none,  */
439                         /*  but put one in just in case.                       */
440 /*        }  */
441     }
442 };
443 
444 
TestUDataSetAppData(void)445 static void TestUDataSetAppData(void){
446 /*    UDataMemory      *dataItem;*/
447 
448     UErrorCode        status=U_ZERO_ERROR;
449 
450     /*
451      * First we try some monkey business and try to do bad things.
452      */
453 
454     status=U_ZERO_ERROR;
455     udata_setAppData("appData1", NULL, &status);
456     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
457         log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", NULL, status) should have failed."
458                 " It returned status of %s\n", u_errorName(status));
459         return;
460     }
461     /* The following call should fail.
462        If the following works with a bad UErrorCode, then later calls to appData1 should fail. */
463     udata_setAppData("appData1", &gEmptyHeader, &status);
464 
465     /*
466      * Got testdata.dat into memory, now we try setAppData using the memory image.
467      */
468 
469     status=U_ZERO_ERROR;
470     udata_setAppData("appData1", &gEmptyHeader, &status);
471     if (status != U_ZERO_ERROR) {
472         log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) "
473                 " returned status of %s\n", u_errorName(status));
474         return;
475     }
476 
477     udata_setAppData("appData2", &gEmptyHeader, &status);
478     if (status != U_ZERO_ERROR) {
479         log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData2\", fileBuf, status) "
480                 " returned status of %s\n", u_errorName(status));
481         return;
482     }
483 
484     /*  If we try to setAppData with the same name a second time, we should get a
485      *    a using default warning.
486      */
487     udata_setAppData("appData2", &gEmptyHeader, &status);
488     if (status != U_USING_DEFAULT_WARNING) {
489         log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData2\", fileBuf, status) "
490                 " returned status of %s, expected U_USING_DEFAULT_WARNING.\n", u_errorName(status));
491     }
492 
493 
494     /** It is no longer  correct to use udata_setAppData to change the
495         package of a contained item.
496 
497         dataItem = udata_open("appData1", "res", "te_IN", &status); **/
498 }
499 
safeGetICUDataDirectory(void)500 static char *safeGetICUDataDirectory(void) {
501     const char *dataDir = u_getDataDirectory();  /* Returned string vanashes with u_cleanup */
502     char *retStr = NULL;
503     if (dataDir != NULL) {
504         retStr = (char *)malloc(strlen(dataDir)+1);
505         strcpy(retStr, dataDir);
506     }
507     return retStr;
508 }
509 
TestUDataFileAccess(void)510 static void TestUDataFileAccess(void){
511     UErrorCode status;
512     char            *icuDataDir;
513     icuDataDir = safeGetICUDataDirectory();   /* save icu data dir, so we can put it back
514                                                *  after doing u_cleanup().                */
515 
516     /** UDATA_NO_FILES, ICU does not access the file system for data loading. */
517     status=U_ZERO_ERROR;
518     u_cleanup();
519     udata_setFileAccess(UDATA_NO_FILES,&status);
520     u_init(&status);
521     if(U_FAILURE(status) && *icuDataDir == 0){
522         log_data_err("udata_setFileAccess(UDATA_NO_FILES) failed with ICU_DATA=\"\" err=%s\n", u_errorName(status));
523     }
524 
525     /** UDATA_ONLY_PACKAGES, ICU only loads data from packages, not from single files. */
526     status=U_ZERO_ERROR;
527     u_cleanup();
528     udata_setFileAccess(UDATA_ONLY_PACKAGES,&status);
529     u_init(&status);
530 
531     /** UDATA_PACKAGES_FIRST, ICU loads data from packages first, and only from single files
532         if the data cannot be found in a package. */
533     status=U_ZERO_ERROR;
534     u_cleanup();
535     udata_setFileAccess(UDATA_PACKAGES_FIRST,&status);
536     u_init(&status);
537 
538     /** UDATA_FILES_FIRST, ICU looks for data in single files first, then in packages. (default) */
539     status=U_ZERO_ERROR;
540     u_cleanup();
541     udata_setFileAccess(UDATA_FILES_FIRST,&status);
542     u_init(&status);
543 
544     /** An alias for the default access mode. */
545     status=U_ZERO_ERROR;
546     u_cleanup();
547     udata_setFileAccess(UDATA_DEFAULT_ACCESS,&status);
548     u_setDataDirectory(icuDataDir);
549     u_init(&status);
550     if(U_FAILURE(status)){
551         log_err_status(status, "%s\n", u_errorName(status));
552     }
553     free(icuDataDir);
554     ctest_resetICU();
555 }
556 
557 
558 static UBool U_CALLCONV
isAcceptable1(void * context,const char * type,const char * name,const UDataInfo * pInfo)559 isAcceptable1(void *context,
560              const char *type, const char *name,
561              const UDataInfo *pInfo) {
562     (void)context; // suppress compiler warnings about unused variable
563 
564     if( pInfo->size>=20 &&
565         pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
566         pInfo->charsetFamily==U_CHARSET_FAMILY &&
567         pInfo->dataFormat[0]==0x43 &&   /* dataFormat="CvAl" */
568         pInfo->dataFormat[1]==0x76 &&
569         pInfo->dataFormat[2]==0x41 &&
570         pInfo->dataFormat[3]==0x6c &&
571         pInfo->formatVersion[0]==3 )
572     {
573         log_verbose("The data from \"%s.%s\" IS acceptable using the verifying function isAcceptable1()\n", name, type);
574         return true;
575     } else {
576         log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifying function isAcceptable1():-\n"
577             "\tsize              = %d\n"
578             "\tisBigEndian       = %d\n"
579             "\tcharsetFamily     = %d\n"
580             "\tformatVersion[0]  = %d\n"
581             "\tdataVersion[0]    = %d\n"
582             "\tdataFormat        = %c%c%c%c\n",
583             name, type, pInfo->size,  pInfo->isBigEndian, pInfo->charsetFamily, pInfo->formatVersion[0],
584             pInfo->dataVersion[0], pInfo->dataFormat[0], pInfo->dataFormat[1], pInfo->dataFormat[2],
585             pInfo->dataFormat[3]);
586         log_verbose("Call another verifying function to accept the data\n");
587         return false;
588     }
589 }
590 
591 static UBool U_CALLCONV
isAcceptable2(void * context,const char * type,const char * name,const UDataInfo * pInfo)592 isAcceptable2(void *context,
593              const char *type, const char *name,
594       const UDataInfo *pInfo){
595     (void)context; // suppress compiler warnings about unused variable
596     UVersionInfo unicodeVersion;
597 
598     u_getUnicodeVersion(unicodeVersion);
599 
600     if( pInfo->size>=20 &&
601         pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
602         pInfo->charsetFamily==U_CHARSET_FAMILY &&
603         pInfo->dataFormat[0]==0x75 &&   /* dataFormat="unam" */
604         pInfo->dataFormat[1]==0x6e &&
605         pInfo->dataFormat[2]==0x61 &&
606         pInfo->dataFormat[3]==0x6d &&
607         pInfo->formatVersion[0]==1 &&
608         pInfo->dataVersion[0]==unicodeVersion[0] )
609     {
610         log_verbose("The data from \"%s.%s\" IS acceptable using the verifying function isAcceptable2()\n", name, type);
611         return true;
612     } else {
613         log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifying function isAcceptable2()\n", name, type);
614 
615         return false;
616     }
617 
618 
619 }
620 static UBool U_CALLCONV
isAcceptable3(void * context,const char * type,const char * name,const UDataInfo * pInfo)621 isAcceptable3(void *context,
622              const char *type, const char *name,
623              const UDataInfo *pInfo){
624     (void)context; // suppress compiler warnings about unused variable
625 
626     if( pInfo->size>=20 &&
627         pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
628         pInfo->charsetFamily==U_CHARSET_FAMILY &&
629         pInfo->dataFormat[0]==0x54 &&   /* dataFormat="test" */
630         pInfo->dataFormat[1]==0x65 &&
631         pInfo->dataFormat[2]==0x73 &&
632         pInfo->dataFormat[3]==0x74 &&
633         pInfo->formatVersion[0]==1 &&
634         pInfo->dataVersion[0]==1   ) {
635         log_verbose("The data from \"%s.%s\" IS acceptable using the verifying function isAcceptable3()\n", name, type);
636 
637         return true;
638     } else {
639         log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifying function isAcceptable3()\n", name, type);
640         return false;
641     }
642 
643 
644 }
645 
646 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
TestUDataOpenChoiceDemo1(void)647 static void TestUDataOpenChoiceDemo1(void) {
648     UDataMemory *result;
649     UErrorCode status=U_ZERO_ERROR;
650 
651     const char* name[]={
652         "cnvalias",
653         "unames",
654         "test",
655         "nam"
656     };
657     const char* type="icu";
658     const char* testPath="testdata";
659     const char* fullTestDataPath = loadTestData(&status);
660     if(U_FAILURE(status)) {
661         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
662         return;
663     }
664 
665     result=udata_openChoice(NULL, "icu", name[0], isAcceptable1, NULL, &status);
666     if(U_FAILURE(status)){
667         log_data_err("FAIL: udata_openChoice() failed name=%s, type=%s, \n errorcode=%s\n", name[0], type, myErrorName(status));
668     } else {
669         log_verbose("PASS: udata_openChoice worked\n");
670         udata_close(result);
671     }
672 
673     status=U_ZERO_ERROR;
674     result=udata_openChoice(NULL, type, name[1], isAcceptable1, NULL, &status);
675     if(U_FAILURE(status)){
676         status=U_ZERO_ERROR;
677         result=udata_openChoice(NULL, type, name[1], isAcceptable2, NULL, &status);
678         if(U_FAILURE(status)){
679             log_data_err("FAIL: udata_openChoice() failed name=%s, type=%s, \n errorcode=%s\n", name[1], type, myErrorName(status));
680         }
681     }
682     else {
683         log_err("FAIL: udata_openChoice() unexpectedly passed. name=%s, type=%s, \n errorcode=%s\n", name[1], type, myErrorName(status));
684     }
685 
686     if(U_SUCCESS(status)){
687         udata_close(result);
688     }
689 
690     status=U_ZERO_ERROR;
691     result=udata_openChoice(testPath, type, name[2], isAcceptable1, NULL, &status);
692     if(U_FAILURE(status)){
693         status=U_ZERO_ERROR;
694         result=udata_openChoice(testPath, type, name[2], isAcceptable3, NULL, &status);
695         if(U_FAILURE(status)){
696             log_data_err("FAIL: udata_openChoice() failed path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name[2], type, myErrorName(status));
697         }
698     }
699     else {
700         log_err("FAIL: udata_openChoice() unexpectedly passed. name=%s, type=%s, \n errorcode=%s\n", name[2], type, myErrorName(status));
701     }
702 
703     if(U_SUCCESS(status)){
704         udata_close(result);
705     }
706 
707     status=U_ZERO_ERROR;
708     type="typ";
709     result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status);
710     if(status != U_INVALID_FORMAT_ERROR){
711         // Android-changed: Android does not try to load ICU data from other files. See  gDataFileAccess = UDATA_NO_FILES in udata.cpp.
712         // log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
713         log_data_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
714     }
715 
716     status=U_USELESS_COLLATOR_ERROR;
717     result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status);
718     if(status != U_USELESS_COLLATOR_ERROR){
719         // Android-changed: Android does not try to load ICU data from other files. See  gDataFileAccess = UDATA_NO_FILES in udata.cpp.
720         // log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
721         log_data_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
722     }
723 }
724 
725 static UBool U_CALLCONV
isAcceptable(void * context,const char * type,const char * name,const UDataInfo * pInfo)726 isAcceptable(void *context,
727              const char *type, const char *name,
728              const UDataInfo *pInfo){
729     if( pInfo->size>=20 &&
730         pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
731         pInfo->charsetFamily==U_CHARSET_FAMILY &&
732         pInfo->dataFormat[0]==0x54 &&   /* dataFormat="test" */
733         pInfo->dataFormat[1]==0x65 &&
734         pInfo->dataFormat[2]==0x73 &&
735         pInfo->dataFormat[3]==0x74 &&
736         pInfo->formatVersion[0]==1 &&
737         pInfo->dataVersion[0]==1   &&
738         *((int*)context) == 2 ) {
739         log_verbose("The data from\"%s.%s\" IS acceptable using the verifying function isAcceptable()\n", name, type);
740 
741         return true;
742     } else {
743         log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifying function isAcceptable()\n", name, type);
744         return false;
745     }
746 }
747 
748 
749 /* This test checks to see if the isAcceptable function is being called correctly. */
750 
TestUDataOpenChoiceDemo2(void)751 static void TestUDataOpenChoiceDemo2(void) {
752     UDataMemory *result;
753     UErrorCode status=U_ZERO_ERROR;
754     int i;
755     int p=2;
756 
757     const char* name="test";
758     const char* type="icu";
759     const char* path = loadTestData(&status);
760     if(U_FAILURE(status)) {
761         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
762         return;
763     }
764 
765     result=udata_openChoice(path, type, name, isAcceptable, &p, &status);
766     if(U_FAILURE(status)){
767         log_data_err("failed to load data at p=%s t=%s n=%s, isAcceptable", path, type, name);
768     }
769     if(U_SUCCESS(status) ) {
770         udata_close(result);
771     }
772 
773     p=0;
774     for(i=0;i<2; i++){
775         result=udata_openChoice(path, type, name, isAcceptable, &p, &status);
776         if(p<2) {
777             if(U_FAILURE(status) && status==U_INVALID_FORMAT_ERROR){
778                 log_verbose("Loads the data but rejects it as expected %s\n", myErrorName(status));
779                 status=U_ZERO_ERROR;
780                 p++;
781             }
782             else {
783                 log_data_err("FAIL: failed to either load the data or to reject the loaded data. ERROR=%s\n", myErrorName(status) );
784             }
785         }
786         else if(p == 2) {
787             if(U_FAILURE(status)) {
788                 log_data_err("FAIL: failed to load the data and accept it.  ERROR=%s\n", myErrorName(status) );
789             }
790             else {
791                 log_verbose("Loads the data and accepts it for p==2 as expected\n");
792                 udata_close(result);
793             }
794         }
795     }
796 }
797 
TestUDataGetInfo(void)798 static void TestUDataGetInfo(void) {
799 
800     UDataMemory *result;
801     /* UDataInfo cf. udata.h */
802     static UDataInfo dataInfo={
803     30,    /*sizeof(UDataInfo),*/
804     0,
805 
806     U_IS_BIG_ENDIAN,
807     U_CHARSET_FAMILY,
808     sizeof(UChar),
809     0,
810 
811     {0x54, 0x65, 0x73, 0x74},     /* dataFormat="Test" */
812     {9, 0, 0, 0},                 /* formatVersion */
813     {4, 0, 0, 0}                  /* dataVersion */
814     };
815     UErrorCode status=U_ZERO_ERROR;
816     const char* name="cnvalias";
817     const char* name2="test";
818     const char* type="icu";
819 
820     const char* testPath=loadTestData(&status);
821     if(U_FAILURE(status)) {
822         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
823         return;
824     }
825 
826     log_verbose("Testing udata_getInfo() for cnvalias.icu\n");
827     result=udata_open(NULL, "icu", name, &status);
828     if(U_FAILURE(status)){
829         log_data_err("FAIL: udata_open() failed for path = NULL, name=%s, type=%s, \n errorcode=%s\n",  name, type, myErrorName(status));
830         return;
831     }
832     udata_getInfo(result, &dataInfo);
833     if(dataInfo.size==20            &&  dataInfo.size!=30 &&
834         dataInfo.isBigEndian==U_IS_BIG_ENDIAN       &&
835         dataInfo.charsetFamily==U_CHARSET_FAMILY    &&
836         dataInfo.dataFormat[0]==0x43 &&  dataInfo.dataFormat[0]!=0x54 && /* dataFormat="CvAl" and not "Test". The values are set for cnvalias.dat*/
837         dataInfo.dataFormat[1]==0x76 &&  dataInfo.dataFormat[1]!=0x65 &&
838         dataInfo.dataFormat[2]==0x41 &&  dataInfo.dataFormat[2]!=0x73 &&
839         dataInfo.dataFormat[3]==0x6c &&  dataInfo.dataFormat[3]!=0x74 &&
840         dataInfo.formatVersion[0]!=9 && /*formatVersion is also set to the one for cnvalias*/
841         dataInfo.dataVersion[0]!=4   && /*dataVersion*/
842         dataInfo.dataVersion[1]!=0   ){
843             log_verbose("PASS: udata_getInfo() filled in the right values\n");
844     } else {
845         log_err("FAIL: udata_getInfo() filled in the wrong values\n");
846     }
847     udata_close(result);
848 
849 
850     log_verbose("Testing udata_getInfo() for test.icu\n");
851     result=udata_open(testPath, type, name2, &status);
852     if(U_FAILURE(status)) {
853        log_data_err("FAIL: udata_open() failed for path=%s name2=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status));
854        return;
855     }
856     udata_getInfo(result, &dataInfo);
857     if(dataInfo.size==20             &&
858         dataInfo.isBigEndian==U_IS_BIG_ENDIAN       &&
859         dataInfo.charsetFamily==U_CHARSET_FAMILY    &&
860         dataInfo.dataFormat[0]==0x54 &&   /* dataFormat="Test". The values are set for test.dat*/
861         dataInfo.dataFormat[1]==0x65 &&
862         dataInfo.dataFormat[2]==0x73 &&
863         dataInfo.dataFormat[3]==0x74 &&
864         dataInfo.formatVersion[0]==1 &&  /*formatVersion is also set to the one for test*/
865         dataInfo.dataVersion[0]==1   &&  /*dataVersion*/
866         dataInfo.dataVersion[1]==0   )
867     {
868         log_verbose("PASS: udata_getInfo() filled in the right values\n");
869     } else {
870         log_err("FAIL: udata_getInfo() filled in the wrong values\n");
871     }
872     udata_close(result);
873 }
874 
TestUDataGetMemory(void)875 static void TestUDataGetMemory(void) {
876 
877     UDataMemory *result;
878     const int32_t *table=NULL;
879     uint16_t* intValue=0;
880     UErrorCode status=U_ZERO_ERROR;
881     const char* name="cnvalias";
882     const char* type;
883 
884     const char* name2="test";
885 
886     const char* testPath = loadTestData(&status);
887     if(U_FAILURE(status)) {
888         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
889         return;
890     }
891 
892     type="icu";
893     log_verbose("Testing udata_getMemory() for \"cnvalias.icu\"\n");
894     result=udata_openChoice(NULL, type, name, isAcceptable1, NULL, &status);
895     if(U_FAILURE(status)){
896         log_data_err("FAIL: udata_openChoice() failed for name=%s, type=%s, \n errorcode=%s\n", name, type, myErrorName(status));
897         return;
898     }
899     table=(const int32_t *)udata_getMemory(result);
900 
901     /* The alias table may list more converters than what's actually available now. [grhoten] */
902     if(ucnv_countAvailable() > table[1])      /*???*/
903         log_err("FAIL: udata_getMemory() failed ucnv_countAvailable returned = %d, expected = %d\n", ucnv_countAvailable(), table[1+2*(*table)]);
904 
905     udata_close(result);
906 
907     type="icu";
908     log_verbose("Testing udata_getMemory for \"test.icu\"()\n");
909     result=udata_openChoice(testPath, type, name2, isAcceptable3, NULL, &status);
910     if(U_FAILURE(status)){
911         log_data_err("FAIL: udata_openChoice() failed for path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status));
912         return;
913     }
914     intValue=(uint16_t *)udata_getMemory(result);
915     /*printf("%d ..... %s", *(intValue), intValue+1));*/
916     if( *intValue != 2000 || strcmp((char*)(intValue+1), "YEAR") != 0 )
917         log_err("FAIL: udata_getMemory() failed: intValue :- Expected:2000 Got:%d \n\tstringValue:- Expected:YEAR Got:%s\n", *intValue, (intValue+1));
918 
919     udata_close(result);
920 
921 }
922 
TestErrorConditions(void)923 static void TestErrorConditions(void){
924 
925     UDataMemory *result=NULL;
926     UErrorCode status=U_ZERO_ERROR;
927     uint16_t* intValue=0;
928     static UDataInfo dataInfo={
929         30,    /*sizeof(UDataInfo),*/
930         0,
931 
932         U_IS_BIG_ENDIAN,
933         U_CHARSET_FAMILY,
934         sizeof(UChar),
935         0,
936 
937         {0x54, 0x65, 0x73, 0x74},     /* dataFormat="Test" */
938         {9, 0, 0, 0},                 /* formatVersion */
939         {4, 0, 0, 0}                  /* dataVersion */
940     };
941 
942     const char* name = "test";
943     const char* type="icu";
944 
945     const char *testPath = loadTestData(&status);
946     if(U_FAILURE(status)) {
947         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
948         return;
949     }
950 
951     status = U_ILLEGAL_ARGUMENT_ERROR;
952     /*Try udata_open with status != U_ZERO_ERROR*/
953     log_verbose("Testing udata_open() with status != U_ZERO_ERROR\n");
954     result=udata_open(testPath, type, name, &status);
955     if(result != NULL){
956         log_data_err("FAIL: udata_open() is supposed to fail for path = %s, name=%s, type=%s, \n errorcode !=U_ZERO_ERROR\n", testPath, name, type);
957         udata_close(result);
958 
959     } else {
960         log_verbose("PASS: udata_open with errorCode != U_ZERO_ERROR failed as expected\n");
961     }
962 
963     /*Try udata_open with data name=NULL*/
964     log_verbose("Testing udata_open() with data name=NULL\n");
965     status=U_ZERO_ERROR;
966     result=udata_open(testPath, type, NULL, &status);
967     if(U_FAILURE(status)){
968         if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){
969             log_err("FAIL: udata_open() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status));
970         }else{
971             log_verbose("PASS: udata_open with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status));
972         }
973     }else{
974         log_err("FAIL: udata_open() with data name=NULL is supposed to fail for path = %s, name=NULL type=%s errorcode=U_ZERO_ERROR \n", testPath, type);
975         udata_close(result);
976     }
977 
978 
979     /*Try udata_openChoice with status != U_ZERO_ERROR*/
980     log_verbose("Testing udata_openChoice() with status != U_ZERO_ERROR\n");
981     status=U_ILLEGAL_ARGUMENT_ERROR;
982     result=udata_openChoice(testPath, type, name, isAcceptable3, NULL, &status);
983     if(result != NULL){
984         log_err("FAIL: udata_openChoice() is supposed to fail for path = %s, name=%s, type=%s, \n errorcode != U_ZERO_ERROR\n", testPath, name, type);
985         udata_close(result);
986     } else {
987         log_verbose("PASS: udata_openChoice() with errorCode != U_ZERO_ERROR failed as expected\n");
988     }
989 
990     /*Try udata_open with data name=NULL*/
991     log_verbose("Testing udata_openChoice() with data name=NULL\n");
992     status=U_ZERO_ERROR;
993     result=udata_openChoice(testPath, type, NULL, isAcceptable3, NULL, &status);
994     if(U_FAILURE(status)){
995         if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){
996             log_err("FAIL: udata_openChoice() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status));
997         }else{
998             log_verbose("PASS: udata_openChoice with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status));
999         }
1000     }else{
1001         log_err("FAIL: udata_openChoice() with data name=NULL is supposed to fail for path = %s, name=NULL type=%s errorcode=U_ZERO_ERROR \n", testPath, type);
1002         udata_close(result);
1003     }
1004 
1005     /*Try udata_getMemory with UDataMemory=NULL*/
1006     log_verbose("Testing udata_getMemory with UDataMemory=NULL\n");
1007     intValue=(uint16_t*)udata_getMemory(NULL);
1008     if(intValue != NULL){
1009         log_err("FAIL: udata_getMemory with UDataMemory = NULL is supposed to fail\n");
1010     }
1011 
1012     /*Try udata_getInfo with UDataMemory=NULL*/
1013     status=U_ZERO_ERROR;
1014     udata_getInfo(NULL, &dataInfo);
1015     if(dataInfo.size != 0){
1016         log_err("FAIL : udata_getInfo with UDataMemory = NULL us supposed to fail\n");
1017     }
1018 
1019     /*Try udata_openChoice with a non existing binary file*/
1020     log_verbose("Testing udata_openChoice() with a non existing binary file\n");
1021     result=udata_openChoice(testPath, "tst", "nonexist", isAcceptable3, NULL, &status);
1022     if(status==U_FILE_ACCESS_ERROR){
1023         log_verbose("Opening udata_openChoice with non-existing file handled correctly.\n");
1024         status=U_ZERO_ERROR;
1025     } else {
1026         log_err("calling udata_open with non-existing file not handled correctly\n.  Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status));
1027         if(U_SUCCESS(status)) {
1028             udata_close(result);
1029         }
1030     }
1031 
1032     if(result != NULL){
1033         log_err("calling udata_open with non-existing file didn't return a null value\n");
1034     } else {
1035         log_verbose("calling udat_open with non-existing file returned null as expected\n");
1036     }
1037 }
1038 
1039 /* Test whether apps and ICU can each have their own root.res */
TestAppData(void)1040 static void TestAppData(void)
1041 {
1042     UResourceBundle *icu, *app;
1043     UResourceBundle *tmp = NULL;
1044     UResourceBundle *tmp2 = NULL;
1045 
1046     const UChar *appString;
1047     const UChar *icuString;
1048 
1049     int32_t len;
1050 
1051     UErrorCode status = U_ZERO_ERROR;
1052     char testMsgBuf[256];
1053 
1054     const char* testPath=loadTestData(&status);
1055     if(U_FAILURE(status)) {
1056         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
1057         return;
1058     }
1059 
1060     icu = ures_open(NULL, "root", &status);
1061     if(U_FAILURE(status))
1062     {
1063         log_data_err("%s:%d: Couldn't open root ICU bundle- %s", __FILE__, __LINE__, u_errorName(status));
1064         return;
1065     }
1066     /*  log_info("Open icu root: %s size_%d\n", u_errorName(status), ures_getSize(icu)); */
1067     status = U_ZERO_ERROR;
1068 
1069     app = ures_open(testPath, "root", &status);
1070     if(U_FAILURE(status))
1071     {
1072         log_data_err("%s:%d: Couldn't open app ICU bundle [%s]- %s", __FILE__, __LINE__, testPath, u_errorName(status));
1073         return;
1074     }
1075     /* log_info("Open  app: %s, size %d\n", u_errorName(status), ures_getSize(app)); */
1076 
1077     tmp = ures_getByKey(icu, "Version", tmp, &status);
1078     if(U_FAILURE(status))
1079     {
1080         log_err("%s:%d: Couldn't get Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1081         return;
1082     }
1083 
1084     icuString =  ures_getString(tmp,  &len, &status);
1085     if(U_FAILURE(status))
1086     {
1087         log_err("%s:%d: Couldn't get string from Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1088         return;
1089     }
1090     /* log_info("icuString=%p - %s\n", icuString, austrdup(icuString)); */
1091 
1092 
1093     tmp2 = ures_getByKey(app, "Version", tmp2, &status);
1094     if(U_FAILURE(status))
1095     {
1096         log_err("%s:%d: Couldn't get Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1097         return;
1098     }
1099 
1100     appString =  ures_getString(tmp2,  &len, &status);
1101     if(U_FAILURE(status))
1102     {
1103         log_err("%s:%d: Couldn't get string from Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1104         return;
1105     }
1106 
1107     /* log_info("appString=%p - %s\n", appString, austrdup(appString)); */
1108 
1109 
1110     if(!u_strcmp(icuString, appString))
1111     {
1112         log_err("%s:%d: Error! Expected ICU and App root version strings to be DIFFERENT but they are both %s and %s\n", __FILE__, __LINE__, austrdup(icuString),
1113             austrdup(appString));
1114     }
1115     else
1116     {
1117         log_verbose("%s:%d:  appstr=%s, icustr=%s\n", __FILE__,
1118             __LINE__, u_austrcpy(testMsgBuf, appString), u_austrcpy(testMsgBuf, icuString));
1119     }
1120 
1121     ures_close(tmp);
1122     ures_close(tmp2);
1123     ures_close(icu);
1124     ures_close(app);
1125 }
1126 #endif
1127 
TestICUDataName(void)1128 static void TestICUDataName(void)
1129 {
1130     UVersionInfo icuVersion;
1131     char expectDataName[20];
1132     unsigned int expectLen = 8;
1133 
1134     char typeChar  = '?';
1135 
1136     /* Print out the version # we have .. */
1137     log_verbose("utypes.h says U_ICUDATA_NAME = %s\n", U_ICUDATA_NAME);
1138 
1139     /* Build up the version # we expect to get */
1140     u_getVersion(icuVersion);
1141 
1142     switch(U_CHARSET_FAMILY)
1143     {
1144     case U_ASCII_FAMILY:
1145           switch((int)U_IS_BIG_ENDIAN)
1146           {
1147           case 1:
1148                 typeChar = 'b';
1149                 break;
1150           case 0:
1151                 typeChar = 'l';
1152                 break;
1153           default:
1154                 log_err("Expected 1 or 0 for U_IS_BIG_ENDIAN, got %d!\n", (int)U_IS_BIG_ENDIAN);
1155                 /* return; */
1156           }
1157           break;
1158     case U_EBCDIC_FAMILY:
1159         typeChar = 'e';
1160         break;
1161     }
1162 
1163     /* Only major number is needed. */
1164     snprintf(expectDataName, sizeof(expectDataName), "%s%d%c",
1165                 "icudt",
1166                 (int)icuVersion[0],
1167                 typeChar);
1168 
1169     log_verbose("Expected: %s\n", expectDataName);
1170     if(uprv_strlen(expectDataName) != expectLen)
1171     {
1172         log_err("*Expected* length is wrong (test err?), should be %d is %d\n",
1173             expectLen, uprv_strlen(expectDataName));
1174     }
1175 
1176     if(uprv_strlen(U_ICUDATA_NAME) != expectLen)
1177     {
1178         log_err("U_ICUDATA_NAME length should be %d is %d\n",
1179             expectLen, uprv_strlen(U_ICUDATA_NAME));
1180     }
1181 
1182     if(uprv_strcmp(U_ICUDATA_NAME, expectDataName))
1183     {
1184         log_err("U_ICUDATA_NAME should be %s but is %s\n",
1185                 expectDataName, U_ICUDATA_NAME);
1186     }
1187 
1188         /* ICUDATA_NAME comes from the build system on *nix */
1189 #ifdef ICUDATA_NAME
1190     if(uprv_strcmp(U_ICUDATA_NAME, ICUDATA_NAME))
1191     {
1192         log_err("ICUDATA_NAME  and U_ICUDATA_NAME don't match: "
1193             "ICUDATA_NAME=%s, U_ICUDATA_NAME=%s.  Check configure.in, icudefs.mk.in, utypes.h...\n",  ICUDATA_NAME, U_ICUDATA_NAME);
1194     }
1195     else
1196     {
1197         log_verbose("ICUDATA_NAME=%s (from icudefs.mk), U_ICUDATA_NAME=%s (from utypes.h)\n", ICUDATA_NAME, U_ICUDATA_NAME);
1198     }
1199 #endif
1200 
1201 }
1202 
1203 /* test data swapping ------------------------------------------------------- */
1204 
1205 #if U_PLATFORM == U_PF_OS400
1206 /* See comments in genccode.c on when this special implementation can be removed. */
1207 static const struct {
1208     double bogus;
1209     const char *bytes;
1210 } gOffsetTOCAppDataItem1={ 0.0, /* alignment bytes */
1211     "\x00\x14" /* sizeof(UDataInfo) *//* MappedData { */
1212     "\xda"
1213     "\x27"                            /* } */
1214     "\x00\x14" /* sizeof(UDataInfo) *//* UDataInfo  { */
1215     "\0\0"
1216     "\1"       /* U_IS_BIG_ENDIAN   */
1217     "\1"       /* U_CHARSET_FAMILY  */
1218     "\2"       /* U_SIZEOF_WHAR_T   */
1219     "\0"
1220     "\x31\x31\x31\x31"
1221     "\0\0\0\0"
1222     "\0\0\0\0"                        /* } */
1223 };
1224 #else
1225 static const struct {
1226     double bogus;
1227     MappedData bytes1;
1228     UDataInfo bytes2;
1229     uint8_t bytes3;
1230 } gOffsetTOCAppDataItem1={
1231     0.0,                            /* alignment bytes */
1232     { sizeof(UDataInfo), 0xda, 0x27 },  /* MappedData */
1233 
1234     {sizeof(UDataInfo),
1235     0,
1236 
1237     U_IS_BIG_ENDIAN,
1238     U_CHARSET_FAMILY,
1239     sizeof(UChar),
1240     0,
1241 
1242     {0x31, 0x31, 0x31, 0x31},     /* dataFormat="1111" */
1243     {0, 0, 0, 0},                 /* formatVersion */
1244     {0, 0, 0, 0}},                /* dataVersion */
1245     0
1246 };
1247 #endif
1248 
1249 static const UChar gOffsetTOCGarbage[] = { /* "I have been very naughty!" */
1250     0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E,
1251     0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6E, 0x61, 0x75, 0x67, 0x68, 0x74, 0x79, 0x21
1252 };
1253 
1254 /* Original source: icu/source/tools/genccode */
1255 static const struct {
1256     uint16_t headerSize;
1257     uint8_t magic1, magic2;
1258     UDataInfo info;
1259     char padding[8];
1260     uint32_t count, reserved;
1261     const struct {
1262         const char *const name;
1263         const void *const data;
1264     } toc[3];
1265 } gOffsetTOCAppData_dat = {
1266     32,          /* headerSize */
1267     0xda,        /* magic1,  (see struct MappedData in udata.c)  */
1268     0x27,        /* magic2     */
1269     {            /*UDataInfo   */
1270         sizeof(UDataInfo),      /* size        */
1271         0,                      /* reserved    */
1272         U_IS_BIG_ENDIAN,
1273         U_CHARSET_FAMILY,
1274         sizeof(UChar),
1275         0,               /* reserved      */
1276         {                /* data format identifier */
1277            0x54, 0x6f, 0x43, 0x50}, /* "ToCP" */
1278            {1, 0, 0, 0},   /* format version major, minor, milli, micro */
1279            {0, 0, 0, 0}    /* dataVersion   */
1280     },
1281     {0,0,0,0,0,0,0,0},  /* Padding[8]   */
1282     3,                  /* count        */
1283     0,                  /* Reserved     */
1284     {                   /*  TOC structure */
1285         { "OffsetTOCAppData/a/b", &gOffsetTOCAppDataItem1 },
1286         { "OffsetTOCAppData/gOffsetTOCAppDataItem1", &gOffsetTOCAppDataItem1 },
1287         { "OffsetTOCAppData/gOffsetTOCGarbage", &gOffsetTOCGarbage }
1288     }
1289 };
1290 
1291 /* Unfortunately, dictionaries are in a C++ header */
1292 U_CAPI int32_t U_EXPORT2
1293 udict_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData, UErrorCode *pErrorCode);
1294 
1295 /* test cases for maximum data swapping code coverage */
1296 static const struct {
1297     const char *name, *type;
1298     UDataSwapFn *swapFn;
1299 } swapCases[]={
1300     /* resource bundles */
1301 
1302     /* resource bundle with many data types */
1303     {"*testtypes",               "res", ures_swap},
1304     /* resource bundle with collation data */
1305     {"ja",                       "res", ures_swap},
1306     /* resource bundle with options-only collation data */
1307     {"ru",                       "res", ures_swap},
1308     {"el",                       "res", ures_swap},
1309     /* ICU's root */
1310     {"root",                     "res", ures_swap},
1311     /* Test a 32-bit key table. This is large. */
1312     {"*testtable32",             "res", ures_swap},
1313 
1314     /* ICU 4.2 resource bundle - data format 1.2 (little-endian ASCII) */
1315     {"*old_l_testtypes",         "res", ures_swap},
1316     /* same for big-endian EBCDIC */
1317     {"*old_e_testtypes",         "res", ures_swap},
1318 
1319 #if !UCONFIG_NO_COLLATION
1320     /* standalone collation data files */
1321     {"ucadata",                  "icu", ucol_swap},
1322 #if 0
1323     /* Starting with ICU 53, the "inverse UCA" data is integrated into ucadata.icu. */
1324     {"invuca",                   "icu", ucol_swapInverseUCA},
1325 #endif
1326 #endif
1327 
1328 #if !UCONFIG_NO_LEGACY_CONVERSION
1329     /* conversion table files */
1330 
1331     /* SBCS conversion table file without extension */
1332     {"ibm-913_P100-2000",   "cnv", ucnv_swap},
1333     /* EBCDIC_STATEFUL conversion table file with extension */
1334     {"ibm-1390_P110-2003",       "cnv", ucnv_swap},
1335     /* DBCS extension-only conversion table file */
1336     {"ibm-16684_P110-2003",      "cnv", ucnv_swap},
1337     /* EUC-TW (3-byte) conversion table file without extension */
1338     {"ibm-964_P110-1999",        "cnv", ucnv_swap},
1339     /* GB 18030 (4-byte) conversion table file without extension */
1340     {"gb18030-2022",             "cnv", ucnv_swap},
1341     /* MBCS conversion table file with extension */
1342     {"*test4x",                  "cnv", ucnv_swap},
1343     /*
1344      * MBCS conversion table file without extension,
1345      * to test swapping and preflighting of UTF-8-friendly mbcsIndex[].
1346      */
1347     {"jisx-212",                 "cnv", ucnv_swap},
1348 #endif
1349 
1350 #if !UCONFIG_NO_CONVERSION
1351     /* alias table */
1352     {"cnvalias",                 "icu", ucnv_swapAliases},
1353 #endif
1354 
1355 #if !UCONFIG_NO_IDNA
1356     {"rfc3491",                    "spp", usprep_swap},
1357 #endif
1358 
1359 #if !UCONFIG_NO_BREAK_ITERATION
1360     {"char",                     "brk", ubrk_swap},
1361     {"laodict",                  "dict",udict_swap},
1362 #endif
1363 
1364 #if 0
1365     /*
1366      * Starting with ICU 4.8, the Unicode property (value) aliases data
1367      * is hardcoded in the ICU4C common library.
1368      * The swapper was moved to the toolutil library for swapping for ICU4J.
1369      */
1370     /* Unicode properties */
1371     {"pnames",                   "icu", upname_swap},
1372 #endif
1373 
1374 #if 0
1375     /*
1376      * Starting with ICU4C 3.4, the core Unicode properties files
1377      * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu)
1378      * are hardcoded in the common DLL and therefore not included
1379      * in the data package any more.
1380      * Their swapping code is moved from the common DLL to the icuswap tool so that
1381      * we need not jump through hoops (like adding snapshots of these files
1382      * to testdata) for code coverage in tests.
1383      * See Jitterbug 4497.
1384      *
1385      * ICU4C 4.4 adds normalization data files again, e.g., nfkc.nrm.
1386      */
1387     {"uprops",                   "icu", uprops_swap},
1388     {"ucase",                    "icu", ucase_swap},
1389     {"ubidi",                    "icu", ubidi_swap},
1390 #endif
1391 #if !UCONFIG_NO_NORMALIZATION && !UCONFIG_ONLY_COLLATION
1392     {"nfkc",                     "nrm", unorm2_swap},
1393 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
1394     {"confusables",              "cfu", uspoof_swap}, /* spoof data missing without regex */
1395 #endif
1396 
1397 #endif
1398     {"unames",                   "icu", uchar_swapNames}
1399     /* the last item should not be #if'ed so that it can reliably omit the last comma */
1400 };
1401 
1402 /* Large enough for the largest swappable data item. */
1403 #define SWAP_BUFFER_SIZE 1800000
1404 
1405 static void U_CALLCONV
printError(void * context,const char * fmt,va_list args)1406 printError(void *context, const char *fmt, va_list args) {
1407     (void)context; // suppress compiler warnings about unused variable
1408     vlog_info("[swap] ", fmt, args);
1409     log_err("\n");  /* Register error */
1410 }
1411 
1412 static void
TestSwapCase(UDataMemory * pData,const char * name,UDataSwapFn * swapFn,uint8_t * buffer,uint8_t * buffer2)1413 TestSwapCase(UDataMemory *pData, const char *name,
1414              UDataSwapFn *swapFn,
1415              uint8_t *buffer, uint8_t *buffer2) {
1416     UDataSwapper *ds;
1417     const void *inData, *inHeader;
1418     int32_t length, dataLength, length2, headerLength;
1419 
1420     UErrorCode errorCode;
1421     UErrorCode badStatus;
1422 
1423     UBool inEndian, oppositeEndian;
1424     uint8_t inCharset, oppositeCharset;
1425 
1426     /* First we check that swapFn handles failures as expected. */
1427     errorCode = U_UNSUPPORTED_ERROR;
1428     length = swapFn(NULL, NULL, 0, buffer, &errorCode);
1429     if (length != 0 || errorCode != U_UNSUPPORTED_ERROR) {
1430         log_err("%s() did not fail as expected - %s\n", name, u_errorName(errorCode));
1431     }
1432     errorCode = U_ZERO_ERROR;
1433     length = swapFn(NULL, NULL, 0, buffer, &errorCode);
1434     if (length != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1435         log_err("%s() did not fail as expected with bad arguments - %s\n", name, u_errorName(errorCode));
1436     }
1437 
1438 
1439     /* Continue with the rest of the tests. */
1440     errorCode = U_ZERO_ERROR;
1441     inData=udata_getMemory(pData);
1442 
1443     /*
1444      * get the data length if possible, to verify that swapping and preflighting
1445      * handles the entire data
1446      */
1447     dataLength=udata_getLength(pData);
1448 
1449     /*
1450      * get the header and its length
1451      * all of the swap implementation functions require the header to be included
1452      */
1453     inHeader=udata_getRawMemory(pData);
1454     headerLength=(int32_t)((const char *)inData-(const char *)inHeader);
1455 
1456     /* first swap to opposite endianness but same charset family */
1457     errorCode=U_ZERO_ERROR;
1458     ds=udata_openSwapperForInputData(inHeader, headerLength,
1459             !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
1460     if(U_FAILURE(errorCode)) {
1461         log_err("udata_openSwapperForInputData(%s->!isBig+same charset) failed - %s\n",
1462                 name, u_errorName(errorCode));
1463         return;
1464     }
1465 
1466     inEndian=ds->inIsBigEndian;
1467     inCharset=ds->inCharset;
1468 
1469     oppositeEndian=!inEndian;
1470     oppositeCharset= inCharset==U_ASCII_FAMILY ? U_EBCDIC_FAMILY : U_ASCII_FAMILY;
1471 
1472     /* make this test work with data files that are built for a different platform */
1473     if(inEndian!=U_IS_BIG_ENDIAN || inCharset!=U_CHARSET_FAMILY) {
1474         udata_closeSwapper(ds);
1475         ds=udata_openSwapper(inEndian, inCharset, oppositeEndian, inCharset, &errorCode);
1476         if(U_FAILURE(errorCode)) {
1477             log_err("udata_openSwapper(%s->!isBig+same charset) failed - %s\n",
1478                     name, u_errorName(errorCode));
1479             return;
1480         }
1481     }
1482 
1483     /*
1484     Check error checking of swappable data not specific to this swapper.
1485     This should always fail.
1486     */
1487     badStatus = U_ZERO_ERROR;
1488     length=swapFn(ds, &gOffsetTOCAppData_dat, -1, NULL, &badStatus);
1489     if(badStatus != U_UNSUPPORTED_ERROR) {
1490         log_err("swapFn(%s->!isBig+same charset) unexpectedly succeeded on bad data - %s\n",
1491                 name, u_errorName(errorCode));
1492         udata_closeSwapper(ds);
1493         return;
1494     }
1495 
1496     /* Now allow errors to be printed */
1497     ds->printError=printError;
1498 
1499     /* preflight the length */
1500     length=swapFn(ds, inHeader, -1, NULL, &errorCode);
1501     if(U_FAILURE(errorCode)) {
1502         log_err("swapFn(preflight %s->!isBig+same charset) failed - %s\n",
1503                 name, u_errorName(errorCode));
1504         udata_closeSwapper(ds);
1505         return;
1506     }
1507 
1508     /* compare the preflighted length against the data length */
1509     if(dataLength>=0 && (length+15)<(headerLength+dataLength)) {
1510         log_err("swapFn(preflight %s->!isBig+same charset) length too small: %d < data length %d\n",
1511                 name, length, (headerLength+dataLength));
1512         udata_closeSwapper(ds);
1513         return;
1514     }
1515 
1516     /* swap, not in-place */
1517     length2=swapFn(ds, inHeader, length, buffer, &errorCode);
1518     udata_closeSwapper(ds);
1519     if(U_FAILURE(errorCode)) {
1520         log_err("swapFn(%s->!isBig+same charset) failed - %s\n",
1521                 name, u_errorName(errorCode));
1522         return;
1523     }
1524 
1525     /* compare the swap length against the preflighted length */
1526     if(length2!=length) {
1527         log_err("swapFn(%s->!isBig+same charset) length differs from preflighting: %d != preflighted %d\n",
1528                 name, length2, length);
1529         return;
1530     }
1531 
1532     /* next swap to opposite charset family */
1533     ds=udata_openSwapper(oppositeEndian, inCharset,
1534                          oppositeEndian, oppositeCharset,
1535                          &errorCode);
1536     if(U_FAILURE(errorCode)) {
1537         log_err("udata_openSwapper(%s->!isBig+other charset) failed - %s\n",
1538                 name, u_errorName(errorCode));
1539         return;
1540     }
1541     ds->printError=printError;
1542 
1543     /* swap in-place */
1544     length2=swapFn(ds, buffer, length, buffer, &errorCode);
1545     udata_closeSwapper(ds);
1546     if(U_FAILURE(errorCode)) {
1547         log_err("swapFn(%s->!isBig+other charset) failed - %s\n",
1548                 name, u_errorName(errorCode));
1549         return;
1550     }
1551 
1552     /* compare the swap length against the original length */
1553     if(length2!=length) {
1554         log_err("swapFn(%s->!isBig+other charset) length differs from original: %d != original %d\n",
1555                 name, length2, length);
1556         return;
1557     }
1558 
1559     /* finally swap to original platform values */
1560     ds=udata_openSwapper(oppositeEndian, oppositeCharset,
1561                          inEndian, inCharset,
1562                          &errorCode);
1563     if(U_FAILURE(errorCode)) {
1564         log_err("udata_openSwapper(%s->back to original) failed - %s\n",
1565                 name, u_errorName(errorCode));
1566         return;
1567     }
1568     ds->printError=printError;
1569 
1570     /* swap, not in-place */
1571     length2=swapFn(ds, buffer, length, buffer2, &errorCode);
1572     udata_closeSwapper(ds);
1573     if(U_FAILURE(errorCode)) {
1574         log_err("swapFn(%s->back to original) failed - %s\n",
1575                 name, u_errorName(errorCode));
1576         return;
1577     }
1578 
1579     /* compare the swap length against the original length */
1580     if(length2!=length) {
1581         log_err("swapFn(%s->back to original) length differs from original: %d != original %d\n",
1582                 name, length2, length);
1583         return;
1584     }
1585 
1586     /* compare the final contents with the original */
1587     if(0!=uprv_memcmp(inHeader, buffer2, length)) {
1588         const uint8_t *original;
1589         uint8_t diff[8];
1590         int32_t i, j;
1591 
1592         log_err("swapFn(%s->back to original) contents differs from original\n",
1593                 name);
1594 
1595         /* find the first difference */
1596         original=(const uint8_t *)inHeader;
1597         for(i=0; i<length && original[i]==buffer2[i]; ++i) {}
1598 
1599         /* find the next byte that is the same */
1600         for(j=i+1; j<length && original[j]!=buffer2[j]; ++j) {}
1601         log_info("    difference at index %d=0x%x, until index %d=0x%x\n", i, i, j, j);
1602 
1603         /* round down to the last 4-boundary for better result output */
1604         i&=~3;
1605         log_info("showing bytes from index %d=0x%x (length %d=0x%x):\n", i, i, length, length);
1606 
1607         /* print 8 bytes but limit to the buffer contents */
1608         length2=i+sizeof(diff);
1609         if(length2>length) {
1610             length2=length;
1611         }
1612 
1613         /* print the original bytes */
1614         uprv_memset(diff, 0, sizeof(diff));
1615         for(j=i; j<length2; ++j) {
1616             diff[j-i]=original[j];
1617         }
1618         log_info("    original: %02x %02x %02x %02x %02x %02x %02x %02x\n",
1619             diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
1620 
1621         /* print the swapped bytes */
1622         uprv_memset(diff, 0, sizeof(diff));
1623         for(j=i; j<length2; ++j) {
1624             diff[j-i]=buffer2[j];
1625         }
1626         log_info("    swapped:  %02x %02x %02x %02x %02x %02x %02x %02x\n",
1627             diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
1628     }
1629 }
1630 
1631 static void U_CALLCONV
printErrorToString(void * context,const char * fmt,va_list args)1632 printErrorToString(void *context, const char *fmt, va_list args) {
1633     vsnprintf((char *)context, 100, fmt, args);
1634 }
1635 
1636 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1637 static void
TestSwapData(void)1638 TestSwapData(void) {
1639     char name[100];
1640     UDataSwapper *ds;
1641     UDataMemory *pData;
1642     uint8_t *buffer;
1643     const char *pkg, *nm, *testPath;
1644     UErrorCode errorCode = U_ZERO_ERROR;
1645     int32_t i;
1646 
1647     buffer=(uint8_t *)malloc(2*SWAP_BUFFER_SIZE);
1648     if(buffer==NULL) {
1649         log_err("unable to allocate %d bytes\n", 2*SWAP_BUFFER_SIZE);
1650         return;
1651     }
1652 
1653     testPath=loadTestData(&errorCode);
1654     if(U_FAILURE(errorCode)) {
1655         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode));
1656     }
1657 
1658     /* Test that printError works as expected. */
1659     errorCode=U_USELESS_COLLATOR_ERROR;
1660     ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1661                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1662                          &errorCode);
1663     if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) {
1664         log_err("udata_openSwapper should have returned NULL with bad argument\n", name);
1665     }
1666     errorCode=U_ZERO_ERROR;
1667     ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1668                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1669                          &errorCode);
1670     ds->printError=printErrorToString;
1671     ds->printErrorContext=name;
1672     udata_printError(ds, "This %s a %s", "is", "test");
1673     udata_closeSwapper(ds);
1674     if (strcmp(name, "This is a test") != 0) {
1675         log_err("udata_printError can't properly print error messages. Got = %s\n", name);
1676     }
1677     errorCode = U_USELESS_COLLATOR_ERROR;
1678     ds=udata_openSwapperForInputData(NULL, 0,
1679                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1680                          &errorCode);
1681     if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) {
1682         log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
1683     }
1684     errorCode=U_ZERO_ERROR;
1685     ds=udata_openSwapperForInputData(NULL, 0,
1686                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1687                          &errorCode);
1688     if (ds != NULL || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1689         log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
1690     }
1691     errorCode=U_ZERO_ERROR;
1692     memset(buffer, 0, sizeof(2*SWAP_BUFFER_SIZE));
1693     ds=udata_openSwapperForInputData(buffer, 2*SWAP_BUFFER_SIZE,
1694                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1695                          &errorCode);
1696     if (ds != NULL || errorCode != U_UNSUPPORTED_ERROR) {
1697         log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
1698     }
1699     errorCode=U_ZERO_ERROR;
1700 
1701     /* Test argument checking. ucol_swap is normally tested via ures_swap, and isn't normally called directly. */
1702 #if !UCONFIG_NO_COLLATION
1703     ucol_swap(NULL, NULL, -1, NULL, &errorCode);
1704     if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1705         log_err("ucol_swap did not fail as expected\n", name);
1706     }
1707     errorCode=U_ZERO_ERROR;
1708 #endif
1709 
1710     for(i=0; i<UPRV_LENGTHOF(swapCases); ++i) {
1711         /* build the name for logging */
1712         errorCode=U_ZERO_ERROR;
1713         if(swapCases[i].name[0]=='*') {
1714             pkg=testPath;
1715             nm=swapCases[i].name+1;
1716             uprv_strcpy(name, "testdata");
1717         } else if (uprv_strcmp(swapCases[i].type, "brk")==0
1718             || uprv_strcmp(swapCases[i].type, "dict")==0) {
1719             pkg=U_ICUDATA_BRKITR;
1720             nm=swapCases[i].name;
1721             uprv_strcpy(name, U_ICUDATA_BRKITR);
1722 #if !UCONFIG_NO_COLLATION
1723         } else if (uprv_strcmp(swapCases[i].name, "ucadata")==0
1724             || uprv_strcmp(swapCases[i].name, "invuca")==0) {
1725             pkg=U_ICUDATA_COLL;
1726             nm=swapCases[i].name;
1727             uprv_strcpy(name, U_ICUDATA_COLL);
1728 #endif  /* !UCONFIG_NO_COLLATION */
1729         } else {
1730             pkg=NULL;
1731             nm=swapCases[i].name;
1732             uprv_strcpy(name, "NULL");
1733         }
1734         uprv_strcat(name, "/");
1735         uprv_strcat(name, nm);
1736         uprv_strcat(name, ".");
1737         uprv_strcat(name, swapCases[i].type);
1738 
1739         pData=udata_open(pkg, swapCases[i].type, nm, &errorCode);
1740 
1741         if(U_SUCCESS(errorCode)) {
1742             TestSwapCase(pData, name, swapCases[i].swapFn, buffer, buffer+SWAP_BUFFER_SIZE);
1743             udata_close(pData);
1744         } else {
1745             log_data_err("udata_open(%s) failed - %s\n",
1746                 name, u_errorName(errorCode));
1747         }
1748     }
1749 
1750     free(buffer);
1751 }
1752 #endif
1753 
PointerTableOfContents(void)1754 static void PointerTableOfContents(void) {
1755     UDataMemory      *dataItem;
1756     UErrorCode        status=U_ZERO_ERROR;
1757 
1758     /*
1759      * Got testdata.dat into memory, now we try setAppData using the memory image.
1760      */
1761 
1762     status=U_ZERO_ERROR;
1763     udata_setAppData("OffsetTOCAppData", &gOffsetTOCAppData_dat, &status);
1764     if (status != U_ZERO_ERROR) {
1765         log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) \n"
1766                 " returned status of %s\n", u_errorName(status));
1767         return;
1768     }
1769 
1770     dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCAppDataItem1", &status);
1771     if (U_FAILURE(status)) {
1772         log_err("FAIL: gOffsetTOCAppDataItem1 could not be opened. status = %s\n", u_errorName(status));
1773     }
1774     if (udata_getMemory(dataItem) != NULL) {
1775         log_verbose("FAIL: udata_getMemory(dataItem) passed\n");
1776     }
1777     else {
1778         log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status));
1779     }
1780     udata_close(dataItem);
1781 
1782     dataItem = udata_open("OffsetTOCAppData-a", "", "b", &status);
1783     if (U_FAILURE(status)) {
1784         log_err("FAIL: gOffsetTOCAppDataItem1 in tree \"a\" could not be opened. status = %s\n", u_errorName(status));
1785     }
1786     if (udata_getMemory(dataItem) != NULL) {
1787         log_verbose("FAIL: udata_getMemory(dataItem) in tree \"a\" passed\n");
1788     }
1789     else {
1790         log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status));
1791     }
1792     udata_close(dataItem);
1793 
1794     dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCGarbage", &status);
1795     if (U_SUCCESS(status)) {
1796         log_err("FAIL: gOffsetTOCGarbage should not be opened. status = %s\n", u_errorName(status));
1797     }
1798     dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCNonExistent", &status);
1799     if (U_SUCCESS(status)) {
1800         log_err("FAIL: gOffsetTOCNonExistent should not be found. status = %s\n", u_errorName(status));
1801     }
1802 
1803 }
1804 
SetBadCommonData(void)1805 static void SetBadCommonData(void) {
1806     /* It's difficult to test that udata_setCommonData really works within the test framework.
1807        So we just test that foolish people can't do bad things. */
1808     UErrorCode status;
1809     char badBuffer[sizeof(gOffsetTOCAppData_dat)];
1810 
1811     memset(badBuffer, 0, sizeof(badBuffer));
1812     strcpy(badBuffer, "Hello! I'm not good data.");
1813 
1814     /* Check that we don't do anything */
1815     status = U_FILE_ACCESS_ERROR;
1816     udata_setCommonData(&gOffsetTOCAppData_dat, &status);
1817     if (status != U_FILE_ACCESS_ERROR) {
1818         log_err("FAIL: udata_setCommonData changed the failure code.\n");
1819     }
1820     /* Check that we fail correctly */
1821     status = U_ZERO_ERROR;
1822     udata_setCommonData(NULL, &status);
1823     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1824         log_err("FAIL: udata_setCommonData did not fail with bad arguments.\n");
1825     }
1826 
1827     /* Check that we verify that the data isn't bad */
1828     status = U_ZERO_ERROR;
1829     udata_setAppData("invalid path", badBuffer, &status);
1830     if (status != U_INVALID_FORMAT_ERROR) {
1831         log_err("FAIL: udata_setAppData doesn't verify data validity.\n");
1832     }
1833 }
1834 
1835 // Check the override loading of time zone .res files from a specified path
1836 //
1837 // Hand testing notes:
1838 //   1. Run this test with the environment variable set. The following should induce faiures:
1839 //        ICU_TIMEZONE_FILES_DIR=../testdata/out/build LD_LIBRARY_PATH=../../lib:../../stubdata:../../tools/ctestfw:$LD_LIBRARY_PATH  ./cintltst /udatatst/TestTZDataDir
1840 //   2. Build ICU with with U_TIMEZONE_FILES_DIR defined. This should also induce failures.
1841 //        CPPFLAGS=-DU_TIMEZONE_FILES_DIR\=`pwd`/test/testdata/out/testdata ./runConfigureICU Linux
1842 //        make check
1843 
TestTZDataDir(void)1844 static void TestTZDataDir(void) {
1845 #if !UCONFIG_NO_FORMATTING
1846     UErrorCode status = U_ZERO_ERROR;
1847     const char *tzDataVersion;
1848     const char *testDataPath;
1849 
1850     // Verify that default ICU time zone data version is something newer than 2014a.
1851     tzDataVersion = ucal_getTZDataVersion(&status);
1852     // printf("tz data version is %s\n", tzDataVersion);
1853     if (U_FAILURE(status)) {
1854         log_data_err("Failed call to ucal_getTZDataVersion - %s\n", u_errorName(status));
1855         return;
1856     } else if (strcmp("2014a", tzDataVersion) == 0) {
1857         log_err("File %s:%d - expected something newer than time zone data 2014a.\n", __FILE__, __LINE__, tzDataVersion);
1858     }
1859 
1860     testDataPath = loadTestData(&status);
1861     // The path produced by loadTestData() will look something like
1862     //     whatever/.../testdata/out/testdata
1863     // The test data puts an old (2014a) version of the time zone data there.
1864 
1865     // Switch ICU to the testdata version of zoneinfo64.res, which is version 2014a.
1866     ctest_resetICU();
1867     u_setTimeZoneFilesDirectory(testDataPath, &status);
1868     tzDataVersion = ucal_getTZDataVersion(&status);
1869     if (strcmp("2014a", tzDataVersion) != 0) {
1870         log_err("File %s:%d - expected \"2014a\"; actual \"%s\"\n", __FILE__, __LINE__, tzDataVersion);
1871     }
1872 
1873     ctest_resetICU();   // Return ICU to using its standard tz data.
1874     tzDataVersion = ucal_getTZDataVersion(&status);
1875     // printf("tz data version is %s\n", tzDataVersion);
1876     if (strcmp("2014a", tzDataVersion) == 0) {
1877         log_err("File %s:%d - expected something newer than time zone data 2014a.\n", __FILE__, __LINE__, tzDataVersion);
1878     }
1879 #endif
1880 }
1881