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