• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * Copyright (c) 1997-2016, International Business Machines
5  * Corporation and others. All Rights Reserved.
6  ********************************************************************/
7 
8 #include "unicode/utypes.h"
9 
10 #include "charstr.h"
11 #include "cmemory.h"
12 #include "cstring.h"
13 #include "unicode/unistr.h"
14 #include "unicode/resbund.h"
15 #include "unicode/brkiter.h"
16 #include "unicode/utrace.h"
17 #include "unicode/ucurr.h"
18 #include "uresimp.h"
19 #include "restsnew.h"
20 
21 #include <stdlib.h>
22 #include <time.h>
23 #include <string.h>
24 #include <limits.h>
25 #include <vector>
26 #include <string>
27 
28 //***************************************************************************************
29 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)30 void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
31 {
32     if (exec) logln("TestSuite ResourceBundleTest: ");
33     TESTCASE_AUTO_BEGIN;
34 
35 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
36     TESTCASE_AUTO(TestResourceBundles);
37     TESTCASE_AUTO(TestConstruction);
38     TESTCASE_AUTO(TestIteration);
39     TESTCASE_AUTO(TestOtherAPI);
40     TESTCASE_AUTO(TestNewTypes);
41 #endif
42 
43     TESTCASE_AUTO(TestGetByFallback);
44     TESTCASE_AUTO(TestFilter);
45     TESTCASE_AUTO(TestIntervalAliasFallbacks);
46 
47 #if U_ENABLE_TRACING
48     TESTCASE_AUTO(TestTrace);
49 #endif
50 
51     TESTCASE_AUTO_END;
52 }
53 
54 //***************************************************************************************
55 
56 static const UChar kErrorUChars[] = { 0x45, 0x52, 0x52, 0x4f, 0x52, 0 };
57 static const int32_t kErrorLength = 5;
58 static const int32_t kERROR_COUNT = -1234567;
59 
60 //***************************************************************************************
61 
62 enum E_Where
63 {
64     e_Root,
65     e_te,
66     e_te_IN,
67     e_Where_count
68 };
69 
70 //***************************************************************************************
71 
72 #define CONFIRM_EQ(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \
73     if ((expected)==(actual)) { \
74         record_pass(); \
75     } else { \
76         record_fail(); \
77         errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of " + (expected)); \
78     } \
79 } UPRV_BLOCK_MACRO_END
80 #define CONFIRM_GE(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \
81     if ((actual)>=(expected)) { \
82         record_pass(); \
83     } else { \
84         record_fail(); \
85         errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x >= " + (expected)); \
86     } \
87 } UPRV_BLOCK_MACRO_END
88 #define CONFIRM_NE(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \
89     if ((expected)!=(actual)) { \
90         record_pass(); \
91     } else { \
92         record_fail(); \
93         errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x != " + (expected)); \
94     } \
95 } UPRV_BLOCK_MACRO_END
96 
97 #define CONFIRM_UErrorCode(actual,expected) UPRV_BLOCK_MACRO_BEGIN { \
98     if ((expected)==(actual)) { \
99         record_pass(); \
100     } else { \
101         record_fail(); \
102         errln(action + (UnicodeString)" returned " + (UnicodeString)u_errorName(actual) + (UnicodeString)" instead of " + (UnicodeString)u_errorName(expected)); \
103     } \
104 } UPRV_BLOCK_MACRO_END
105 
106 //***************************************************************************************
107 
108 /**
109  * Convert an integer, positive or negative, to a character string radix 10.
110  */
111 static char*
itoa(int32_t i,char * buf)112 itoa(int32_t i, char* buf)
113 {
114     char* result = buf;
115 
116     // Handle negative
117     if (i < 0)
118     {
119         *buf++ = '-';
120         i = -i;
121     }
122 
123     // Output digits in reverse order
124     char* p = buf;
125     do
126     {
127         *p++ = (char)('0' + (i % 10));
128         i /= 10;
129     }
130     while (i);
131     *p-- = 0;
132 
133     // Reverse the string
134     while (buf < p)
135     {
136         char c = *buf;
137         *buf++ = *p;
138         *p-- = c;
139     }
140 
141     return result;
142 }
143 
144 
145 
146 //***************************************************************************************
147 
148 // Array of our test objects
149 
150 static struct
151 {
152     const char* name;
153     Locale *locale;
154     UErrorCode expected_constructor_status;
155     E_Where where;
156     UBool like[e_Where_count];
157     UBool inherits[e_Where_count];
158 }
159 param[] =
160 {
161     // "te" means test
162     // "IN" means inherits
163     // "NE" or "ne" means "does not exist"
164 
165     { "root",       0,   U_ZERO_ERROR,             e_Root,      { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } },
166     { "te",         0,   U_ZERO_ERROR,             e_te,        { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE  } },
167     { "te_IN",      0,   U_ZERO_ERROR,             e_te_IN,     { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE   } },
168     { "te_NE",      0,   U_USING_FALLBACK_WARNING, e_te,        { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE  } },
169     { "te_IN_NE",   0,   U_USING_FALLBACK_WARNING, e_te_IN,     { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE   } },
170     { "ne",         0,   U_USING_DEFAULT_WARNING,  e_Root,      { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }
171 };
172 
173 static int32_t bundles_count = UPRV_LENGTHOF(param);
174 
175 //***************************************************************************************
176 
177 /**
178  * Return a random unsigned long l where 0N <= l <= ULONG_MAX.
179  */
180 
181 static uint32_t
randul()182 randul()
183 {
184     static UBool initialized = FALSE;
185     if (!initialized)
186     {
187         srand((unsigned)time(NULL));
188         initialized = TRUE;
189     }
190     // Assume rand has at least 12 bits of precision
191     uint32_t l = 0;
192     for (uint32_t i=0; i<sizeof(l); ++i)
193         ((char*)&l)[i] = (char)((rand() & 0x0FF0) >> 4);
194     return l;
195 }
196 
197 /**
198  * Return a random double x where 0.0 <= x < 1.0.
199  */
200 static double
randd()201 randd()
202 {
203     return (double)(randul() / ULONG_MAX);
204 }
205 
206 /**
207  * Return a random integer i where 0 <= i < n.
208  */
randi(int32_t n)209 static int32_t randi(int32_t n)
210 {
211     return (int32_t)(randd() * n);
212 }
213 
214 //***************************************************************************************
215 
216 /*
217  Don't use more than one of these at a time because of the Locale names
218 */
NewResourceBundleTest()219 NewResourceBundleTest::NewResourceBundleTest()
220 : pass(0),
221   fail(0)
222 {
223     if (param[5].locale == NULL) {
224         param[0].locale = new Locale("root");
225         param[1].locale = new Locale("te");
226         param[2].locale = new Locale("te", "IN");
227         param[3].locale = new Locale("te", "NE");
228         param[4].locale = new Locale("te", "IN", "NE");
229         param[5].locale = new Locale("ne");
230     }
231 }
232 
~NewResourceBundleTest()233 NewResourceBundleTest::~NewResourceBundleTest()
234 {
235     if (param[5].locale) {
236         int idx;
237         for (idx = 0; idx < UPRV_LENGTHOF(param); idx++) {
238             delete param[idx].locale;
239             param[idx].locale = NULL;
240         }
241     }
242 }
243 
244 //***************************************************************************************
245 
246 void
TestResourceBundles()247 NewResourceBundleTest::TestResourceBundles()
248 {
249     UErrorCode status = U_ZERO_ERROR;
250     loadTestData(status);
251     if(U_FAILURE(status))
252     {
253         dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(status)));
254         return;
255     }
256 
257     /* Make sure that users using te_IN for the default locale don't get test failures. */
258     Locale originalDefault;
259     if (Locale::getDefault() == Locale("te_IN")) {
260         Locale::setDefault(Locale("en_US"), status);
261     }
262 
263     testTag("only_in_Root", TRUE, FALSE, FALSE);
264     testTag("only_in_te", FALSE, TRUE, FALSE);
265     testTag("only_in_te_IN", FALSE, FALSE, TRUE);
266     testTag("in_Root_te", TRUE, TRUE, FALSE);
267     testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE);
268     testTag("in_Root_te_IN", TRUE, FALSE, TRUE);
269     testTag("in_te_te_IN", FALSE, TRUE, TRUE);
270     testTag("nonexistent", FALSE, FALSE, FALSE);
271     logln("Passed: %d\nFailed: %d", pass, fail);
272 
273     /* Restore the default locale for the other tests. */
274     Locale::setDefault(originalDefault, status);
275 }
276 
277 void
TestConstruction()278 NewResourceBundleTest::TestConstruction()
279 {
280     UErrorCode   err = U_ZERO_ERROR;
281     Locale       locale("te", "IN");
282 
283     const char* testdatapath;
284     testdatapath=loadTestData(err);
285     if(U_FAILURE(err))
286     {
287         dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err)));
288         return;
289     }
290 
291     /* Make sure that users using te_IN for the default locale don't get test failures. */
292     Locale originalDefault;
293     if (Locale::getDefault() == Locale("te_IN")) {
294         Locale::setDefault(Locale("en_US"), err);
295     }
296 
297     ResourceBundle  test1((UnicodeString)testdatapath, err);
298     ResourceBundle  test2(testdatapath, locale, err);
299 
300     UnicodeString   result1;
301     UnicodeString   result2;
302 
303     result1 = test1.getStringEx("string_in_Root_te_te_IN", err);
304     result2 = test2.getStringEx("string_in_Root_te_te_IN", err);
305     if (U_FAILURE(err)) {
306         errln("Something threw an error in TestConstruction()");
307         return;
308     }
309 
310     logln("for string_in_Root_te_te_IN, root.txt had " + result1);
311     logln("for string_in_Root_te_te_IN, te_IN.txt had " + result2);
312 
313     if (result1 != "ROOT" || result2 != "TE_IN") {
314         errln("Construction test failed; run verbose for more information");
315     }
316 
317     const char* version1;
318     const char* version2;
319 
320     version1 = test1.getVersionNumber();
321     version2 = test2.getVersionNumber();
322 
323     char *versionID1 = new char[1 + strlen(U_ICU_VERSION) + strlen(version1)]; // + 1 for zero byte
324     char *versionID2 = new char[1 + strlen(U_ICU_VERSION) + strlen(version2)]; // + 1 for zero byte
325 
326     strcpy(versionID1, "44.0");  // hardcoded, please change if the default.txt file or ResourceBundle::kVersionSeparater is changed.
327 
328     strcpy(versionID2, "55.0");  // hardcoded, please change if the te_IN.txt file or ResourceBundle::kVersionSeparater is changed.
329 
330     logln(UnicodeString("getVersionNumber on default.txt returned ") + version1 + UnicodeString(" Expect: " ) + versionID1);
331     logln(UnicodeString("getVersionNumber on te_IN.txt returned ") + version2 + UnicodeString(" Expect: " ) + versionID2);
332 
333     if (strcmp(version1, versionID1) != 0) {
334         errln("getVersionNumber(version1) failed. %s != %s", version1, versionID1);
335     }
336     if (strcmp(version2, versionID2) != 0) {
337         errln("getVersionNumber(version2) failed. %s != %s", version2, versionID2);
338     }
339     delete[] versionID1;
340     delete[] versionID2;
341 
342     /* Restore the default locale for the other tests. */
343     Locale::setDefault(originalDefault, err);
344 }
345 
346 void
TestIteration()347 NewResourceBundleTest::TestIteration()
348 {
349     UErrorCode   err = U_ZERO_ERROR;
350     const char* testdatapath;
351     const char* data[]={
352         "string_in_Root_te_te_IN",   "1",
353         "array_in_Root_te_te_IN",    "5",
354         "array_2d_in_Root_te_te_IN", "4",
355     };
356 
357     Locale       *locale=new Locale("te_IN");
358 
359     testdatapath=loadTestData(err);
360     if(U_FAILURE(err))
361     {
362         dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err)));
363         return;
364     }
365 
366     ResourceBundle  test1(testdatapath, *locale, err);
367     if(U_FAILURE(err)){
368         errln("Construction failed");
369     }
370     uint32_t i;
371     int32_t count, row=0, col=0;
372     char buf[5];
373     UnicodeString expected;
374     UnicodeString element("TE_IN");
375     UnicodeString action;
376 
377 
378     for(i=0; i<UPRV_LENGTHOF(data); i=i+2){
379         action = "te_IN";
380         action +=".get(";
381         action += data[i];
382         action +=", err)";
383         err=U_ZERO_ERROR;
384         ResourceBundle bundle = test1.get(data[i], err);
385         if(!U_FAILURE(err)){
386             action = "te_IN";
387             action +=".getKey()";
388 
389             CONFIRM_EQ((UnicodeString)bundle.getKey(), (UnicodeString)data[i]);
390 
391             count=0;
392             row=0;
393             while(bundle.hasNext()){
394                 action = data[i];
395                 action +=".getNextString(err)";
396                 row=count;
397                 UnicodeString got=bundle.getNextString(err);
398                 if(U_SUCCESS(err)){
399                     expected=element;
400                     if(bundle.getSize() > 1){
401                         CONFIRM_EQ(bundle.getType(), URES_ARRAY);
402                         expected+=itoa(row, buf);
403                         ResourceBundle rowbundle=bundle.get(row, err);
404                         if(!U_FAILURE(err) && rowbundle.getSize()>1){
405                             col=0;
406                             while(rowbundle.hasNext()){
407                                 expected=element;
408                                 got=rowbundle.getNextString(err);
409                                 if(!U_FAILURE(err)){
410                                     expected+=itoa(row, buf);
411                                     expected+=itoa(col, buf);
412                                     col++;
413                                     CONFIRM_EQ(got, expected);
414                                 }
415                             }
416                             CONFIRM_EQ(col, rowbundle.getSize());
417                         }
418                     }
419                     else{
420                         CONFIRM_EQ(bundle.getType(), (int32_t)URES_STRING);
421                     }
422                 }
423                 CONFIRM_EQ(got, expected);
424                 count++;
425             }
426             action = data[i];
427             action +=".getSize()";
428             CONFIRM_EQ(bundle.getSize(), count);
429             CONFIRM_EQ(count, atoi(data[i+1]));
430             //after reaching the end
431             err=U_ZERO_ERROR;
432             ResourceBundle errbundle=bundle.getNext(err);
433             action = "After reaching the end of the Iterator:-  ";
434             action +=data[i];
435             action +=".getNext()";
436             CONFIRM_NE(err, (int32_t)U_ZERO_ERROR);
437             CONFIRM_EQ(u_errorName(err), u_errorName(U_INDEX_OUTOFBOUNDS_ERROR));
438             //reset the iterator
439             err = U_ZERO_ERROR;
440             bundle.resetIterator();
441          /*  The following code is causing a crash
442          ****CRASH******
443          */
444 
445             bundle.getNext(err);
446             if(U_FAILURE(err)){
447                 errln("ERROR: getNext()  throw an error");
448             }
449         }
450     }
451     delete locale;
452 }
453 
454 // TODO: add operator== and != to ResourceBundle
455 static UBool
equalRB(ResourceBundle & a,ResourceBundle & b)456 equalRB(ResourceBundle &a, ResourceBundle &b) {
457     UResType type;
458     UErrorCode status;
459 
460     type=a.getType();
461     status=U_ZERO_ERROR;
462     return
463         type==b.getType() &&
464         a.getLocale()==b.getLocale() &&
465         0==strcmp(a.getName(), b.getName()) &&
466         type==URES_STRING ?
467             a.getString(status)==b.getString(status) :
468             type==URES_INT ?
469                 a.getInt(status)==b.getInt(status) :
470                 TRUE;
471 }
472 
473 void
TestOtherAPI()474 NewResourceBundleTest::TestOtherAPI(){
475     UErrorCode   err = U_ZERO_ERROR;
476     const char* testdatapath=loadTestData(err);
477     UnicodeString tDataPathUS = UnicodeString(testdatapath, "");
478 
479     if(U_FAILURE(err))
480     {
481         dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err)));
482         return;
483     }
484 
485     /* Make sure that users using te_IN for the default locale don't get test failures. */
486     Locale originalDefault;
487     if (Locale::getDefault() == Locale("te_IN")) {
488         Locale::setDefault(Locale("en_US"), err);
489     }
490 
491     Locale       *locale=new Locale("te_IN");
492 
493     ResourceBundle test0(tDataPathUS, *locale, err);
494     if(U_FAILURE(err)){
495         errln("Construction failed");
496         return;
497     }
498 
499     ResourceBundle  test1(testdatapath, *locale, err);
500     if(U_FAILURE(err)){
501         errln("Construction failed");
502         return;
503     }
504 
505     logln("Testing getLocale()\n");
506     if(strcmp(test1.getLocale().getName(), locale->getName()) !=0 ){
507         errln("FAIL: ResourceBundle::getLocale() failed\n");
508     }
509 
510     delete locale;
511 
512     logln("Testing ResourceBundle(UErrorCode)\n");
513     ResourceBundle defaultresource(err);
514     ResourceBundle explicitdefaultresource(NULL, Locale::getDefault(), err);
515     if(U_FAILURE(err)){
516         errcheckln(err, "Construction of default resourcebundle failed - %s", u_errorName(err));
517         return;
518     }
519     // You can't compare the default locale to the resolved locale in the
520     // resource bundle due to aliasing, keywords in the default locale
521     // or the chance that the machine running these tests is using a locale
522     // that isn't available in ICU.
523     if(strcmp(defaultresource.getLocale().getName(), explicitdefaultresource.getLocale().getName()) != 0){
524         errln("Construction of default resourcebundle didn't take the defaultlocale. Expected %s Got %s err=%s\n",
525             explicitdefaultresource.getLocale().getName(), defaultresource.getLocale().getName(), u_errorName(err));
526     }
527 
528 
529     ResourceBundle copyRes(defaultresource);
530     if(strcmp(copyRes.getName(), defaultresource.getName() ) !=0  ||
531         strcmp(test1.getName(), defaultresource.getName() ) ==0 ||
532         strcmp(copyRes.getLocale().getName(), defaultresource.getLocale().getName() ) !=0  ||
533         strcmp(test1.getLocale().getName(), defaultresource.getLocale().getName() ) ==0 )
534     {
535         errln("copy construction failed\n");
536     }
537 
538     ResourceBundle defaultSub = defaultresource.get((int32_t)0, err);
539     ResourceBundle defSubCopy(defaultSub);
540     if(strcmp(defSubCopy.getName(), defaultSub.getName() ) !=0  ||
541         strcmp(defSubCopy.getLocale().getName(), defaultSub.getLocale().getName() ) !=0  ){
542         errln("copy construction for subresource failed\n");
543     }
544 
545     ResourceBundle *p;
546 
547     p = defaultresource.clone();
548     if(p == &defaultresource || !equalRB(*p, defaultresource)) {
549         errln("ResourceBundle.clone() failed");
550     }
551     delete p;
552 
553     p = defaultSub.clone();
554     if(p == &defaultSub || !equalRB(*p, defaultSub)) {
555         errln("2nd ResourceBundle.clone() failed");
556     }
557     delete p;
558 
559     UVersionInfo ver;
560     copyRes.getVersion(ver);
561 
562     logln("Version returned: [%d.%d.%d.%d]\n", ver[0], ver[1], ver[2], ver[3]);
563 
564     logln("Testing C like UnicodeString APIs\n");
565 
566     UResourceBundle *testCAPI = NULL, *bundle = NULL, *rowbundle = NULL, *temp = NULL;
567     err = U_ZERO_ERROR;
568     const char* data[]={
569         "string_in_Root_te_te_IN",   "1",
570         "array_in_Root_te_te_IN",    "5",
571         "array_2d_in_Root_te_te_IN", "4",
572     };
573 
574 
575     testCAPI = ures_open(testdatapath, "te_IN", &err);
576 
577     if(U_SUCCESS(err)) {
578         // Do the testing
579         // first iteration
580 
581         uint32_t i;
582         int32_t count, row=0, col=0;
583         char buf[5];
584         UnicodeString expected;
585         UnicodeString element("TE_IN");
586         UnicodeString action;
587 
588 
589         for(i=0; i<UPRV_LENGTHOF(data); i=i+2){
590             action = "te_IN";
591             action +=".get(";
592             action += data[i];
593             action +=", err)";
594             err=U_ZERO_ERROR;
595             bundle = ures_getByKey(testCAPI, data[i], bundle, &err);
596             if(!U_FAILURE(err)){
597                 const char* key = NULL;
598                 action = "te_IN";
599                 action +=".getKey()";
600 
601                 CONFIRM_EQ((UnicodeString)ures_getKey(bundle), (UnicodeString)data[i]);
602 
603                 count=0;
604                 row=0;
605                 while(ures_hasNext(bundle)){
606                     action = data[i];
607                     action +=".getNextString(err)";
608                     row=count;
609                     UnicodeString got=ures_getNextUnicodeString(bundle, &key, &err);
610                     if(U_SUCCESS(err)){
611                         expected=element;
612                         if(ures_getSize(bundle) > 1){
613                             CONFIRM_EQ(ures_getType(bundle), URES_ARRAY);
614                             expected+=itoa(row, buf);
615                             rowbundle=ures_getByIndex(bundle, row, rowbundle, &err);
616                             if(!U_FAILURE(err) && ures_getSize(rowbundle)>1){
617                                 col=0;
618                                 while(ures_hasNext(rowbundle)){
619                                     expected=element;
620                                     got=ures_getNextUnicodeString(rowbundle, &key, &err);
621                                     temp = ures_getByIndex(rowbundle, col, temp, &err);
622                                     UnicodeString bla = ures_getUnicodeString(temp, &err);
623                                     UnicodeString bla2 = ures_getUnicodeStringByIndex(rowbundle, col, &err);
624                                     if(!U_FAILURE(err)){
625                                         expected+=itoa(row, buf);
626                                         expected+=itoa(col, buf);
627                                         col++;
628                                         CONFIRM_EQ(got, expected);
629                                         CONFIRM_EQ(bla, expected);
630                                         CONFIRM_EQ(bla2, expected);
631                                     }
632                                 }
633                                 CONFIRM_EQ(col, ures_getSize(rowbundle));
634                             }
635                         }
636                         else{
637                             CONFIRM_EQ(ures_getType(bundle), (int32_t)URES_STRING);
638                         }
639                     }
640                     CONFIRM_EQ(got, expected);
641                     count++;
642                 }
643             }
644         }
645 
646         // Check that ures_getUnicodeString() & variants return a bogus string if failure.
647         // Same relevant code path whether the failure code is passed in
648         // or comes from a lookup error.
649         UErrorCode failure = U_INTERNAL_PROGRAM_ERROR;
650         assertTrue("ures_getUnicodeString(failure).isBogus()",
651                    ures_getUnicodeString(testCAPI, &failure).isBogus());
652         assertTrue("ures_getNextUnicodeString(failure).isBogus()",
653                    ures_getNextUnicodeString(testCAPI, NULL, &failure).isBogus());
654         assertTrue("ures_getUnicodeStringByIndex(failure).isBogus()",
655                    ures_getUnicodeStringByIndex(testCAPI, 999, &failure).isBogus());
656         assertTrue("ures_getUnicodeStringByKey(failure).isBogus()",
657                    ures_getUnicodeStringByKey(testCAPI, "bogus key", &failure).isBogus());
658 
659         ures_close(temp);
660         ures_close(rowbundle);
661         ures_close(bundle);
662         ures_close(testCAPI);
663     } else {
664         errln("failed to open a resource bundle\n");
665     }
666 
667     /* Restore the default locale for the other tests. */
668     Locale::setDefault(originalDefault, err);
669 }
670 
671 
672 
673 
674 //***************************************************************************************
675 
676 UBool
testTag(const char * frag,UBool in_Root,UBool in_te,UBool in_te_IN)677 NewResourceBundleTest::testTag(const char* frag,
678                             UBool in_Root,
679                             UBool in_te,
680                             UBool in_te_IN)
681 {
682     int32_t failOrig = fail;
683 
684     // Make array from input params
685 
686     UBool is_in[] = { in_Root, in_te, in_te_IN };
687 
688     const char* NAME[] = { "ROOT", "TE", "TE_IN" };
689 
690     // Now try to load the desired items
691 
692     char tag[100];
693     UnicodeString action;
694 
695     int32_t i,j,row,col, actual_bundle;
696     int32_t index;
697     const char* testdatapath;
698 
699     UErrorCode status = U_ZERO_ERROR;
700     testdatapath=loadTestData(status);
701     if(U_FAILURE(status))
702     {
703         dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(status)));
704         return FALSE;
705     }
706 
707     for (i=0; i<bundles_count; ++i)
708     {
709         action = "Constructor for ";
710         action += param[i].name;
711 
712         status = U_ZERO_ERROR;
713         ResourceBundle theBundle( testdatapath, *param[i].locale, status);
714         //ResourceBundle theBundle( "c:\\icu\\icu\\source\\test\\testdata\\testdata", *param[i].locale, status);
715         CONFIRM_UErrorCode(status,param[i].expected_constructor_status);
716 
717         if(i == 5)
718           actual_bundle = 0; /* ne -> default */
719         else if(i == 3)
720           actual_bundle = 1; /* te_NE -> te */
721         else if(i == 4)
722           actual_bundle = 2; /* te_IN_NE -> te_IN */
723         else
724           actual_bundle = i;
725 
726 
727         UErrorCode expected_resource_status = U_MISSING_RESOURCE_ERROR;
728         for (j=e_te_IN; j>=e_Root; --j)
729         {
730             if (is_in[j] && param[i].inherits[j])
731               {
732                 if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */
733                   expected_resource_status = U_ZERO_ERROR;
734                 else if(j == 0)
735                   expected_resource_status = U_USING_DEFAULT_WARNING;
736                 else
737                   expected_resource_status = U_USING_FALLBACK_WARNING;
738 
739                 break;
740             }
741         }
742 
743         UErrorCode expected_status;
744 
745         UnicodeString base;
746         for (j=param[i].where; j>=0; --j)
747         {
748             if (is_in[j])
749             {
750                 base = NAME[j];
751                 break;
752             }
753         }
754 
755         //--------------------------------------------------------------------------
756         // string
757 
758         uprv_strcpy(tag, "string_");
759         uprv_strcat(tag, frag);
760 
761         action = param[i].name;
762         action += ".getStringEx(";
763         action += tag;
764         action += ")";
765 
766 
767         status = U_ZERO_ERROR;
768         UnicodeString string = theBundle.getStringEx(tag, status);
769         if(U_FAILURE(status)) {
770             string.setTo(TRUE, kErrorUChars, kErrorLength);
771         }
772 
773         CONFIRM_UErrorCode(status, expected_resource_status);
774 
775         UnicodeString expected_string(kErrorUChars);
776         if (U_SUCCESS(status)) {
777             expected_string = base;
778         }
779 
780         CONFIRM_EQ(string, expected_string);
781 
782         //--------------------------------------------------------------------------
783         // array   ResourceBundle using the key
784 
785         uprv_strcpy(tag, "array_");
786         uprv_strcat(tag, frag);
787 
788         action = param[i].name;
789         action += ".get(";
790         action += tag;
791         action += ")";
792 
793         int32_t count = kERROR_COUNT;
794         status = U_ZERO_ERROR;
795         ResourceBundle array = theBundle.get(tag, status);
796         CONFIRM_UErrorCode(status,expected_resource_status);
797 
798 
799         if (U_SUCCESS(status))
800         {
801             //confirm the resource type is an array
802             UResType bundleType=array.getType();
803             CONFIRM_EQ(bundleType, URES_ARRAY);
804 
805             count=array.getSize();
806             CONFIRM_GE(count,1);
807 
808             for (j=0; j<count; ++j)
809             {
810                 char buf[32];
811                 expected_string = base;
812                 expected_string += itoa(j,buf);
813                 CONFIRM_EQ(array.getNextString(status),expected_string);
814             }
815 
816         }
817         else
818         {
819             CONFIRM_EQ(count,kERROR_COUNT);
820             //       CONFIRM_EQ((int32_t)(unsigned long)array,(int32_t)0);
821             count = 0;
822         }
823 
824         //--------------------------------------------------------------------------
825         // arrayItem ResourceBundle using the index
826 
827 
828         for (j=0; j<100; ++j)
829         {
830             index = count ? (randi(count * 3) - count) : (randi(200) - 100);
831             status = U_ZERO_ERROR;
832             string = kErrorUChars;
833             ResourceBundle array = theBundle.get(tag, status);
834             if(!U_FAILURE(status)){
835                 UnicodeString t = array.getStringEx(index, status);
836                 if(!U_FAILURE(status)) {
837                    string=t;
838                 }
839             }
840 
841             expected_status = (index >= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR;
842             CONFIRM_UErrorCode(status,expected_status);
843 
844             if (U_SUCCESS(status)){
845                 char buf[32];
846                 expected_string = base;
847                 expected_string += itoa(index,buf);
848             } else {
849                 expected_string = kErrorUChars;
850             }
851                CONFIRM_EQ(string,expected_string);
852 
853         }
854 
855         //--------------------------------------------------------------------------
856         // 2dArray
857 
858         uprv_strcpy(tag, "array_2d_");
859         uprv_strcat(tag, frag);
860 
861         action = param[i].name;
862         action += ".get(";
863         action += tag;
864         action += ")";
865 
866 
867         int32_t row_count = kERROR_COUNT, column_count = kERROR_COUNT;
868         status = U_ZERO_ERROR;
869         ResourceBundle array2d=theBundle.get(tag, status);
870 
871         //const UnicodeString** array2d = theBundle.get2dArray(tag, row_count, column_count, status);
872         CONFIRM_UErrorCode(status,expected_resource_status);
873 
874         if (U_SUCCESS(status))
875         {
876             //confirm the resource type is an 2darray
877             UResType bundleType=array2d.getType();
878             CONFIRM_EQ(bundleType, URES_ARRAY);
879 
880             row_count=array2d.getSize();
881             CONFIRM_GE(row_count,1);
882 
883             for(row=0; row<row_count; ++row){
884                 ResourceBundle tablerow=array2d.get(row, status);
885                 CONFIRM_UErrorCode(status, expected_resource_status);
886                 if(U_SUCCESS(status)){
887                     //confirm the resourcetype of each table row is an array
888                     UResType rowType=tablerow.getType();
889                     CONFIRM_EQ(rowType, URES_ARRAY);
890 
891                     column_count=tablerow.getSize();
892                     CONFIRM_GE(column_count,1);
893 
894                     for (col=0; j<column_count; ++j) {
895                            char buf[32];
896                            expected_string = base;
897                            expected_string += itoa(row,buf);
898                            expected_string += itoa(col,buf);
899                            CONFIRM_EQ(tablerow.getNextString(status),expected_string);
900                     }
901                 }
902             }
903         }else{
904             CONFIRM_EQ(row_count,kERROR_COUNT);
905             CONFIRM_EQ(column_count,kERROR_COUNT);
906              row_count=column_count=0;
907         }
908 
909 
910 
911 
912        //--------------------------------------------------------------------------
913        // 2dArrayItem
914        for (j=0; j<200; ++j)
915        {
916            row = row_count ? (randi(row_count * 3) - row_count) : (randi(200) - 100);
917            col = column_count ? (randi(column_count * 3) - column_count) : (randi(200) - 100);
918            status = U_ZERO_ERROR;
919            string = kErrorUChars;
920            ResourceBundle array2d=theBundle.get(tag, status);
921            if(U_SUCCESS(status)){
922                 ResourceBundle tablerow=array2d.get(row, status);
923                 if(U_SUCCESS(status)) {
924                     UnicodeString t=tablerow.getStringEx(col, status);
925                     if(U_SUCCESS(status)){
926                        string=t;
927                     }
928                 }
929            }
930            expected_status = (row >= 0 && row < row_count && col >= 0 && col < column_count) ?
931                                   expected_resource_status: U_MISSING_RESOURCE_ERROR;
932            CONFIRM_UErrorCode(status,expected_status);
933 
934            if (U_SUCCESS(status)){
935                char buf[32];
936                expected_string = base;
937                expected_string += itoa(row,buf);
938                expected_string += itoa(col,buf);
939            } else {
940                expected_string = kErrorUChars;
941            }
942                CONFIRM_EQ(string,expected_string);
943 
944         }
945 
946         //--------------------------------------------------------------------------
947         // taggedArray
948 
949         uprv_strcpy(tag, "tagged_array_");
950         uprv_strcat(tag, frag);
951 
952         action = param[i].name;
953         action += ".get(";
954         action += tag;
955         action += ")";
956 
957         int32_t         tag_count;
958         status = U_ZERO_ERROR;
959 
960         ResourceBundle tags=theBundle.get(tag, status);
961         CONFIRM_UErrorCode(status, expected_resource_status);
962 
963         if (U_SUCCESS(status)) {
964             UResType bundleType=tags.getType();
965             CONFIRM_EQ(bundleType, URES_TABLE);
966 
967             tag_count=tags.getSize();
968             CONFIRM_GE((int32_t)tag_count, (int32_t)0);
969 
970             for(index=0; index <tag_count; index++){
971                 ResourceBundle tagelement=tags.get(index, status);
972                 UnicodeString key=tagelement.getKey();
973                 UnicodeString value=tagelement.getNextString(status);
974                 logln("tag = " + key + ", value = " + value );
975                 if(key.startsWith("tag") && value.startsWith(base)){
976                     record_pass();
977                 }else{
978                     record_fail();
979                 }
980 
981             }
982 
983             for(index=0; index <tag_count; index++){
984                 ResourceBundle tagelement=tags.get(index, status);
985                 const char *tkey=NULL;
986                 UnicodeString value=tagelement.getNextString(&tkey, status);
987                 UnicodeString key(tkey);
988                 logln("tag = " + key + ", value = " + value );
989                 if(value.startsWith(base)){
990                     record_pass();
991                 }else{
992                     record_fail();
993                 }
994             }
995 
996         }else{
997             tag_count=0;
998         }
999 
1000 
1001 
1002 
1003         //--------------------------------------------------------------------------
1004         // taggedArrayItem
1005 
1006         action = param[i].name;
1007         action += ".get(";
1008         action += tag;
1009         action += ")";
1010 
1011         count = 0;
1012         for (index=-20; index<20; ++index)
1013         {
1014             char buf[32];
1015             status = U_ZERO_ERROR;
1016             string = kErrorUChars;
1017             char item_tag[8];
1018             uprv_strcpy(item_tag, "tag");
1019             uprv_strcat(item_tag, itoa(index,buf));
1020             ResourceBundle tags=theBundle.get(tag, status);
1021             if(U_SUCCESS(status)){
1022                 ResourceBundle tagelement=tags.get(item_tag, status);
1023                 if(!U_FAILURE(status)){
1024                     UResType elementType=tagelement.getType();
1025                     CONFIRM_EQ(elementType, (int32_t)URES_STRING);
1026                     const char* key=tagelement.getKey();
1027                     CONFIRM_EQ((UnicodeString)key, (UnicodeString)item_tag);
1028                     UnicodeString t=tagelement.getString(status);
1029                     if(!U_FAILURE(status)){
1030                         string=t;
1031                     }
1032                 }
1033                 if (index < 0) {
1034                     CONFIRM_UErrorCode(status,U_MISSING_RESOURCE_ERROR);
1035                 }
1036                 else{
1037                    if (status != U_MISSING_RESOURCE_ERROR) {
1038                        count++;
1039                        expected_string = base;
1040                        expected_string += buf;
1041                        CONFIRM_EQ(string,expected_string);
1042                    }
1043                 }
1044             }
1045 
1046         }
1047         CONFIRM_EQ(count, tag_count);
1048 
1049     }
1050     return (UBool)(failOrig == fail);
1051 }
1052 
1053 void
record_pass()1054 NewResourceBundleTest::record_pass()
1055 {
1056   ++pass;
1057 }
1058 void
record_fail()1059 NewResourceBundleTest::record_fail()
1060 {
1061   err();
1062   ++fail;
1063 }
1064 
1065 
1066 void
TestNewTypes()1067 NewResourceBundleTest::TestNewTypes() {
1068     char action[256];
1069     const char* testdatapath;
1070     UErrorCode status = U_ZERO_ERROR;
1071     uint8_t *binResult = NULL;
1072     int32_t len = 0;
1073     int32_t i = 0;
1074     int32_t intResult = 0;
1075     uint32_t uintResult = 0;
1076     UChar expected[] = { 'a','b','c','\0','d','e','f' };
1077     const char* expect ="tab:\t cr:\r ff:\f newline:\n backslash:\\\\ quote=\\\' doubleQuote=\\\" singlequoutes=''";
1078     UChar uExpect[200];
1079 
1080     testdatapath=loadTestData(status);
1081 
1082     if(U_FAILURE(status))
1083     {
1084         dataerrln("Could not load testdata.dat %s \n",u_errorName(status));
1085         return;
1086     }
1087 
1088     ResourceBundle theBundle(testdatapath, "testtypes", status);
1089     ResourceBundle bundle(testdatapath, Locale("te_IN"),status);
1090 
1091     UnicodeString emptyStr = theBundle.getStringEx("emptystring", status);
1092     if(emptyStr.length() != 0) {
1093       logln("Empty string returned invalid value\n");
1094     }
1095 
1096     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1097 
1098     /* This test reads the string "abc\u0000def" from the bundle   */
1099     /* if everything is working correctly, the size of this string */
1100     /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/
1101 
1102     strcpy(action, "getting and testing of string with embeded zero");
1103     ResourceBundle res = theBundle.get("zerotest", status);
1104     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1105     CONFIRM_EQ(res.getType(), URES_STRING);
1106     UnicodeString zeroString=res.getString(status);
1107     len = zeroString.length();
1108     if(U_SUCCESS(status)){
1109         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1110         CONFIRM_EQ(len, 7);
1111         CONFIRM_NE(len, 3);
1112     }
1113     for(i=0;i<len;i++){
1114         if(zeroString[i]!= expected[i]){
1115             logln("Output didnot match Expected: \\u%4X Got: \\u%4X", expected[i], zeroString[i]);
1116         }
1117     }
1118 
1119     strcpy(action, "getting and testing of binary type");
1120     res = theBundle.get("binarytest", status);
1121     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1122     CONFIRM_EQ(res.getType(), URES_BINARY);
1123     binResult=(uint8_t*)res.getBinary(len, status);
1124     if(U_SUCCESS(status)){
1125         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1126         CONFIRM_EQ(len, 15);
1127         for(i = 0; i<15; i++) {
1128             CONFIRM_EQ(binResult[i], i);
1129         }
1130     }
1131 
1132     strcpy(action, "getting and testing of imported binary type");
1133     res = theBundle.get("importtest",status);
1134     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1135     CONFIRM_EQ(res.getType(), URES_BINARY);
1136     binResult=(uint8_t*)res.getBinary(len, status);
1137     if(U_SUCCESS(status)){
1138         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1139         CONFIRM_EQ(len, 15);
1140         for(i = 0; i<15; i++) {
1141             CONFIRM_EQ(binResult[i], i);
1142         }
1143     }
1144 
1145     strcpy(action, "getting and testing of integer types");
1146     res = theBundle.get("one",  status);
1147     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1148     CONFIRM_EQ(res.getType(), URES_INT);
1149     intResult=res.getInt(status);
1150     uintResult = res.getUInt(status);
1151     if(U_SUCCESS(status)){
1152         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1153         CONFIRM_EQ(uintResult, (uint32_t)intResult);
1154         CONFIRM_EQ(intResult, 1);
1155     }
1156 
1157     strcpy(action, "getting minusone");
1158     res = theBundle.get((const char*)"minusone", status);
1159     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1160     CONFIRM_EQ(res.getType(), URES_INT);
1161     intResult=res.getInt(status);
1162     uintResult = res.getUInt(status);
1163     if(U_SUCCESS(status)){
1164         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1165         CONFIRM_EQ(uintResult, 0x0FFFFFFF); /* a 28 bit integer */
1166         CONFIRM_EQ(intResult, -1);
1167         CONFIRM_NE(uintResult, (uint32_t)intResult);
1168     }
1169 
1170     strcpy(action, "getting plusone");
1171     res = theBundle.get("plusone",status);
1172     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1173     CONFIRM_EQ(res.getType(), URES_INT);
1174     intResult=res.getInt(status);
1175     uintResult = res.getUInt(status);
1176     if(U_SUCCESS(status)){
1177         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1178         CONFIRM_EQ(uintResult, (uint32_t)intResult);
1179         CONFIRM_EQ(intResult, 1);
1180     }
1181 
1182     res = theBundle.get("onehundredtwentythree",status);
1183     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1184     CONFIRM_EQ(res.getType(), URES_INT);
1185     intResult=res.getInt(status);
1186     if(U_SUCCESS(status)){
1187         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1188         CONFIRM_EQ(intResult, 123);
1189     }
1190 
1191     /* this tests if escapes are preserved or not */
1192     {
1193         UnicodeString str = theBundle.getStringEx("testescape",status);
1194         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1195         if(U_SUCCESS(status)){
1196             u_charsToUChars(expect,uExpect,(int32_t)uprv_strlen(expect)+1);
1197             if(str.compare(uExpect)!=0){
1198                 errln("Did not get the expected string for testescape expected. Expected : "
1199                     +UnicodeString(uExpect )+ " Got: " + str);
1200             }
1201         }
1202     }
1203     /* test for jitterbug#1435 */
1204     {
1205         UnicodeString str = theBundle.getStringEx("test_underscores",status);
1206         expect ="test message ....";
1207         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1208         u_charsToUChars(expect,uExpect,(int32_t)uprv_strlen(expect)+1);
1209         if(str.compare(uExpect)!=0){
1210             errln("Did not get the expected string for test_underscores.\n");
1211         }
1212     }
1213 
1214 
1215 }
1216 
1217 void
TestGetByFallback()1218 NewResourceBundleTest::TestGetByFallback() {
1219     UErrorCode status = U_ZERO_ERROR;
1220 
1221     ResourceBundle heRes(NULL, "he", status);
1222 
1223     heRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("DateTime", status);
1224     if(U_SUCCESS(status)) {
1225         errln("he locale's Islamic-civil DateTime resource exists. How did it get here?\n");
1226     }
1227     status = U_ZERO_ERROR;
1228 
1229     heRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("eras", status);
1230     if(U_FAILURE(status)) {
1231         dataerrln("Didn't get Islamic Eras. I know they are there! - %s", u_errorName(status));
1232     }
1233     status = U_ZERO_ERROR;
1234 
1235     ResourceBundle rootRes(NULL, "root", status);
1236     rootRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("DateTime", status);
1237     if(U_SUCCESS(status)) {
1238         errln("Root's Islamic-civil's DateTime resource exists. How did it get here?\n");
1239     }
1240     status = U_ZERO_ERROR;
1241 
1242 }
1243 
1244 
1245 #define REQUIRE_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
1246     if (status.errIfFailureAndReset("line %d", __LINE__)) { \
1247         return; \
1248     } \
1249 } UPRV_BLOCK_MACRO_END
1250 
1251 #define REQUIRE_ERROR(expected, status) UPRV_BLOCK_MACRO_BEGIN { \
1252     if (!status.expectErrorAndReset(expected, "line %d", __LINE__)) { \
1253         return; \
1254     } \
1255 } UPRV_BLOCK_MACRO_END
1256 
1257 /**
1258  * Tests the --filterDir option in genrb.
1259  *
1260  * Input resource text file: test/testdata/filtertest.txt
1261  * Input filter rule file: test/testdata/filters/filtertest.txt
1262  *
1263  * The resource bundle should contain no keys matched by the filter
1264  * and should contain all other keys.
1265  */
TestFilter()1266 void NewResourceBundleTest::TestFilter() {
1267     IcuTestErrorCode status(*this, "TestFilter");
1268 
1269     ResourceBundle rb(loadTestData(status), "filtertest", status);
1270     REQUIRE_SUCCESS(status);
1271     assertEquals("rb", rb.getType(), URES_TABLE);
1272 
1273     ResourceBundle alabama = rb.get("alabama", status);
1274     REQUIRE_SUCCESS(status);
1275     assertEquals("alabama", alabama.getType(), URES_TABLE);
1276 
1277     {
1278         ResourceBundle alaska = alabama.get("alaska", status);
1279         REQUIRE_SUCCESS(status);
1280         assertEquals("alaska", alaska.getType(), URES_TABLE);
1281 
1282         {
1283             ResourceBundle arizona = alaska.get("arizona", status);
1284             REQUIRE_SUCCESS(status);
1285             assertEquals("arizona", arizona.getType(), URES_STRING);
1286             assertEquals("arizona", u"arkansas", arizona.getString(status));
1287             REQUIRE_SUCCESS(status);
1288 
1289             // Filter: california should not be included
1290             ResourceBundle california = alaska.get("california", status);
1291             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1292         }
1293 
1294         // Filter: connecticut should not be included
1295         ResourceBundle connecticut = alabama.get("connecticut", status);
1296         REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1297     }
1298 
1299     ResourceBundle fornia = rb.get("fornia", status);
1300     REQUIRE_SUCCESS(status);
1301     assertEquals("fornia", fornia.getType(), URES_TABLE);
1302 
1303     {
1304         // Filter: hawaii should not be included based on parent inheritance
1305         ResourceBundle hawaii = fornia.get("hawaii", status);
1306         REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1307 
1308         // Filter: illinois should not be included based on direct rule
1309         ResourceBundle illinois = fornia.get("illinois", status);
1310         REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1311     }
1312 
1313     ResourceBundle mississippi = rb.get("mississippi", status);
1314     REQUIRE_SUCCESS(status);
1315     assertEquals("mississippi", mississippi.getType(), URES_TABLE);
1316 
1317     {
1318         ResourceBundle louisiana = mississippi.get("louisiana", status);
1319         REQUIRE_SUCCESS(status);
1320         assertEquals("louisiana", louisiana.getType(), URES_TABLE);
1321 
1322         {
1323             ResourceBundle maine = louisiana.get("maine", status);
1324             REQUIRE_SUCCESS(status);
1325             assertEquals("maine", maine.getType(), URES_STRING);
1326             assertEquals("maine", u"maryland", maine.getString(status));
1327             REQUIRE_SUCCESS(status);
1328 
1329             ResourceBundle iowa = louisiana.get("iowa", status);
1330             REQUIRE_SUCCESS(status);
1331             assertEquals("iowa", iowa.getType(), URES_STRING);
1332             assertEquals("iowa", u"kansas", iowa.getString(status));
1333             REQUIRE_SUCCESS(status);
1334 
1335             // Filter: missouri should not be included
1336             ResourceBundle missouri = louisiana.get("missouri", status);
1337             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1338         }
1339 
1340         ResourceBundle michigan = mississippi.get("michigan", status);
1341         REQUIRE_SUCCESS(status);
1342         assertEquals("michigan", michigan.getType(), URES_TABLE);
1343 
1344         {
1345             ResourceBundle maine = michigan.get("maine", status);
1346             REQUIRE_SUCCESS(status);
1347             assertEquals("maine", maine.getType(), URES_STRING);
1348             assertEquals("maine", u"minnesota", maine.getString(status));
1349             REQUIRE_SUCCESS(status);
1350 
1351             // Filter: iowa should not be included
1352             ResourceBundle iowa = michigan.get("iowa", status);
1353             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1354 
1355             ResourceBundle missouri = michigan.get("missouri", status);
1356             REQUIRE_SUCCESS(status);
1357             assertEquals("missouri", missouri.getType(), URES_STRING);
1358             assertEquals("missouri", u"nebraska", missouri.getString(status));
1359             REQUIRE_SUCCESS(status);
1360         }
1361 
1362         ResourceBundle nevada = mississippi.get("nevada", status);
1363         REQUIRE_SUCCESS(status);
1364         assertEquals("nevada", nevada.getType(), URES_TABLE);
1365 
1366         {
1367             ResourceBundle maine = nevada.get("maine", status);
1368             REQUIRE_SUCCESS(status);
1369             assertEquals("maine", maine.getType(), URES_STRING);
1370             assertEquals("maine", u"new-hampshire", maine.getString(status));
1371             REQUIRE_SUCCESS(status);
1372 
1373             // Filter: iowa should not be included
1374             ResourceBundle iowa = nevada.get("iowa", status);
1375             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1376 
1377             // Filter: missouri should not be included
1378             ResourceBundle missouri = nevada.get("missouri", status);
1379             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1380         }
1381     }
1382 
1383     // Filter: northCarolina should be included based on direct rule,
1384     // and so should its child, northDakota
1385     ResourceBundle northCarolina = rb.get("northCarolina", status);
1386     REQUIRE_SUCCESS(status);
1387     assertEquals("northCarolina", northCarolina.getType(), URES_TABLE);
1388 
1389     {
1390         ResourceBundle northDakota = northCarolina.get("northDakota", status);
1391         REQUIRE_SUCCESS(status);
1392         assertEquals("northDakota", northDakota.getType(), URES_STRING);
1393         assertEquals("northDakota", u"west-virginia", northDakota.getString(status));
1394         REQUIRE_SUCCESS(status);
1395     }
1396 }
1397 
TestIntervalAliasFallbacks()1398 void NewResourceBundleTest::TestIntervalAliasFallbacks() {
1399     const char* locales[] = {
1400         // Thee will not cause infinity loop
1401         "en",
1402         "ja",
1403 
1404         // These will cause infinity loop
1405         "fr_CA",
1406         "en_150",
1407         "es_419",
1408         "id",
1409         "in",
1410         "pl",
1411         "pt_PT",
1412         "sr_ME",
1413         "zh_Hant",
1414         "zh_Hant_TW",
1415         "zh_TW",
1416     };
1417     const char* calendars[] = {
1418         // These won't cause infinity loop
1419         "gregorian",
1420         "chinese",
1421 
1422         // These will cause infinity loop
1423         "islamic",
1424         "islamic-civil",
1425         "islamic-tbla",
1426         "islamic-umalqura",
1427         "ethiopic-amete-alem",
1428         "islamic-rgsa",
1429         "japanese",
1430         "roc",
1431     };
1432 
1433     for (int lidx = 0; lidx < UPRV_LENGTHOF(locales); lidx++) {
1434         UErrorCode status = U_ZERO_ERROR;
1435         UResourceBundle *rb = ures_open(NULL, locales[lidx], &status);
1436         if (U_FAILURE(status)) {
1437             errln("Cannot open bundle for locale %s", locales[lidx]);
1438             break;
1439         }
1440         for (int cidx = 0; cidx < UPRV_LENGTHOF(calendars); cidx++) {
1441             CharString key;
1442             key.append("calendar/", status);
1443             key.append(calendars[cidx], status);
1444             key.append("/intervalFormats/fallback", status);
1445             if (! logKnownIssue("20400")) {
1446                 int32_t resStrLen = 0;
1447                 ures_getStringByKeyWithFallback(rb, key.data(), &resStrLen, &status);
1448             }
1449             if (U_FAILURE(status)) {
1450                 errln("Cannot ures_getStringByKeyWithFallback('%s') on locale %s",
1451                       key.data(), locales[lidx]);
1452                 break;
1453             }
1454         }
1455         ures_close(rb);
1456     }
1457 }
1458 
1459 #if U_ENABLE_TRACING
1460 
1461 static std::vector<std::string> gResourcePathsTraced;
1462 static std::vector<std::string> gDataFilesTraced;
1463 static std::vector<std::string> gBundlesTraced;
1464 
traceData(const void *,int32_t fnNumber,int32_t,const char *,va_list args)1465 static void U_CALLCONV traceData(
1466         const void*,
1467         int32_t fnNumber,
1468         int32_t,
1469         const char *,
1470         va_list args) {
1471 
1472     // NOTE: Whether this test is run in isolation affects whether or not
1473     // *.res files are opened. For stability, ignore *.res file opens.
1474 
1475     if (fnNumber == UTRACE_UDATA_RESOURCE) {
1476         va_arg(args, const char*); // type
1477         va_arg(args, const char*); // file
1478         const char* resourcePath = va_arg(args, const char*);
1479         gResourcePathsTraced.push_back(resourcePath);
1480     } else if (fnNumber == UTRACE_UDATA_BUNDLE) {
1481         const char* filePath = va_arg(args, const char*);
1482         gBundlesTraced.push_back(filePath);
1483     } else if (fnNumber == UTRACE_UDATA_DATA_FILE) {
1484         const char* filePath = va_arg(args, const char*);
1485         gDataFilesTraced.push_back(filePath);
1486     } else if (fnNumber == UTRACE_UDATA_RES_FILE) {
1487         // ignore
1488     }
1489 }
1490 
TestTrace()1491 void NewResourceBundleTest::TestTrace() {
1492     IcuTestErrorCode status(*this, "TestTrace");
1493 
1494     assertEquals("Start position stability coverage", 0x3000, UTRACE_UDATA_START);
1495 
1496     const void* context;
1497     utrace_setFunctions(context, nullptr, nullptr, traceData);
1498     utrace_setLevel(UTRACE_VERBOSE);
1499 
1500     {
1501         LocalPointer<BreakIterator> brkitr(BreakIterator::createWordInstance("zh-CN", status));
1502 
1503         assertEquals("Should touch expected resource paths",
1504             { "/boundaries", "/boundaries/word", "/boundaries/word" },
1505             gResourcePathsTraced);
1506         assertEquals("Should touch expected resource bundles",
1507             { U_ICUDATA_NAME "-brkitr/zh.res" },
1508             gBundlesTraced);
1509         assertEquals("Should touch expected data files",
1510             { U_ICUDATA_NAME "-brkitr/word.brk" },
1511             gDataFilesTraced);
1512         gResourcePathsTraced.clear();
1513         gDataFilesTraced.clear();
1514         gBundlesTraced.clear();
1515     }
1516 
1517     {
1518         ucurr_getDefaultFractionDigits(u"USD", status);
1519 
1520         assertEquals("Should touch expected resource paths",
1521             { "/CurrencyMeta", "/CurrencyMeta/DEFAULT", "/CurrencyMeta/DEFAULT" },
1522             gResourcePathsTraced);
1523         assertEquals("Should touch expected resource bundles",
1524             { U_ICUDATA_NAME "-curr/supplementalData.res" },
1525             gBundlesTraced);
1526         assertEquals("Should touch expected data files",
1527             { },
1528             gDataFilesTraced);
1529         gResourcePathsTraced.clear();
1530         gDataFilesTraced.clear();
1531         gBundlesTraced.clear();
1532     }
1533 
1534     utrace_setFunctions(context, nullptr, nullptr, nullptr);
1535 }
1536 
1537 #endif
1538 
1539 //eof
1540 
1541