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