• 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     {
539         LocalPointer<ResourceBundle> p(defaultresource.clone());
540         if(p.getAlias() == &defaultresource || !equalRB(*p, defaultresource)) {
541             errln("ResourceBundle.clone() failed");
542         }
543     }
544 
545     // The following tests involving defaultSub may no longer be exercised if
546     // defaultresource is for a locale like en_US with an empty resource bundle.
547     // (Before ICU-21028 such a bundle would have contained at least a Version string.)
548     if(defaultresource.getSize() != 0) {
549         ResourceBundle defaultSub = defaultresource.get((int32_t)0, err);
550         ResourceBundle defSubCopy(defaultSub);
551         if(strcmp(defSubCopy.getName(), defaultSub.getName()) != 0 ||
552                 strcmp(defSubCopy.getLocale().getName(), defaultSub.getLocale().getName() ) != 0) {
553             errln("copy construction for subresource failed\n");
554         }
555         LocalPointer<ResourceBundle> p(defaultSub.clone());
556         if(p.getAlias() == &defaultSub || !equalRB(*p, defaultSub)) {
557             errln("2nd ResourceBundle.clone() failed");
558         }
559     }
560 
561     UVersionInfo ver;
562     copyRes.getVersion(ver);
563 
564     logln("Version returned: [%d.%d.%d.%d]\n", ver[0], ver[1], ver[2], ver[3]);
565 
566     logln("Testing C like UnicodeString APIs\n");
567 
568     UResourceBundle *testCAPI = NULL, *bundle = NULL, *rowbundle = NULL, *temp = NULL;
569     err = U_ZERO_ERROR;
570     const char* data[]={
571         "string_in_Root_te_te_IN",   "1",
572         "array_in_Root_te_te_IN",    "5",
573         "array_2d_in_Root_te_te_IN", "4",
574     };
575 
576 
577     testCAPI = ures_open(testdatapath, "te_IN", &err);
578 
579     if(U_SUCCESS(err)) {
580         // Do the testing
581         // first iteration
582 
583         uint32_t i;
584         int32_t count, row=0, col=0;
585         char buf[5];
586         UnicodeString expected;
587         UnicodeString element("TE_IN");
588         UnicodeString action;
589 
590 
591         for(i=0; i<UPRV_LENGTHOF(data); i=i+2){
592             action = "te_IN";
593             action +=".get(";
594             action += data[i];
595             action +=", err)";
596             err=U_ZERO_ERROR;
597             bundle = ures_getByKey(testCAPI, data[i], bundle, &err);
598             if(!U_FAILURE(err)){
599                 const char* key = NULL;
600                 action = "te_IN";
601                 action +=".getKey()";
602 
603                 CONFIRM_EQ((UnicodeString)ures_getKey(bundle), (UnicodeString)data[i]);
604 
605                 count=0;
606                 row=0;
607                 while(ures_hasNext(bundle)){
608                     action = data[i];
609                     action +=".getNextString(err)";
610                     row=count;
611                     UnicodeString got=ures_getNextUnicodeString(bundle, &key, &err);
612                     if(U_SUCCESS(err)){
613                         expected=element;
614                         if(ures_getSize(bundle) > 1){
615                             CONFIRM_EQ(ures_getType(bundle), URES_ARRAY);
616                             expected+=itoa(row, buf);
617                             rowbundle=ures_getByIndex(bundle, row, rowbundle, &err);
618                             if(!U_FAILURE(err) && ures_getSize(rowbundle)>1){
619                                 col=0;
620                                 while(ures_hasNext(rowbundle)){
621                                     expected=element;
622                                     got=ures_getNextUnicodeString(rowbundle, &key, &err);
623                                     temp = ures_getByIndex(rowbundle, col, temp, &err);
624                                     UnicodeString bla = ures_getUnicodeString(temp, &err);
625                                     UnicodeString bla2 = ures_getUnicodeStringByIndex(rowbundle, col, &err);
626                                     if(!U_FAILURE(err)){
627                                         expected+=itoa(row, buf);
628                                         expected+=itoa(col, buf);
629                                         col++;
630                                         CONFIRM_EQ(got, expected);
631                                         CONFIRM_EQ(bla, expected);
632                                         CONFIRM_EQ(bla2, expected);
633                                     }
634                                 }
635                                 CONFIRM_EQ(col, ures_getSize(rowbundle));
636                             }
637                         }
638                         else{
639                             CONFIRM_EQ(ures_getType(bundle), (int32_t)URES_STRING);
640                         }
641                     }
642                     CONFIRM_EQ(got, expected);
643                     count++;
644                 }
645             }
646         }
647 
648         // Check that ures_getUnicodeString() & variants return a bogus string if failure.
649         // Same relevant code path whether the failure code is passed in
650         // or comes from a lookup error.
651         UErrorCode failure = U_INTERNAL_PROGRAM_ERROR;
652         assertTrue("ures_getUnicodeString(failure).isBogus()",
653                    ures_getUnicodeString(testCAPI, &failure).isBogus());
654         assertTrue("ures_getNextUnicodeString(failure).isBogus()",
655                    ures_getNextUnicodeString(testCAPI, NULL, &failure).isBogus());
656         assertTrue("ures_getUnicodeStringByIndex(failure).isBogus()",
657                    ures_getUnicodeStringByIndex(testCAPI, 999, &failure).isBogus());
658         assertTrue("ures_getUnicodeStringByKey(failure).isBogus()",
659                    ures_getUnicodeStringByKey(testCAPI, "bogus key", &failure).isBogus());
660 
661         ures_close(temp);
662         ures_close(rowbundle);
663         ures_close(bundle);
664         ures_close(testCAPI);
665     } else {
666         errln("failed to open a resource bundle\n");
667     }
668 
669     /* Restore the default locale for the other tests. */
670     Locale::setDefault(originalDefault, err);
671 }
672 
673 
674 
675 
676 //***************************************************************************************
677 
678 UBool
testTag(const char * frag,UBool in_Root,UBool in_te,UBool in_te_IN)679 NewResourceBundleTest::testTag(const char* frag,
680                             UBool in_Root,
681                             UBool in_te,
682                             UBool in_te_IN)
683 {
684     int32_t failOrig = fail;
685 
686     // Make array from input params
687 
688     UBool is_in[] = { in_Root, in_te, in_te_IN };
689 
690     const char* NAME[] = { "ROOT", "TE", "TE_IN" };
691 
692     // Now try to load the desired items
693 
694     char tag[100];
695     UnicodeString action;
696 
697     int32_t i,j,row,col, actual_bundle;
698     int32_t index;
699     const char* testdatapath;
700 
701     UErrorCode status = U_ZERO_ERROR;
702     testdatapath=loadTestData(status);
703     if(U_FAILURE(status))
704     {
705         dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(status)));
706         return FALSE;
707     }
708 
709     for (i=0; i<bundles_count; ++i)
710     {
711         action = "Constructor for ";
712         action += param[i].name;
713 
714         status = U_ZERO_ERROR;
715         ResourceBundle theBundle( testdatapath, *param[i].locale, status);
716         //ResourceBundle theBundle( "c:\\icu\\icu\\source\\test\\testdata\\testdata", *param[i].locale, status);
717         CONFIRM_UErrorCode(status,param[i].expected_constructor_status);
718 
719         if(i == 5)
720           actual_bundle = 0; /* ne -> default */
721         else if(i == 3)
722           actual_bundle = 1; /* te_NE -> te */
723         else if(i == 4)
724           actual_bundle = 2; /* te_IN_NE -> te_IN */
725         else
726           actual_bundle = i;
727 
728 
729         UErrorCode expected_resource_status = U_MISSING_RESOURCE_ERROR;
730         for (j=e_te_IN; j>=e_Root; --j)
731         {
732             if (is_in[j] && param[i].inherits[j])
733               {
734                 if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */
735                   expected_resource_status = U_ZERO_ERROR;
736                 else if(j == 0)
737                   expected_resource_status = U_USING_DEFAULT_WARNING;
738                 else
739                   expected_resource_status = U_USING_FALLBACK_WARNING;
740 
741                 break;
742             }
743         }
744 
745         UErrorCode expected_status;
746 
747         UnicodeString base;
748         for (j=param[i].where; j>=0; --j)
749         {
750             if (is_in[j])
751             {
752                 base = NAME[j];
753                 break;
754             }
755         }
756 
757         //--------------------------------------------------------------------------
758         // string
759 
760         uprv_strcpy(tag, "string_");
761         uprv_strcat(tag, frag);
762 
763         action = param[i].name;
764         action += ".getStringEx(";
765         action += tag;
766         action += ")";
767 
768 
769         status = U_ZERO_ERROR;
770         UnicodeString string = theBundle.getStringEx(tag, status);
771         if(U_FAILURE(status)) {
772             string.setTo(TRUE, kErrorUChars, kErrorLength);
773         }
774 
775         CONFIRM_UErrorCode(status, expected_resource_status);
776 
777         UnicodeString expected_string(kErrorUChars);
778         if (U_SUCCESS(status)) {
779             expected_string = base;
780         }
781 
782         CONFIRM_EQ(string, expected_string);
783 
784         //--------------------------------------------------------------------------
785         // array   ResourceBundle using the key
786 
787         uprv_strcpy(tag, "array_");
788         uprv_strcat(tag, frag);
789 
790         action = param[i].name;
791         action += ".get(";
792         action += tag;
793         action += ")";
794 
795         int32_t count = kERROR_COUNT;
796         status = U_ZERO_ERROR;
797         ResourceBundle array = theBundle.get(tag, status);
798         CONFIRM_UErrorCode(status,expected_resource_status);
799 
800 
801         if (U_SUCCESS(status))
802         {
803             //confirm the resource type is an array
804             UResType bundleType=array.getType();
805             CONFIRM_EQ(bundleType, URES_ARRAY);
806 
807             count=array.getSize();
808             CONFIRM_GE(count,1);
809 
810             for (j=0; j<count; ++j)
811             {
812                 char buf[32];
813                 expected_string = base;
814                 expected_string += itoa(j,buf);
815                 CONFIRM_EQ(array.getNextString(status),expected_string);
816             }
817 
818         }
819         else
820         {
821             CONFIRM_EQ(count,kERROR_COUNT);
822             //       CONFIRM_EQ((int32_t)(unsigned long)array,(int32_t)0);
823             count = 0;
824         }
825 
826         //--------------------------------------------------------------------------
827         // arrayItem ResourceBundle using the index
828 
829 
830         for (j=0; j<100; ++j)
831         {
832             index = count ? (randi(count * 3) - count) : (randi(200) - 100);
833             status = U_ZERO_ERROR;
834             string = kErrorUChars;
835             ResourceBundle array = theBundle.get(tag, status);
836             if(!U_FAILURE(status)){
837                 UnicodeString t = array.getStringEx(index, status);
838                 if(!U_FAILURE(status)) {
839                    string=t;
840                 }
841             }
842 
843             expected_status = (index >= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR;
844             CONFIRM_UErrorCode(status,expected_status);
845 
846             if (U_SUCCESS(status)){
847                 char buf[32];
848                 expected_string = base;
849                 expected_string += itoa(index,buf);
850             } else {
851                 expected_string = kErrorUChars;
852             }
853                CONFIRM_EQ(string,expected_string);
854 
855         }
856 
857         //--------------------------------------------------------------------------
858         // 2dArray
859 
860         uprv_strcpy(tag, "array_2d_");
861         uprv_strcat(tag, frag);
862 
863         action = param[i].name;
864         action += ".get(";
865         action += tag;
866         action += ")";
867 
868 
869         int32_t row_count = kERROR_COUNT, column_count = kERROR_COUNT;
870         status = U_ZERO_ERROR;
871         ResourceBundle array2d=theBundle.get(tag, status);
872 
873         //const UnicodeString** array2d = theBundle.get2dArray(tag, row_count, column_count, status);
874         CONFIRM_UErrorCode(status,expected_resource_status);
875 
876         if (U_SUCCESS(status))
877         {
878             //confirm the resource type is an 2darray
879             UResType bundleType=array2d.getType();
880             CONFIRM_EQ(bundleType, URES_ARRAY);
881 
882             row_count=array2d.getSize();
883             CONFIRM_GE(row_count,1);
884 
885             for(row=0; row<row_count; ++row){
886                 ResourceBundle tablerow=array2d.get(row, status);
887                 CONFIRM_UErrorCode(status, expected_resource_status);
888                 if(U_SUCCESS(status)){
889                     //confirm the resourcetype of each table row is an array
890                     UResType rowType=tablerow.getType();
891                     CONFIRM_EQ(rowType, URES_ARRAY);
892 
893                     column_count=tablerow.getSize();
894                     CONFIRM_GE(column_count,1);
895 
896                     for (col=0; j<column_count; ++j) {
897                            char buf[32];
898                            expected_string = base;
899                            expected_string += itoa(row,buf);
900                            expected_string += itoa(col,buf);
901                            CONFIRM_EQ(tablerow.getNextString(status),expected_string);
902                     }
903                 }
904             }
905         }else{
906             CONFIRM_EQ(row_count,kERROR_COUNT);
907             CONFIRM_EQ(column_count,kERROR_COUNT);
908              row_count=column_count=0;
909         }
910 
911 
912 
913 
914        //--------------------------------------------------------------------------
915        // 2dArrayItem
916        for (j=0; j<200; ++j)
917        {
918            row = row_count ? (randi(row_count * 3) - row_count) : (randi(200) - 100);
919            col = column_count ? (randi(column_count * 3) - column_count) : (randi(200) - 100);
920            status = U_ZERO_ERROR;
921            string = kErrorUChars;
922            ResourceBundle array2d=theBundle.get(tag, status);
923            if(U_SUCCESS(status)){
924                 ResourceBundle tablerow=array2d.get(row, status);
925                 if(U_SUCCESS(status)) {
926                     UnicodeString t=tablerow.getStringEx(col, status);
927                     if(U_SUCCESS(status)){
928                        string=t;
929                     }
930                 }
931            }
932            expected_status = (row >= 0 && row < row_count && col >= 0 && col < column_count) ?
933                                   expected_resource_status: U_MISSING_RESOURCE_ERROR;
934            CONFIRM_UErrorCode(status,expected_status);
935 
936            if (U_SUCCESS(status)){
937                char buf[32];
938                expected_string = base;
939                expected_string += itoa(row,buf);
940                expected_string += itoa(col,buf);
941            } else {
942                expected_string = kErrorUChars;
943            }
944                CONFIRM_EQ(string,expected_string);
945 
946         }
947 
948         //--------------------------------------------------------------------------
949         // taggedArray
950 
951         uprv_strcpy(tag, "tagged_array_");
952         uprv_strcat(tag, frag);
953 
954         action = param[i].name;
955         action += ".get(";
956         action += tag;
957         action += ")";
958 
959         int32_t         tag_count;
960         status = U_ZERO_ERROR;
961 
962         ResourceBundle tags=theBundle.get(tag, status);
963         CONFIRM_UErrorCode(status, expected_resource_status);
964 
965         if (U_SUCCESS(status)) {
966             UResType bundleType=tags.getType();
967             CONFIRM_EQ(bundleType, URES_TABLE);
968 
969             tag_count=tags.getSize();
970             CONFIRM_GE((int32_t)tag_count, (int32_t)0);
971 
972             for(index=0; index <tag_count; index++){
973                 ResourceBundle tagelement=tags.get(index, status);
974                 UnicodeString key=tagelement.getKey();
975                 UnicodeString value=tagelement.getNextString(status);
976                 logln("tag = " + key + ", value = " + value );
977                 if(key.startsWith("tag") && value.startsWith(base)){
978                     record_pass();
979                 }else{
980                     record_fail();
981                 }
982 
983             }
984 
985             for(index=0; index <tag_count; index++){
986                 ResourceBundle tagelement=tags.get(index, status);
987                 const char *tkey=NULL;
988                 UnicodeString value=tagelement.getNextString(&tkey, status);
989                 UnicodeString key(tkey);
990                 logln("tag = " + key + ", value = " + value );
991                 if(value.startsWith(base)){
992                     record_pass();
993                 }else{
994                     record_fail();
995                 }
996             }
997 
998         }else{
999             tag_count=0;
1000         }
1001 
1002 
1003 
1004 
1005         //--------------------------------------------------------------------------
1006         // taggedArrayItem
1007 
1008         action = param[i].name;
1009         action += ".get(";
1010         action += tag;
1011         action += ")";
1012 
1013         count = 0;
1014         for (index=-20; index<20; ++index)
1015         {
1016             char buf[32];
1017             status = U_ZERO_ERROR;
1018             string = kErrorUChars;
1019             char item_tag[8];
1020             uprv_strcpy(item_tag, "tag");
1021             uprv_strcat(item_tag, itoa(index,buf));
1022             ResourceBundle tags=theBundle.get(tag, status);
1023             if(U_SUCCESS(status)){
1024                 ResourceBundle tagelement=tags.get(item_tag, status);
1025                 if(!U_FAILURE(status)){
1026                     UResType elementType=tagelement.getType();
1027                     CONFIRM_EQ(elementType, (int32_t)URES_STRING);
1028                     const char* key=tagelement.getKey();
1029                     CONFIRM_EQ((UnicodeString)key, (UnicodeString)item_tag);
1030                     UnicodeString t=tagelement.getString(status);
1031                     if(!U_FAILURE(status)){
1032                         string=t;
1033                     }
1034                 }
1035                 if (index < 0) {
1036                     CONFIRM_UErrorCode(status,U_MISSING_RESOURCE_ERROR);
1037                 }
1038                 else{
1039                    if (status != U_MISSING_RESOURCE_ERROR) {
1040                        count++;
1041                        expected_string = base;
1042                        expected_string += buf;
1043                        CONFIRM_EQ(string,expected_string);
1044                    }
1045                 }
1046             }
1047 
1048         }
1049         CONFIRM_EQ(count, tag_count);
1050 
1051     }
1052     return (UBool)(failOrig == fail);
1053 }
1054 
1055 void
record_pass()1056 NewResourceBundleTest::record_pass()
1057 {
1058   ++pass;
1059 }
1060 void
record_fail()1061 NewResourceBundleTest::record_fail()
1062 {
1063   err();
1064   ++fail;
1065 }
1066 
1067 
1068 void
TestNewTypes()1069 NewResourceBundleTest::TestNewTypes() {
1070     char action[256];
1071     const char* testdatapath;
1072     UErrorCode status = U_ZERO_ERROR;
1073     uint8_t *binResult = NULL;
1074     int32_t len = 0;
1075     int32_t i = 0;
1076     int32_t intResult = 0;
1077     uint32_t uintResult = 0;
1078     UChar expected[] = { 'a','b','c','\0','d','e','f' };
1079     const char* expect ="tab:\t cr:\r ff:\f newline:\n backslash:\\\\ quote=\\\' doubleQuote=\\\" singlequoutes=''";
1080     UChar uExpect[200];
1081 
1082     testdatapath=loadTestData(status);
1083 
1084     if(U_FAILURE(status))
1085     {
1086         dataerrln("Could not load testdata.dat %s \n",u_errorName(status));
1087         return;
1088     }
1089 
1090     ResourceBundle theBundle(testdatapath, "testtypes", status);
1091     ResourceBundle bundle(testdatapath, Locale("te_IN"),status);
1092 
1093     UnicodeString emptyStr = theBundle.getStringEx("emptystring", status);
1094     if(emptyStr.length() != 0) {
1095       logln("Empty string returned invalid value\n");
1096     }
1097 
1098     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1099 
1100     /* This test reads the string "abc\u0000def" from the bundle   */
1101     /* if everything is working correctly, the size of this string */
1102     /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/
1103 
1104     strcpy(action, "getting and testing of string with embeded zero");
1105     ResourceBundle res = theBundle.get("zerotest", status);
1106     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1107     CONFIRM_EQ(res.getType(), URES_STRING);
1108     UnicodeString zeroString=res.getString(status);
1109     len = zeroString.length();
1110     if(U_SUCCESS(status)){
1111         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1112         CONFIRM_EQ(len, 7);
1113         CONFIRM_NE(len, 3);
1114     }
1115     for(i=0;i<len;i++){
1116         if(zeroString[i]!= expected[i]){
1117             logln("Output didnot match Expected: \\u%4X Got: \\u%4X", expected[i], zeroString[i]);
1118         }
1119     }
1120 
1121     strcpy(action, "getting and testing of binary type");
1122     res = theBundle.get("binarytest", status);
1123     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1124     CONFIRM_EQ(res.getType(), URES_BINARY);
1125     binResult=(uint8_t*)res.getBinary(len, status);
1126     if(U_SUCCESS(status)){
1127         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1128         CONFIRM_EQ(len, 15);
1129         for(i = 0; i<15; i++) {
1130             CONFIRM_EQ(binResult[i], i);
1131         }
1132     }
1133 
1134     strcpy(action, "getting and testing of imported binary type");
1135     res = theBundle.get("importtest",status);
1136     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1137     CONFIRM_EQ(res.getType(), URES_BINARY);
1138     binResult=(uint8_t*)res.getBinary(len, status);
1139     if(U_SUCCESS(status)){
1140         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1141         CONFIRM_EQ(len, 15);
1142         for(i = 0; i<15; i++) {
1143             CONFIRM_EQ(binResult[i], i);
1144         }
1145     }
1146 
1147     strcpy(action, "getting and testing of integer types");
1148     res = theBundle.get("one",  status);
1149     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1150     CONFIRM_EQ(res.getType(), URES_INT);
1151     intResult=res.getInt(status);
1152     uintResult = res.getUInt(status);
1153     if(U_SUCCESS(status)){
1154         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1155         CONFIRM_EQ(uintResult, (uint32_t)intResult);
1156         CONFIRM_EQ(intResult, 1);
1157     }
1158 
1159     strcpy(action, "getting minusone");
1160     res = theBundle.get((const char*)"minusone", status);
1161     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1162     CONFIRM_EQ(res.getType(), URES_INT);
1163     intResult=res.getInt(status);
1164     uintResult = res.getUInt(status);
1165     if(U_SUCCESS(status)){
1166         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1167         CONFIRM_EQ(uintResult, 0x0FFFFFFF); /* a 28 bit integer */
1168         CONFIRM_EQ(intResult, -1);
1169         CONFIRM_NE(uintResult, (uint32_t)intResult);
1170     }
1171 
1172     strcpy(action, "getting plusone");
1173     res = theBundle.get("plusone",status);
1174     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1175     CONFIRM_EQ(res.getType(), URES_INT);
1176     intResult=res.getInt(status);
1177     uintResult = res.getUInt(status);
1178     if(U_SUCCESS(status)){
1179         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1180         CONFIRM_EQ(uintResult, (uint32_t)intResult);
1181         CONFIRM_EQ(intResult, 1);
1182     }
1183 
1184     res = theBundle.get("onehundredtwentythree",status);
1185     CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1186     CONFIRM_EQ(res.getType(), URES_INT);
1187     intResult=res.getInt(status);
1188     if(U_SUCCESS(status)){
1189         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1190         CONFIRM_EQ(intResult, 123);
1191     }
1192 
1193     /* this tests if escapes are preserved or not */
1194     {
1195         UnicodeString str = theBundle.getStringEx("testescape",status);
1196         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1197         if(U_SUCCESS(status)){
1198             u_charsToUChars(expect,uExpect,(int32_t)uprv_strlen(expect)+1);
1199             if(str.compare(uExpect)!=0){
1200                 errln("Did not get the expected string for testescape expected. Expected : "
1201                     +UnicodeString(uExpect )+ " Got: " + str);
1202             }
1203         }
1204     }
1205     /* test for jitterbug#1435 */
1206     {
1207         UnicodeString str = theBundle.getStringEx("test_underscores",status);
1208         expect ="test message ....";
1209         CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1210         u_charsToUChars(expect,uExpect,(int32_t)uprv_strlen(expect)+1);
1211         if(str.compare(uExpect)!=0){
1212             errln("Did not get the expected string for test_underscores.\n");
1213         }
1214     }
1215 
1216 
1217 }
1218 
1219 void
TestGetByFallback()1220 NewResourceBundleTest::TestGetByFallback() {
1221     UErrorCode status = U_ZERO_ERROR;
1222 
1223     ResourceBundle heRes(NULL, "he", status);
1224 
1225     heRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("DateTime", status);
1226     if(U_SUCCESS(status)) {
1227         errln("he locale's Islamic-civil DateTime resource exists. How did it get here?\n");
1228     }
1229     status = U_ZERO_ERROR;
1230 
1231     heRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("eras", status);
1232     if(U_FAILURE(status)) {
1233         dataerrln("Didn't get Islamic Eras. I know they are there! - %s", u_errorName(status));
1234     }
1235     status = U_ZERO_ERROR;
1236 
1237     ResourceBundle rootRes(NULL, "root", status);
1238     rootRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("DateTime", status);
1239     if(U_SUCCESS(status)) {
1240         errln("Root's Islamic-civil's DateTime resource exists. How did it get here?\n");
1241     }
1242     status = U_ZERO_ERROR;
1243 
1244 }
1245 
1246 
1247 #define REQUIRE_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
1248     if (status.errIfFailureAndReset("line %d", __LINE__)) { \
1249         return; \
1250     } \
1251 } UPRV_BLOCK_MACRO_END
1252 
1253 #define REQUIRE_ERROR(expected, status) UPRV_BLOCK_MACRO_BEGIN { \
1254     if (!status.expectErrorAndReset(expected, "line %d", __LINE__)) { \
1255         return; \
1256     } \
1257 } UPRV_BLOCK_MACRO_END
1258 
1259 /**
1260  * Tests the --filterDir option in genrb.
1261  *
1262  * Input resource text file: test/testdata/filtertest.txt
1263  * Input filter rule file: test/testdata/filters/filtertest.txt
1264  *
1265  * The resource bundle should contain no keys matched by the filter
1266  * and should contain all other keys.
1267  */
TestFilter()1268 void NewResourceBundleTest::TestFilter() {
1269     IcuTestErrorCode status(*this, "TestFilter");
1270 
1271     ResourceBundle rb(loadTestData(status), "filtertest", status);
1272     REQUIRE_SUCCESS(status);
1273     assertEquals("rb", rb.getType(), URES_TABLE);
1274 
1275     ResourceBundle alabama = rb.get("alabama", status);
1276     REQUIRE_SUCCESS(status);
1277     assertEquals("alabama", alabama.getType(), URES_TABLE);
1278 
1279     {
1280         ResourceBundle alaska = alabama.get("alaska", status);
1281         REQUIRE_SUCCESS(status);
1282         assertEquals("alaska", alaska.getType(), URES_TABLE);
1283 
1284         {
1285             ResourceBundle arizona = alaska.get("arizona", status);
1286             REQUIRE_SUCCESS(status);
1287             assertEquals("arizona", arizona.getType(), URES_STRING);
1288             assertEquals("arizona", u"arkansas", arizona.getString(status));
1289             REQUIRE_SUCCESS(status);
1290 
1291             // Filter: california should not be included
1292             ResourceBundle california = alaska.get("california", status);
1293             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1294         }
1295 
1296         // Filter: connecticut should not be included
1297         ResourceBundle connecticut = alabama.get("connecticut", status);
1298         REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1299     }
1300 
1301     ResourceBundle fornia = rb.get("fornia", status);
1302     REQUIRE_SUCCESS(status);
1303     assertEquals("fornia", fornia.getType(), URES_TABLE);
1304 
1305     {
1306         // Filter: hawaii should not be included based on parent inheritance
1307         ResourceBundle hawaii = fornia.get("hawaii", status);
1308         REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1309 
1310         // Filter: illinois should not be included based on direct rule
1311         ResourceBundle illinois = fornia.get("illinois", status);
1312         REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1313     }
1314 
1315     ResourceBundle mississippi = rb.get("mississippi", status);
1316     REQUIRE_SUCCESS(status);
1317     assertEquals("mississippi", mississippi.getType(), URES_TABLE);
1318 
1319     {
1320         ResourceBundle louisiana = mississippi.get("louisiana", status);
1321         REQUIRE_SUCCESS(status);
1322         assertEquals("louisiana", louisiana.getType(), URES_TABLE);
1323 
1324         {
1325             ResourceBundle maine = louisiana.get("maine", status);
1326             REQUIRE_SUCCESS(status);
1327             assertEquals("maine", maine.getType(), URES_STRING);
1328             assertEquals("maine", u"maryland", maine.getString(status));
1329             REQUIRE_SUCCESS(status);
1330 
1331             ResourceBundle iowa = louisiana.get("iowa", status);
1332             REQUIRE_SUCCESS(status);
1333             assertEquals("iowa", iowa.getType(), URES_STRING);
1334             assertEquals("iowa", u"kansas", iowa.getString(status));
1335             REQUIRE_SUCCESS(status);
1336 
1337             // Filter: missouri should not be included
1338             ResourceBundle missouri = louisiana.get("missouri", status);
1339             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1340         }
1341 
1342         ResourceBundle michigan = mississippi.get("michigan", status);
1343         REQUIRE_SUCCESS(status);
1344         assertEquals("michigan", michigan.getType(), URES_TABLE);
1345 
1346         {
1347             ResourceBundle maine = michigan.get("maine", status);
1348             REQUIRE_SUCCESS(status);
1349             assertEquals("maine", maine.getType(), URES_STRING);
1350             assertEquals("maine", u"minnesota", maine.getString(status));
1351             REQUIRE_SUCCESS(status);
1352 
1353             // Filter: iowa should not be included
1354             ResourceBundle iowa = michigan.get("iowa", status);
1355             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1356 
1357             ResourceBundle missouri = michigan.get("missouri", status);
1358             REQUIRE_SUCCESS(status);
1359             assertEquals("missouri", missouri.getType(), URES_STRING);
1360             assertEquals("missouri", u"nebraska", missouri.getString(status));
1361             REQUIRE_SUCCESS(status);
1362         }
1363 
1364         ResourceBundle nevada = mississippi.get("nevada", status);
1365         REQUIRE_SUCCESS(status);
1366         assertEquals("nevada", nevada.getType(), URES_TABLE);
1367 
1368         {
1369             ResourceBundle maine = nevada.get("maine", status);
1370             REQUIRE_SUCCESS(status);
1371             assertEquals("maine", maine.getType(), URES_STRING);
1372             assertEquals("maine", u"new-hampshire", maine.getString(status));
1373             REQUIRE_SUCCESS(status);
1374 
1375             // Filter: iowa should not be included
1376             ResourceBundle iowa = nevada.get("iowa", status);
1377             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1378 
1379             // Filter: missouri should not be included
1380             ResourceBundle missouri = nevada.get("missouri", status);
1381             REQUIRE_ERROR(U_MISSING_RESOURCE_ERROR, status);
1382         }
1383     }
1384 
1385     // Filter: northCarolina should be included based on direct rule,
1386     // and so should its child, northDakota
1387     ResourceBundle northCarolina = rb.get("northCarolina", status);
1388     REQUIRE_SUCCESS(status);
1389     assertEquals("northCarolina", northCarolina.getType(), URES_TABLE);
1390 
1391     {
1392         ResourceBundle northDakota = northCarolina.get("northDakota", status);
1393         REQUIRE_SUCCESS(status);
1394         assertEquals("northDakota", northDakota.getType(), URES_STRING);
1395         assertEquals("northDakota", u"west-virginia", northDakota.getString(status));
1396         REQUIRE_SUCCESS(status);
1397     }
1398 }
1399 
1400 /*
1401  * The following test for ICU-20706 has infinite loops on certain inputs for
1402  * locales and calendars.  In order to unblock the build (ICU-21055), those
1403  * specific values are temporarily removed.
1404  * The issue of the infinite loops and its blocking dependencies were captured
1405  * in ICU-21080.
1406  */
1407 
TestIntervalAliasFallbacks()1408 void NewResourceBundleTest::TestIntervalAliasFallbacks() {
1409     const char* locales[] = {
1410         // Thee will not cause infinity loop
1411         "en",
1412         "ja",
1413 
1414         // These will cause infinity loop
1415 #if 0
1416         "fr_CA",
1417         "en_150",
1418         "es_419",
1419         "id",
1420         "in",
1421         "pl",
1422         "pt_PT",
1423         "sr_ME",
1424         "zh_Hant",
1425         "zh_Hant_TW",
1426         "zh_TW",
1427 #endif
1428     };
1429     const char* calendars[] = {
1430         // These won't cause infinity loop
1431         "gregorian",
1432         "chinese",
1433 
1434         // These will cause infinity loop
1435 #if 0
1436         "islamic",
1437         "islamic-civil",
1438         "islamic-tbla",
1439         "islamic-umalqura",
1440         "ethiopic-amete-alem",
1441         "islamic-rgsa",
1442         "japanese",
1443         "roc",
1444 #endif
1445     };
1446 
1447     for (int lidx = 0; lidx < UPRV_LENGTHOF(locales); lidx++) {
1448         UErrorCode status = U_ZERO_ERROR;
1449         UResourceBundle *rb = ures_open(NULL, locales[lidx], &status);
1450         if (U_FAILURE(status)) {
1451             errln("Cannot open bundle for locale %s", locales[lidx]);
1452             break;
1453         }
1454         for (int cidx = 0; cidx < UPRV_LENGTHOF(calendars); cidx++) {
1455             CharString key;
1456             key.append("calendar/", status);
1457             key.append(calendars[cidx], status);
1458             key.append("/intervalFormats/fallback", status);
1459             if (! logKnownIssue("20400")) {
1460                 int32_t resStrLen = 0;
1461                 ures_getStringByKeyWithFallback(rb, key.data(), &resStrLen, &status);
1462             }
1463             if (U_FAILURE(status)) {
1464                 errln("Cannot ures_getStringByKeyWithFallback('%s') on locale %s",
1465                       key.data(), locales[lidx]);
1466                 break;
1467             }
1468         }
1469         ures_close(rb);
1470     }
1471 }
1472 
1473 #if U_ENABLE_TRACING
1474 
1475 static std::vector<std::string> gResourcePathsTraced;
1476 static std::vector<std::string> gDataFilesTraced;
1477 static std::vector<std::string> gBundlesTraced;
1478 
traceData(const void *,int32_t fnNumber,int32_t,const char *,va_list args)1479 static void U_CALLCONV traceData(
1480         const void*,
1481         int32_t fnNumber,
1482         int32_t,
1483         const char *,
1484         va_list args) {
1485 
1486     // NOTE: Whether this test is run in isolation affects whether or not
1487     // *.res files are opened. For stability, ignore *.res file opens.
1488 
1489     if (fnNumber == UTRACE_UDATA_RESOURCE) {
1490         va_arg(args, const char*); // type
1491         va_arg(args, const char*); // file
1492         const char* resourcePath = va_arg(args, const char*);
1493         gResourcePathsTraced.push_back(resourcePath);
1494     } else if (fnNumber == UTRACE_UDATA_BUNDLE) {
1495         const char* filePath = va_arg(args, const char*);
1496         gBundlesTraced.push_back(filePath);
1497     } else if (fnNumber == UTRACE_UDATA_DATA_FILE) {
1498         const char* filePath = va_arg(args, const char*);
1499         gDataFilesTraced.push_back(filePath);
1500     } else if (fnNumber == UTRACE_UDATA_RES_FILE) {
1501         // ignore
1502     }
1503 }
1504 
TestTrace()1505 void NewResourceBundleTest::TestTrace() {
1506     IcuTestErrorCode status(*this, "TestTrace");
1507 
1508     assertEquals("Start position stability coverage", 0x3000, UTRACE_UDATA_START);
1509 
1510     const void* context;
1511     utrace_setFunctions(context, nullptr, nullptr, traceData);
1512     utrace_setLevel(UTRACE_VERBOSE);
1513 
1514     {
1515         LocalPointer<BreakIterator> brkitr(BreakIterator::createWordInstance("zh-CN", status));
1516 
1517         assertEquals("Should touch expected resource paths",
1518             { "/boundaries", "/boundaries/word", "/boundaries/word" },
1519             gResourcePathsTraced);
1520         assertEquals("Should touch expected resource bundles",
1521             { U_ICUDATA_NAME "-brkitr/zh.res" },
1522             gBundlesTraced);
1523         assertEquals("Should touch expected data files",
1524             { U_ICUDATA_NAME "-brkitr/word.brk" },
1525             gDataFilesTraced);
1526         gResourcePathsTraced.clear();
1527         gDataFilesTraced.clear();
1528         gBundlesTraced.clear();
1529     }
1530 
1531     {
1532         ucurr_getDefaultFractionDigits(u"USD", status);
1533 
1534         assertEquals("Should touch expected resource paths",
1535             { "/CurrencyMeta", "/CurrencyMeta/DEFAULT", "/CurrencyMeta/DEFAULT" },
1536             gResourcePathsTraced);
1537         assertEquals("Should touch expected resource bundles",
1538             { U_ICUDATA_NAME "-curr/supplementalData.res" },
1539             gBundlesTraced);
1540         assertEquals("Should touch expected data files",
1541             { },
1542             gDataFilesTraced);
1543         gResourcePathsTraced.clear();
1544         gDataFilesTraced.clear();
1545         gBundlesTraced.clear();
1546     }
1547 
1548     utrace_setFunctions(context, nullptr, nullptr, nullptr);
1549 }
1550 
1551 #endif
1552 
1553 //eof
1554 
1555