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