• 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()120 static void TestUDataOpen(){
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()445 static void TestUDataSetAppData(){
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()500 static char *safeGetICUDataDirectory() {
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()510 static void TestUDataFileAccess(){
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()647 static void TestUDataOpenChoiceDemo1() {
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         log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
712     }
713 
714     status=U_USELESS_COLLATOR_ERROR;
715     result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status);
716     if(status != U_USELESS_COLLATOR_ERROR){
717         log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
718     }
719 }
720 
721 static UBool U_CALLCONV
isAcceptable(void * context,const char * type,const char * name,const UDataInfo * pInfo)722 isAcceptable(void *context,
723              const char *type, const char *name,
724              const UDataInfo *pInfo){
725     if( pInfo->size>=20 &&
726         pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
727         pInfo->charsetFamily==U_CHARSET_FAMILY &&
728         pInfo->dataFormat[0]==0x54 &&   /* dataFormat="test" */
729         pInfo->dataFormat[1]==0x65 &&
730         pInfo->dataFormat[2]==0x73 &&
731         pInfo->dataFormat[3]==0x74 &&
732         pInfo->formatVersion[0]==1 &&
733         pInfo->dataVersion[0]==1   &&
734         *((int*)context) == 2 ) {
735         log_verbose("The data from\"%s.%s\" IS acceptable using the verifying function isAcceptable()\n", name, type);
736 
737         return true;
738     } else {
739         log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifying function isAcceptable()\n", name, type);
740         return false;
741     }
742 }
743 
744 
745 /* This test checks to see if the isAcceptable function is being called correctly. */
746 
TestUDataOpenChoiceDemo2()747 static void TestUDataOpenChoiceDemo2() {
748     UDataMemory *result;
749     UErrorCode status=U_ZERO_ERROR;
750     int i;
751     int p=2;
752 
753     const char* name="test";
754     const char* type="icu";
755     const char* path = loadTestData(&status);
756     if(U_FAILURE(status)) {
757         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
758         return;
759     }
760 
761     result=udata_openChoice(path, type, name, isAcceptable, &p, &status);
762     if(U_FAILURE(status)){
763         log_data_err("failed to load data at p=%s t=%s n=%s, isAcceptable", path, type, name);
764     }
765     if(U_SUCCESS(status) ) {
766         udata_close(result);
767     }
768 
769     p=0;
770     for(i=0;i<2; i++){
771         result=udata_openChoice(path, type, name, isAcceptable, &p, &status);
772         if(p<2) {
773             if(U_FAILURE(status) && status==U_INVALID_FORMAT_ERROR){
774                 log_verbose("Loads the data but rejects it as expected %s\n", myErrorName(status));
775                 status=U_ZERO_ERROR;
776                 p++;
777             }
778             else {
779                 log_data_err("FAIL: failed to either load the data or to reject the loaded data. ERROR=%s\n", myErrorName(status) );
780             }
781         }
782         else if(p == 2) {
783             if(U_FAILURE(status)) {
784                 log_data_err("FAIL: failed to load the data and accept it.  ERROR=%s\n", myErrorName(status) );
785             }
786             else {
787                 log_verbose("Loads the data and accepts it for p==2 as expected\n");
788                 udata_close(result);
789             }
790         }
791     }
792 }
793 
TestUDataGetInfo()794 static void TestUDataGetInfo() {
795 
796     UDataMemory *result;
797     /* UDataInfo cf. udata.h */
798     static UDataInfo dataInfo={
799     30,    /*sizeof(UDataInfo),*/
800     0,
801 
802     U_IS_BIG_ENDIAN,
803     U_CHARSET_FAMILY,
804     sizeof(UChar),
805     0,
806 
807     {0x54, 0x65, 0x73, 0x74},     /* dataFormat="Test" */
808     {9, 0, 0, 0},                 /* formatVersion */
809     {4, 0, 0, 0}                  /* dataVersion */
810     };
811     UErrorCode status=U_ZERO_ERROR;
812     const char* name="cnvalias";
813     const char* name2="test";
814     const char* type="icu";
815 
816     const char* testPath=loadTestData(&status);
817     if(U_FAILURE(status)) {
818         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
819         return;
820     }
821 
822     log_verbose("Testing udata_getInfo() for cnvalias.icu\n");
823     result=udata_open(NULL, "icu", name, &status);
824     if(U_FAILURE(status)){
825         log_data_err("FAIL: udata_open() failed for path = NULL, name=%s, type=%s, \n errorcode=%s\n",  name, type, myErrorName(status));
826         return;
827     }
828     udata_getInfo(result, &dataInfo);
829     if(dataInfo.size==20            &&  dataInfo.size!=30 &&
830         dataInfo.isBigEndian==U_IS_BIG_ENDIAN       &&
831         dataInfo.charsetFamily==U_CHARSET_FAMILY    &&
832         dataInfo.dataFormat[0]==0x43 &&  dataInfo.dataFormat[0]!=0x54 && /* dataFormat="CvAl" and not "Test". The values are set for cnvalias.dat*/
833         dataInfo.dataFormat[1]==0x76 &&  dataInfo.dataFormat[1]!=0x65 &&
834         dataInfo.dataFormat[2]==0x41 &&  dataInfo.dataFormat[2]!=0x73 &&
835         dataInfo.dataFormat[3]==0x6c &&  dataInfo.dataFormat[3]!=0x74 &&
836         dataInfo.formatVersion[0]!=9 && /*formatVersion is also set to the one for cnvalias*/
837         dataInfo.dataVersion[0]!=4   && /*dataVersion*/
838         dataInfo.dataVersion[1]!=0   ){
839             log_verbose("PASS: udata_getInfo() filled in the right values\n");
840     } else {
841         log_err("FAIL: udata_getInfo() filled in the wrong values\n");
842     }
843     udata_close(result);
844 
845 
846     log_verbose("Testing udata_getInfo() for test.icu\n");
847     result=udata_open(testPath, type, name2, &status);
848     if(U_FAILURE(status)) {
849        log_data_err("FAIL: udata_open() failed for path=%s name2=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status));
850        return;
851     }
852     udata_getInfo(result, &dataInfo);
853     if(dataInfo.size==20             &&
854         dataInfo.isBigEndian==U_IS_BIG_ENDIAN       &&
855         dataInfo.charsetFamily==U_CHARSET_FAMILY    &&
856         dataInfo.dataFormat[0]==0x54 &&   /* dataFormat="Test". The values are set for test.dat*/
857         dataInfo.dataFormat[1]==0x65 &&
858         dataInfo.dataFormat[2]==0x73 &&
859         dataInfo.dataFormat[3]==0x74 &&
860         dataInfo.formatVersion[0]==1 &&  /*formatVersion is also set to the one for test*/
861         dataInfo.dataVersion[0]==1   &&  /*dataVersion*/
862         dataInfo.dataVersion[1]==0   )
863     {
864         log_verbose("PASS: udata_getInfo() filled in the right values\n");
865     } else {
866         log_err("FAIL: udata_getInfo() filled in the wrong values\n");
867     }
868     udata_close(result);
869 }
870 
TestUDataGetMemory()871 static void TestUDataGetMemory() {
872 
873     UDataMemory *result;
874     const int32_t *table=NULL;
875     uint16_t* intValue=0;
876     UErrorCode status=U_ZERO_ERROR;
877     const char* name="cnvalias";
878     const char* type;
879 
880     const char* name2="test";
881 
882     const char* testPath = loadTestData(&status);
883     if(U_FAILURE(status)) {
884         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
885         return;
886     }
887 
888     type="icu";
889     log_verbose("Testing udata_getMemory() for \"cnvalias.icu\"\n");
890     result=udata_openChoice(NULL, type, name, isAcceptable1, NULL, &status);
891     if(U_FAILURE(status)){
892         log_data_err("FAIL: udata_openChoice() failed for name=%s, type=%s, \n errorcode=%s\n", name, type, myErrorName(status));
893         return;
894     }
895     table=(const int32_t *)udata_getMemory(result);
896 
897     /* The alias table may list more converters than what's actually available now. [grhoten] */
898     if(ucnv_countAvailable() > table[1])      /*???*/
899         log_err("FAIL: udata_getMemory() failed ucnv_countAvailable returned = %d, expected = %d\n", ucnv_countAvailable(), table[1+2*(*table)]);
900 
901     udata_close(result);
902 
903     type="icu";
904     log_verbose("Testing udata_getMemory for \"test.icu\"()\n");
905     result=udata_openChoice(testPath, type, name2, isAcceptable3, NULL, &status);
906     if(U_FAILURE(status)){
907         log_data_err("FAIL: udata_openChoice() failed for path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status));
908         return;
909     }
910     intValue=(uint16_t *)udata_getMemory(result);
911     /*printf("%d ..... %s", *(intValue), intValue+1));*/
912     if( *intValue != 2000 || strcmp((char*)(intValue+1), "YEAR") != 0 )
913         log_err("FAIL: udata_getMemory() failed: intValue :- Expected:2000 Got:%d \n\tstringValue:- Expected:YEAR Got:%s\n", *intValue, (intValue+1));
914 
915     udata_close(result);
916 
917 }
918 
TestErrorConditions()919 static void TestErrorConditions(){
920 
921     UDataMemory *result=NULL;
922     UErrorCode status=U_ZERO_ERROR;
923     uint16_t* intValue=0;
924     static UDataInfo dataInfo={
925         30,    /*sizeof(UDataInfo),*/
926         0,
927 
928         U_IS_BIG_ENDIAN,
929         U_CHARSET_FAMILY,
930         sizeof(UChar),
931         0,
932 
933         {0x54, 0x65, 0x73, 0x74},     /* dataFormat="Test" */
934         {9, 0, 0, 0},                 /* formatVersion */
935         {4, 0, 0, 0}                  /* dataVersion */
936     };
937 
938     const char* name = "test";
939     const char* type="icu";
940 
941     const char *testPath = loadTestData(&status);
942     if(U_FAILURE(status)) {
943         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
944         return;
945     }
946 
947     status = U_ILLEGAL_ARGUMENT_ERROR;
948     /*Try udata_open with status != U_ZERO_ERROR*/
949     log_verbose("Testing udata_open() with status != U_ZERO_ERROR\n");
950     result=udata_open(testPath, type, name, &status);
951     if(result != NULL){
952         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);
953         udata_close(result);
954 
955     } else {
956         log_verbose("PASS: udata_open with errorCode != U_ZERO_ERROR failed as expected\n");
957     }
958 
959     /*Try udata_open with data name=NULL*/
960     log_verbose("Testing udata_open() with data name=NULL\n");
961     status=U_ZERO_ERROR;
962     result=udata_open(testPath, type, NULL, &status);
963     if(U_FAILURE(status)){
964         if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){
965             log_err("FAIL: udata_open() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status));
966         }else{
967             log_verbose("PASS: udata_open with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status));
968         }
969     }else{
970         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);
971         udata_close(result);
972     }
973 
974 
975     /*Try udata_openChoice with status != U_ZERO_ERROR*/
976     log_verbose("Testing udata_openChoice() with status != U_ZERO_ERROR\n");
977     status=U_ILLEGAL_ARGUMENT_ERROR;
978     result=udata_openChoice(testPath, type, name, isAcceptable3, NULL, &status);
979     if(result != NULL){
980         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);
981         udata_close(result);
982     } else {
983         log_verbose("PASS: udata_openChoice() with errorCode != U_ZERO_ERROR failed as expected\n");
984     }
985 
986     /*Try udata_open with data name=NULL*/
987     log_verbose("Testing udata_openChoice() with data name=NULL\n");
988     status=U_ZERO_ERROR;
989     result=udata_openChoice(testPath, type, NULL, isAcceptable3, NULL, &status);
990     if(U_FAILURE(status)){
991         if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){
992             log_err("FAIL: udata_openChoice() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status));
993         }else{
994             log_verbose("PASS: udata_openChoice with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status));
995         }
996     }else{
997         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);
998         udata_close(result);
999     }
1000 
1001     /*Try udata_getMemory with UDataMemory=NULL*/
1002     log_verbose("Testing udata_getMemory with UDataMemory=NULL\n");
1003     intValue=(uint16_t*)udata_getMemory(NULL);
1004     if(intValue != NULL){
1005         log_err("FAIL: udata_getMemory with UDataMemory = NULL is supposed to fail\n");
1006     }
1007 
1008     /*Try udata_getInfo with UDataMemory=NULL*/
1009     status=U_ZERO_ERROR;
1010     udata_getInfo(NULL, &dataInfo);
1011     if(dataInfo.size != 0){
1012         log_err("FAIL : udata_getInfo with UDataMemory = NULL us supposed to fail\n");
1013     }
1014 
1015     /*Try udata_openChoice with a non existing binary file*/
1016     log_verbose("Testing udata_openChoice() with a non existing binary file\n");
1017     result=udata_openChoice(testPath, "tst", "nonexist", isAcceptable3, NULL, &status);
1018     if(status==U_FILE_ACCESS_ERROR){
1019         log_verbose("Opening udata_openChoice with non-existing file handled correctly.\n");
1020         status=U_ZERO_ERROR;
1021     } else {
1022         log_err("calling udata_open with non-existing file not handled correctly\n.  Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status));
1023         if(U_SUCCESS(status)) {
1024             udata_close(result);
1025         }
1026     }
1027 
1028     if(result != NULL){
1029         log_err("calling udata_open with non-existing file didn't return a null value\n");
1030     } else {
1031         log_verbose("calling udat_open with non-existing file returned null as expected\n");
1032     }
1033 }
1034 
1035 /* Test whether apps and ICU can each have their own root.res */
TestAppData()1036 static void TestAppData()
1037 {
1038     UResourceBundle *icu, *app;
1039     UResourceBundle *tmp = NULL;
1040     UResourceBundle *tmp2 = NULL;
1041 
1042     const UChar *appString;
1043     const UChar *icuString;
1044 
1045     int32_t len;
1046 
1047     UErrorCode status = U_ZERO_ERROR;
1048     char testMsgBuf[256];
1049 
1050     const char* testPath=loadTestData(&status);
1051     if(U_FAILURE(status)) {
1052         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
1053         return;
1054     }
1055 
1056     icu = ures_open(NULL, "root", &status);
1057     if(U_FAILURE(status))
1058     {
1059         log_data_err("%s:%d: Couldn't open root ICU bundle- %s", __FILE__, __LINE__, u_errorName(status));
1060         return;
1061     }
1062     /*  log_info("Open icu root: %s size_%d\n", u_errorName(status), ures_getSize(icu)); */
1063     status = U_ZERO_ERROR;
1064 
1065     app = ures_open(testPath, "root", &status);
1066     if(U_FAILURE(status))
1067     {
1068         log_data_err("%s:%d: Couldn't open app ICU bundle [%s]- %s", __FILE__, __LINE__, testPath, u_errorName(status));
1069         return;
1070     }
1071     /* log_info("Open  app: %s, size %d\n", u_errorName(status), ures_getSize(app)); */
1072 
1073     tmp = ures_getByKey(icu, "Version", tmp, &status);
1074     if(U_FAILURE(status))
1075     {
1076         log_err("%s:%d: Couldn't get Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1077         return;
1078     }
1079 
1080     icuString =  ures_getString(tmp,  &len, &status);
1081     if(U_FAILURE(status))
1082     {
1083         log_err("%s:%d: Couldn't get string from Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1084         return;
1085     }
1086     /* log_info("icuString=%p - %s\n", icuString, austrdup(icuString)); */
1087 
1088 
1089     tmp2 = ures_getByKey(app, "Version", tmp2, &status);
1090     if(U_FAILURE(status))
1091     {
1092         log_err("%s:%d: Couldn't get Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1093         return;
1094     }
1095 
1096     appString =  ures_getString(tmp2,  &len, &status);
1097     if(U_FAILURE(status))
1098     {
1099         log_err("%s:%d: Couldn't get string from Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status));
1100         return;
1101     }
1102 
1103     /* log_info("appString=%p - %s\n", appString, austrdup(appString)); */
1104 
1105 
1106     if(!u_strcmp(icuString, appString))
1107     {
1108         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),
1109             austrdup(appString));
1110     }
1111     else
1112     {
1113         log_verbose("%s:%d:  appstr=%s, icustr=%s\n", __FILE__,
1114             __LINE__, u_austrcpy(testMsgBuf, appString), u_austrcpy(testMsgBuf, icuString));
1115     }
1116 
1117     ures_close(tmp);
1118     ures_close(tmp2);
1119     ures_close(icu);
1120     ures_close(app);
1121 }
1122 #endif
1123 
TestICUDataName()1124 static void TestICUDataName()
1125 {
1126     UVersionInfo icuVersion;
1127     char expectDataName[20];
1128     unsigned int expectLen = 8;
1129 
1130     char typeChar  = '?';
1131 
1132     /* Print out the version # we have .. */
1133     log_verbose("utypes.h says U_ICUDATA_NAME = %s\n", U_ICUDATA_NAME);
1134 
1135     /* Build up the version # we expect to get */
1136     u_getVersion(icuVersion);
1137 
1138     switch(U_CHARSET_FAMILY)
1139     {
1140     case U_ASCII_FAMILY:
1141           switch((int)U_IS_BIG_ENDIAN)
1142           {
1143           case 1:
1144                 typeChar = 'b';
1145                 break;
1146           case 0:
1147                 typeChar = 'l';
1148                 break;
1149           default:
1150                 log_err("Expected 1 or 0 for U_IS_BIG_ENDIAN, got %d!\n", (int)U_IS_BIG_ENDIAN);
1151                 /* return; */
1152           }
1153           break;
1154     case U_EBCDIC_FAMILY:
1155         typeChar = 'e';
1156         break;
1157     }
1158 
1159     /* Only major number is needed. */
1160     sprintf(expectDataName, "%s%d%c",
1161                 "icudt",
1162                 (int)icuVersion[0],
1163                 typeChar);
1164 
1165     log_verbose("Expected: %s\n", expectDataName);
1166     if(uprv_strlen(expectDataName) != expectLen)
1167     {
1168         log_err("*Expected* length is wrong (test err?), should be %d is %d\n",
1169             expectLen, uprv_strlen(expectDataName));
1170     }
1171 
1172     if(uprv_strlen(U_ICUDATA_NAME) != expectLen)
1173     {
1174         log_err("U_ICUDATA_NAME length should be %d is %d\n",
1175             expectLen, uprv_strlen(U_ICUDATA_NAME));
1176     }
1177 
1178     if(uprv_strcmp(U_ICUDATA_NAME, expectDataName))
1179     {
1180         log_err("U_ICUDATA_NAME should be %s but is %s\n",
1181                 expectDataName, U_ICUDATA_NAME);
1182     }
1183 
1184         /* ICUDATA_NAME comes from the build system on *nix */
1185 #ifdef ICUDATA_NAME
1186     if(uprv_strcmp(U_ICUDATA_NAME, ICUDATA_NAME))
1187     {
1188         log_err("ICUDATA_NAME  and U_ICUDATA_NAME don't match: "
1189             "ICUDATA_NAME=%s, U_ICUDATA_NAME=%s.  Check configure.in, icudefs.mk.in, utypes.h...\n",  ICUDATA_NAME, U_ICUDATA_NAME);
1190     }
1191     else
1192     {
1193         log_verbose("ICUDATA_NAME=%s (from icudefs.mk), U_ICUDATA_NAME=%s (from utypes.h)\n", ICUDATA_NAME, U_ICUDATA_NAME);
1194     }
1195 #endif
1196 
1197 }
1198 
1199 /* test data swapping ------------------------------------------------------- */
1200 
1201 #if U_PLATFORM == U_PF_OS400
1202 /* See comments in genccode.c on when this special implementation can be removed. */
1203 static const struct {
1204     double bogus;
1205     const char *bytes;
1206 } gOffsetTOCAppDataItem1={ 0.0, /* alignment bytes */
1207     "\x00\x14" /* sizeof(UDataInfo) *//* MappedData { */
1208     "\xda"
1209     "\x27"                            /* } */
1210     "\x00\x14" /* sizeof(UDataInfo) *//* UDataInfo  { */
1211     "\0\0"
1212     "\1"       /* U_IS_BIG_ENDIAN   */
1213     "\1"       /* U_CHARSET_FAMILY  */
1214     "\2"       /* U_SIZEOF_WHAR_T   */
1215     "\0"
1216     "\x31\x31\x31\x31"
1217     "\0\0\0\0"
1218     "\0\0\0\0"                        /* } */
1219 };
1220 #else
1221 static const struct {
1222     double bogus;
1223     MappedData bytes1;
1224     UDataInfo bytes2;
1225     uint8_t bytes3;
1226 } gOffsetTOCAppDataItem1={
1227     0.0,                            /* alignment bytes */
1228     { sizeof(UDataInfo), 0xda, 0x27 },  /* MappedData */
1229 
1230     {sizeof(UDataInfo),
1231     0,
1232 
1233     U_IS_BIG_ENDIAN,
1234     U_CHARSET_FAMILY,
1235     sizeof(UChar),
1236     0,
1237 
1238     {0x31, 0x31, 0x31, 0x31},     /* dataFormat="1111" */
1239     {0, 0, 0, 0},                 /* formatVersion */
1240     {0, 0, 0, 0}},                /* dataVersion */
1241     0
1242 };
1243 #endif
1244 
1245 static const UChar gOffsetTOCGarbage[] = { /* "I have been very naughty!" */
1246     0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E,
1247     0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6E, 0x61, 0x75, 0x67, 0x68, 0x74, 0x79, 0x21
1248 };
1249 
1250 /* Original source: icu/source/tools/genccode */
1251 static const struct {
1252     uint16_t headerSize;
1253     uint8_t magic1, magic2;
1254     UDataInfo info;
1255     char padding[8];
1256     uint32_t count, reserved;
1257     const struct {
1258         const char *const name;
1259         const void *const data;
1260     } toc[3];
1261 } gOffsetTOCAppData_dat = {
1262     32,          /* headerSize */
1263     0xda,        /* magic1,  (see struct MappedData in udata.c)  */
1264     0x27,        /* magic2     */
1265     {            /*UDataInfo   */
1266         sizeof(UDataInfo),      /* size        */
1267         0,                      /* reserved    */
1268         U_IS_BIG_ENDIAN,
1269         U_CHARSET_FAMILY,
1270         sizeof(UChar),
1271         0,               /* reserved      */
1272         {                /* data format identifier */
1273            0x54, 0x6f, 0x43, 0x50}, /* "ToCP" */
1274            {1, 0, 0, 0},   /* format version major, minor, milli, micro */
1275            {0, 0, 0, 0}    /* dataVersion   */
1276     },
1277     {0,0,0,0,0,0,0,0},  /* Padding[8]   */
1278     3,                  /* count        */
1279     0,                  /* Reserved     */
1280     {                   /*  TOC structure */
1281         { "OffsetTOCAppData/a/b", &gOffsetTOCAppDataItem1 },
1282         { "OffsetTOCAppData/gOffsetTOCAppDataItem1", &gOffsetTOCAppDataItem1 },
1283         { "OffsetTOCAppData/gOffsetTOCGarbage", &gOffsetTOCGarbage }
1284     }
1285 };
1286 
1287 /* Unfortunately, dictionaries are in a C++ header */
1288 U_CAPI int32_t U_EXPORT2
1289 udict_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData, UErrorCode *pErrorCode);
1290 
1291 /* test cases for maximum data swapping code coverage */
1292 static const struct {
1293     const char *name, *type;
1294     UDataSwapFn *swapFn;
1295 } swapCases[]={
1296     /* resource bundles */
1297 
1298     /* resource bundle with many data types */
1299     {"*testtypes",               "res", ures_swap},
1300     /* resource bundle with collation data */
1301     {"ja",                       "res", ures_swap},
1302     /* resource bundle with options-only collation data */
1303     {"ru",                       "res", ures_swap},
1304     {"el",                       "res", ures_swap},
1305     /* ICU's root */
1306     {"root",                     "res", ures_swap},
1307     /* Test a 32-bit key table. This is large. */
1308     {"*testtable32",             "res", ures_swap},
1309 
1310     /* ICU 4.2 resource bundle - data format 1.2 (little-endian ASCII) */
1311     {"*old_l_testtypes",         "res", ures_swap},
1312     /* same for big-endian EBCDIC */
1313     {"*old_e_testtypes",         "res", ures_swap},
1314 
1315 #if !UCONFIG_NO_COLLATION
1316     /* standalone collation data files */
1317     {"ucadata",                  "icu", ucol_swap},
1318 #if 0
1319     /* Starting with ICU 53, the "inverse UCA" data is integrated into ucadata.icu. */
1320     {"invuca",                   "icu", ucol_swapInverseUCA},
1321 #endif
1322 #endif
1323 
1324 #if !UCONFIG_NO_LEGACY_CONVERSION
1325     /* conversion table files */
1326 
1327     /* SBCS conversion table file without extension */
1328     {"ibm-913_P100-2000",   "cnv", ucnv_swap},
1329     /* EBCDIC_STATEFUL conversion table file with extension */
1330     {"ibm-1390_P110-2003",       "cnv", ucnv_swap},
1331     /* DBCS extension-only conversion table file */
1332     {"ibm-16684_P110-2003",      "cnv", ucnv_swap},
1333     /* EUC-TW (3-byte) conversion table file without extension */
1334     {"ibm-964_P110-1999",        "cnv", ucnv_swap},
1335     /* GB 18030 (4-byte) conversion table file without extension */
1336     {"gb18030",                  "cnv", ucnv_swap},
1337     /* MBCS conversion table file with extension */
1338     {"*test4x",                  "cnv", ucnv_swap},
1339     /*
1340      * MBCS conversion table file without extension,
1341      * to test swapping and preflighting of UTF-8-friendly mbcsIndex[].
1342      */
1343     {"jisx-212",                 "cnv", ucnv_swap},
1344 #endif
1345 
1346 #if !UCONFIG_NO_CONVERSION
1347     /* alias table */
1348     {"cnvalias",                 "icu", ucnv_swapAliases},
1349 #endif
1350 
1351 #if !UCONFIG_NO_IDNA
1352     {"rfc3491",                    "spp", usprep_swap},
1353 #endif
1354 
1355 #if !UCONFIG_NO_BREAK_ITERATION
1356     {"char",                     "brk", ubrk_swap},
1357     {"laodict",                  "dict",udict_swap},
1358 #endif
1359 
1360 #if 0
1361     /*
1362      * Starting with ICU 4.8, the Unicode property (value) aliases data
1363      * is hardcoded in the ICU4C common library.
1364      * The swapper was moved to the toolutil library for swapping for ICU4J.
1365      */
1366     /* Unicode properties */
1367     {"pnames",                   "icu", upname_swap},
1368 #endif
1369 
1370 #if 0
1371     /*
1372      * Starting with ICU4C 3.4, the core Unicode properties files
1373      * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu)
1374      * are hardcoded in the common DLL and therefore not included
1375      * in the data package any more.
1376      * Their swapping code is moved from the common DLL to the icuswap tool so that
1377      * we need not jump through hoops (like adding snapshots of these files
1378      * to testdata) for code coverage in tests.
1379      * See Jitterbug 4497.
1380      *
1381      * ICU4C 4.4 adds normalization data files again, e.g., nfkc.nrm.
1382      */
1383     {"uprops",                   "icu", uprops_swap},
1384     {"ucase",                    "icu", ucase_swap},
1385     {"ubidi",                    "icu", ubidi_swap},
1386 #endif
1387 #if !UCONFIG_NO_NORMALIZATION && !UCONFIG_ONLY_COLLATION
1388     {"nfkc",                     "nrm", unorm2_swap},
1389 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
1390     {"confusables",              "cfu", uspoof_swap}, /* spoof data missing without regex */
1391 #endif
1392 
1393 #endif
1394     {"unames",                   "icu", uchar_swapNames}
1395     /* the last item should not be #if'ed so that it can reliably omit the last comma */
1396 };
1397 
1398 /* Large enough for the largest swappable data item. */
1399 #define SWAP_BUFFER_SIZE 1800000
1400 
1401 static void U_CALLCONV
printError(void * context,const char * fmt,va_list args)1402 printError(void *context, const char *fmt, va_list args) {
1403     (void)context; // suppress compiler warnings about unused variable
1404     vlog_info("[swap] ", fmt, args);
1405     log_err("\n");  /* Register error */
1406 }
1407 
1408 static void
TestSwapCase(UDataMemory * pData,const char * name,UDataSwapFn * swapFn,uint8_t * buffer,uint8_t * buffer2)1409 TestSwapCase(UDataMemory *pData, const char *name,
1410              UDataSwapFn *swapFn,
1411              uint8_t *buffer, uint8_t *buffer2) {
1412     UDataSwapper *ds;
1413     const void *inData, *inHeader;
1414     int32_t length, dataLength, length2, headerLength;
1415 
1416     UErrorCode errorCode;
1417     UErrorCode badStatus;
1418 
1419     UBool inEndian, oppositeEndian;
1420     uint8_t inCharset, oppositeCharset;
1421 
1422     /* First we check that swapFn handles failures as expected. */
1423     errorCode = U_UNSUPPORTED_ERROR;
1424     length = swapFn(NULL, NULL, 0, buffer, &errorCode);
1425     if (length != 0 || errorCode != U_UNSUPPORTED_ERROR) {
1426         log_err("%s() did not fail as expected - %s\n", name, u_errorName(errorCode));
1427     }
1428     errorCode = U_ZERO_ERROR;
1429     length = swapFn(NULL, NULL, 0, buffer, &errorCode);
1430     if (length != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1431         log_err("%s() did not fail as expected with bad arguments - %s\n", name, u_errorName(errorCode));
1432     }
1433 
1434 
1435     /* Continue with the rest of the tests. */
1436     errorCode = U_ZERO_ERROR;
1437     inData=udata_getMemory(pData);
1438 
1439     /*
1440      * get the data length if possible, to verify that swapping and preflighting
1441      * handles the entire data
1442      */
1443     dataLength=udata_getLength(pData);
1444 
1445     /*
1446      * get the header and its length
1447      * all of the swap implementation functions require the header to be included
1448      */
1449     inHeader=udata_getRawMemory(pData);
1450     headerLength=(int32_t)((const char *)inData-(const char *)inHeader);
1451 
1452     /* first swap to opposite endianness but same charset family */
1453     errorCode=U_ZERO_ERROR;
1454     ds=udata_openSwapperForInputData(inHeader, headerLength,
1455             !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
1456     if(U_FAILURE(errorCode)) {
1457         log_err("udata_openSwapperForInputData(%s->!isBig+same charset) failed - %s\n",
1458                 name, u_errorName(errorCode));
1459         return;
1460     }
1461 
1462     inEndian=ds->inIsBigEndian;
1463     inCharset=ds->inCharset;
1464 
1465     oppositeEndian=!inEndian;
1466     oppositeCharset= inCharset==U_ASCII_FAMILY ? U_EBCDIC_FAMILY : U_ASCII_FAMILY;
1467 
1468     /* make this test work with data files that are built for a different platform */
1469     if(inEndian!=U_IS_BIG_ENDIAN || inCharset!=U_CHARSET_FAMILY) {
1470         udata_closeSwapper(ds);
1471         ds=udata_openSwapper(inEndian, inCharset, oppositeEndian, inCharset, &errorCode);
1472         if(U_FAILURE(errorCode)) {
1473             log_err("udata_openSwapper(%s->!isBig+same charset) failed - %s\n",
1474                     name, u_errorName(errorCode));
1475             return;
1476         }
1477     }
1478 
1479     /*
1480     Check error checking of swappable data not specific to this swapper.
1481     This should always fail.
1482     */
1483     badStatus = U_ZERO_ERROR;
1484     length=swapFn(ds, &gOffsetTOCAppData_dat, -1, NULL, &badStatus);
1485     if(badStatus != U_UNSUPPORTED_ERROR) {
1486         log_err("swapFn(%s->!isBig+same charset) unexpectedly succeeded on bad data - %s\n",
1487                 name, u_errorName(errorCode));
1488         udata_closeSwapper(ds);
1489         return;
1490     }
1491 
1492     /* Now allow errors to be printed */
1493     ds->printError=printError;
1494 
1495     /* preflight the length */
1496     length=swapFn(ds, inHeader, -1, NULL, &errorCode);
1497     if(U_FAILURE(errorCode)) {
1498         log_err("swapFn(preflight %s->!isBig+same charset) failed - %s\n",
1499                 name, u_errorName(errorCode));
1500         udata_closeSwapper(ds);
1501         return;
1502     }
1503 
1504     /* compare the preflighted length against the data length */
1505     if(dataLength>=0 && (length+15)<(headerLength+dataLength)) {
1506         log_err("swapFn(preflight %s->!isBig+same charset) length too small: %d < data length %d\n",
1507                 name, length, (headerLength+dataLength));
1508         udata_closeSwapper(ds);
1509         return;
1510     }
1511 
1512     /* swap, not in-place */
1513     length2=swapFn(ds, inHeader, length, buffer, &errorCode);
1514     udata_closeSwapper(ds);
1515     if(U_FAILURE(errorCode)) {
1516         log_err("swapFn(%s->!isBig+same charset) failed - %s\n",
1517                 name, u_errorName(errorCode));
1518         return;
1519     }
1520 
1521     /* compare the swap length against the preflighted length */
1522     if(length2!=length) {
1523         log_err("swapFn(%s->!isBig+same charset) length differs from preflighting: %d != preflighted %d\n",
1524                 name, length2, length);
1525         return;
1526     }
1527 
1528     /* next swap to opposite charset family */
1529     ds=udata_openSwapper(oppositeEndian, inCharset,
1530                          oppositeEndian, oppositeCharset,
1531                          &errorCode);
1532     if(U_FAILURE(errorCode)) {
1533         log_err("udata_openSwapper(%s->!isBig+other charset) failed - %s\n",
1534                 name, u_errorName(errorCode));
1535         return;
1536     }
1537     ds->printError=printError;
1538 
1539     /* swap in-place */
1540     length2=swapFn(ds, buffer, length, buffer, &errorCode);
1541     udata_closeSwapper(ds);
1542     if(U_FAILURE(errorCode)) {
1543         log_err("swapFn(%s->!isBig+other charset) failed - %s\n",
1544                 name, u_errorName(errorCode));
1545         return;
1546     }
1547 
1548     /* compare the swap length against the original length */
1549     if(length2!=length) {
1550         log_err("swapFn(%s->!isBig+other charset) length differs from original: %d != original %d\n",
1551                 name, length2, length);
1552         return;
1553     }
1554 
1555     /* finally swap to original platform values */
1556     ds=udata_openSwapper(oppositeEndian, oppositeCharset,
1557                          inEndian, inCharset,
1558                          &errorCode);
1559     if(U_FAILURE(errorCode)) {
1560         log_err("udata_openSwapper(%s->back to original) failed - %s\n",
1561                 name, u_errorName(errorCode));
1562         return;
1563     }
1564     ds->printError=printError;
1565 
1566     /* swap, not in-place */
1567     length2=swapFn(ds, buffer, length, buffer2, &errorCode);
1568     udata_closeSwapper(ds);
1569     if(U_FAILURE(errorCode)) {
1570         log_err("swapFn(%s->back to original) failed - %s\n",
1571                 name, u_errorName(errorCode));
1572         return;
1573     }
1574 
1575     /* compare the swap length against the original length */
1576     if(length2!=length) {
1577         log_err("swapFn(%s->back to original) length differs from original: %d != original %d\n",
1578                 name, length2, length);
1579         return;
1580     }
1581 
1582     /* compare the final contents with the original */
1583     if(0!=uprv_memcmp(inHeader, buffer2, length)) {
1584         const uint8_t *original;
1585         uint8_t diff[8];
1586         int32_t i, j;
1587 
1588         log_err("swapFn(%s->back to original) contents differs from original\n",
1589                 name);
1590 
1591         /* find the first difference */
1592         original=(const uint8_t *)inHeader;
1593         for(i=0; i<length && original[i]==buffer2[i]; ++i) {}
1594 
1595         /* find the next byte that is the same */
1596         for(j=i+1; j<length && original[j]!=buffer2[j]; ++j) {}
1597         log_info("    difference at index %d=0x%x, until index %d=0x%x\n", i, i, j, j);
1598 
1599         /* round down to the last 4-boundary for better result output */
1600         i&=~3;
1601         log_info("showing bytes from index %d=0x%x (length %d=0x%x):\n", i, i, length, length);
1602 
1603         /* print 8 bytes but limit to the buffer contents */
1604         length2=i+sizeof(diff);
1605         if(length2>length) {
1606             length2=length;
1607         }
1608 
1609         /* print the original bytes */
1610         uprv_memset(diff, 0, sizeof(diff));
1611         for(j=i; j<length2; ++j) {
1612             diff[j-i]=original[j];
1613         }
1614         log_info("    original: %02x %02x %02x %02x %02x %02x %02x %02x\n",
1615             diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
1616 
1617         /* print the swapped bytes */
1618         uprv_memset(diff, 0, sizeof(diff));
1619         for(j=i; j<length2; ++j) {
1620             diff[j-i]=buffer2[j];
1621         }
1622         log_info("    swapped:  %02x %02x %02x %02x %02x %02x %02x %02x\n",
1623             diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
1624     }
1625 }
1626 
1627 static void U_CALLCONV
printErrorToString(void * context,const char * fmt,va_list args)1628 printErrorToString(void *context, const char *fmt, va_list args) {
1629     vsprintf((char *)context, fmt, args);
1630 }
1631 
1632 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
1633 static void
TestSwapData()1634 TestSwapData() {
1635     char name[100];
1636     UDataSwapper *ds;
1637     UDataMemory *pData;
1638     uint8_t *buffer;
1639     const char *pkg, *nm, *testPath;
1640     UErrorCode errorCode = U_ZERO_ERROR;
1641     int32_t i;
1642 
1643     buffer=(uint8_t *)malloc(2*SWAP_BUFFER_SIZE);
1644     if(buffer==NULL) {
1645         log_err("unable to allocate %d bytes\n", 2*SWAP_BUFFER_SIZE);
1646         return;
1647     }
1648 
1649     testPath=loadTestData(&errorCode);
1650     if(U_FAILURE(errorCode)) {
1651         log_data_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode));
1652     }
1653 
1654     /* Test that printError works as expected. */
1655     errorCode=U_USELESS_COLLATOR_ERROR;
1656     ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1657                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1658                          &errorCode);
1659     if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) {
1660         log_err("udata_openSwapper should have returned NULL with bad argument\n", name);
1661     }
1662     errorCode=U_ZERO_ERROR;
1663     ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1664                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1665                          &errorCode);
1666     ds->printError=printErrorToString;
1667     ds->printErrorContext=name;
1668     udata_printError(ds, "This %s a %s", "is", "test");
1669     udata_closeSwapper(ds);
1670     if (strcmp(name, "This is a test") != 0) {
1671         log_err("udata_printError can't properly print error messages. Got = %s\n", name);
1672     }
1673     errorCode = U_USELESS_COLLATOR_ERROR;
1674     ds=udata_openSwapperForInputData(NULL, 0,
1675                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1676                          &errorCode);
1677     if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) {
1678         log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
1679     }
1680     errorCode=U_ZERO_ERROR;
1681     ds=udata_openSwapperForInputData(NULL, 0,
1682                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1683                          &errorCode);
1684     if (ds != NULL || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1685         log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
1686     }
1687     errorCode=U_ZERO_ERROR;
1688     memset(buffer, 0, sizeof(2*SWAP_BUFFER_SIZE));
1689     ds=udata_openSwapperForInputData(buffer, 2*SWAP_BUFFER_SIZE,
1690                          !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
1691                          &errorCode);
1692     if (ds != NULL || errorCode != U_UNSUPPORTED_ERROR) {
1693         log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
1694     }
1695     errorCode=U_ZERO_ERROR;
1696 
1697     /* Test argument checking. ucol_swap is normally tested via ures_swap, and isn't normally called directly. */
1698 #if !UCONFIG_NO_COLLATION
1699     ucol_swap(NULL, NULL, -1, NULL, &errorCode);
1700     if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
1701         log_err("ucol_swap did not fail as expected\n", name);
1702     }
1703     errorCode=U_ZERO_ERROR;
1704 #endif
1705 
1706     for(i=0; i<UPRV_LENGTHOF(swapCases); ++i) {
1707         /* build the name for logging */
1708         errorCode=U_ZERO_ERROR;
1709         if(swapCases[i].name[0]=='*') {
1710             pkg=testPath;
1711             nm=swapCases[i].name+1;
1712             uprv_strcpy(name, "testdata");
1713         } else if (uprv_strcmp(swapCases[i].type, "brk")==0
1714             || uprv_strcmp(swapCases[i].type, "dict")==0) {
1715             pkg=U_ICUDATA_BRKITR;
1716             nm=swapCases[i].name;
1717             uprv_strcpy(name, U_ICUDATA_BRKITR);
1718 #if !UCONFIG_NO_COLLATION
1719         } else if (uprv_strcmp(swapCases[i].name, "ucadata")==0
1720             || uprv_strcmp(swapCases[i].name, "invuca")==0) {
1721             pkg=U_ICUDATA_COLL;
1722             nm=swapCases[i].name;
1723             uprv_strcpy(name, U_ICUDATA_COLL);
1724 #endif  /* !UCONFIG_NO_COLLATION */
1725         } else {
1726             pkg=NULL;
1727             nm=swapCases[i].name;
1728             uprv_strcpy(name, "NULL");
1729         }
1730         uprv_strcat(name, "/");
1731         uprv_strcat(name, nm);
1732         uprv_strcat(name, ".");
1733         uprv_strcat(name, swapCases[i].type);
1734 
1735         pData=udata_open(pkg, swapCases[i].type, nm, &errorCode);
1736 
1737         if(U_SUCCESS(errorCode)) {
1738             TestSwapCase(pData, name, swapCases[i].swapFn, buffer, buffer+SWAP_BUFFER_SIZE);
1739             udata_close(pData);
1740         } else {
1741             log_data_err("udata_open(%s) failed - %s\n",
1742                 name, u_errorName(errorCode));
1743         }
1744     }
1745 
1746     free(buffer);
1747 }
1748 #endif
1749 
PointerTableOfContents()1750 static void PointerTableOfContents() {
1751     UDataMemory      *dataItem;
1752     UErrorCode        status=U_ZERO_ERROR;
1753 
1754     /*
1755      * Got testdata.dat into memory, now we try setAppData using the memory image.
1756      */
1757 
1758     status=U_ZERO_ERROR;
1759     udata_setAppData("OffsetTOCAppData", &gOffsetTOCAppData_dat, &status);
1760     if (status != U_ZERO_ERROR) {
1761         log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) \n"
1762                 " returned status of %s\n", u_errorName(status));
1763         return;
1764     }
1765 
1766     dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCAppDataItem1", &status);
1767     if (U_FAILURE(status)) {
1768         log_err("FAIL: gOffsetTOCAppDataItem1 could not be opened. status = %s\n", u_errorName(status));
1769     }
1770     if (udata_getMemory(dataItem) != NULL) {
1771         log_verbose("FAIL: udata_getMemory(dataItem) passed\n");
1772     }
1773     else {
1774         log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status));
1775     }
1776     udata_close(dataItem);
1777 
1778     dataItem = udata_open("OffsetTOCAppData-a", "", "b", &status);
1779     if (U_FAILURE(status)) {
1780         log_err("FAIL: gOffsetTOCAppDataItem1 in tree \"a\" could not be opened. status = %s\n", u_errorName(status));
1781     }
1782     if (udata_getMemory(dataItem) != NULL) {
1783         log_verbose("FAIL: udata_getMemory(dataItem) in tree \"a\" passed\n");
1784     }
1785     else {
1786         log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status));
1787     }
1788     udata_close(dataItem);
1789 
1790     dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCGarbage", &status);
1791     if (U_SUCCESS(status)) {
1792         log_err("FAIL: gOffsetTOCGarbage should not be opened. status = %s\n", u_errorName(status));
1793     }
1794     dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCNonExistent", &status);
1795     if (U_SUCCESS(status)) {
1796         log_err("FAIL: gOffsetTOCNonExistent should not be found. status = %s\n", u_errorName(status));
1797     }
1798 
1799 }
1800 
SetBadCommonData(void)1801 static void SetBadCommonData(void) {
1802     /* It's difficult to test that udata_setCommonData really works within the test framework.
1803        So we just test that foolish people can't do bad things. */
1804     UErrorCode status;
1805     char badBuffer[sizeof(gOffsetTOCAppData_dat)];
1806 
1807     memset(badBuffer, 0, sizeof(badBuffer));
1808     strcpy(badBuffer, "Hello! I'm not good data.");
1809 
1810     /* Check that we don't do anything */
1811     status = U_FILE_ACCESS_ERROR;
1812     udata_setCommonData(&gOffsetTOCAppData_dat, &status);
1813     if (status != U_FILE_ACCESS_ERROR) {
1814         log_err("FAIL: udata_setCommonData changed the failure code.\n");
1815     }
1816     /* Check that we fail correctly */
1817     status = U_ZERO_ERROR;
1818     udata_setCommonData(NULL, &status);
1819     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
1820         log_err("FAIL: udata_setCommonData did not fail with bad arguments.\n");
1821     }
1822 
1823     /* Check that we verify that the data isn't bad */
1824     status = U_ZERO_ERROR;
1825     udata_setAppData("invalid path", badBuffer, &status);
1826     if (status != U_INVALID_FORMAT_ERROR) {
1827         log_err("FAIL: udata_setAppData doesn't verify data validity.\n");
1828     }
1829 }
1830 
1831 // Check the override loading of time zone .res files from a specified path
1832 //
1833 // Hand testing notes:
1834 //   1. Run this test with the environment variable set. The following should induce faiures:
1835 //        ICU_TIMEZONE_FILES_DIR=../testdata/out/build LD_LIBRARY_PATH=../../lib:../../stubdata:../../tools/ctestfw:$LD_LIBRARY_PATH  ./cintltst /udatatst/TestTZDataDir
1836 //   2. Build ICU with with U_TIMEZONE_FILES_DIR defined. This should also induce failures.
1837 //        CPPFLAGS=-DU_TIMEZONE_FILES_DIR\=`pwd`/test/testdata/out/testdata ./runConfigureICU Linux
1838 //        make check
1839 
TestTZDataDir(void)1840 static void TestTZDataDir(void) {
1841 #if !UCONFIG_NO_FORMATTING
1842     UErrorCode status = U_ZERO_ERROR;
1843     const char *tzDataVersion;
1844     const char *testDataPath;
1845 
1846     // Verify that default ICU time zone data version is something newer than 2014a.
1847     tzDataVersion = ucal_getTZDataVersion(&status);
1848     // printf("tz data version is %s\n", tzDataVersion);
1849     if (U_FAILURE(status)) {
1850         log_data_err("Failed call to ucal_getTZDataVersion - %s\n", u_errorName(status));
1851         return;
1852     } else if (strcmp("2014a", tzDataVersion) == 0) {
1853         log_err("File %s:%d - expected something newer than time zone data 2014a.\n", __FILE__, __LINE__, tzDataVersion);
1854     }
1855 
1856     testDataPath = loadTestData(&status);
1857     // The path produced by loadTestData() will look something like
1858     //     whatever/.../testdata/out/testdata
1859     // The test data puts an old (2014a) version of the time zone data there.
1860 
1861     // Switch ICU to the testdata version of zoneinfo64.res, which is version 2014a.
1862     ctest_resetICU();
1863     u_setTimeZoneFilesDirectory(testDataPath, &status);
1864     tzDataVersion = ucal_getTZDataVersion(&status);
1865     if (strcmp("2014a", tzDataVersion) != 0) {
1866         log_err("File %s:%d - expected \"2014a\"; actual \"%s\"\n", __FILE__, __LINE__, tzDataVersion);
1867     }
1868 
1869     ctest_resetICU();   // Return ICU to using its standard tz data.
1870     tzDataVersion = ucal_getTZDataVersion(&status);
1871     // printf("tz data version is %s\n", tzDataVersion);
1872     if (strcmp("2014a", tzDataVersion) == 0) {
1873         log_err("File %s:%d - expected something newer than time zone data 2014a.\n", __FILE__, __LINE__, tzDataVersion);
1874     }
1875 #endif
1876 }
1877