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