1// Copyright (C) 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 "cmemory.h"
11#include "cstring.h"
12#include "unicode/unistr.h"
13#include "unicode/resbund.h"
14#include "restsnew.h"
15
16#include <stdlib.h>
17#include <time.h>
18#include <string.h>
19#include <limits.h>
20
21//***************************************************************************************
22
23static const UChar kErrorUChars[] = { 0x45, 0x52, 0x52, 0x4f, 0x52, 0 };
24static const int32_t kErrorLength = 5;
25static const int32_t kERROR_COUNT = -1234567;
26
27//***************************************************************************************
28
29enum E_Where
30{
31    e_Root,
32    e_te,
33    e_te_IN,
34    e_Where_count
35};
36
37//***************************************************************************************
38
39#define CONFIRM_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of " + (expected)); }
40#define CONFIRM_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x >= " + (expected)); }
41#define CONFIRM_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (actual) + (UnicodeString)" instead of x != " + (expected)); }
42
43#define CONFIRM_UErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); errln(action + (UnicodeString)" returned " + (UnicodeString)u_errorName(actual) + (UnicodeString)" instead of " + (UnicodeString)u_errorName(expected)); }
44
45//***************************************************************************************
46
47/**
48 * Convert an integer, positive or negative, to a character string radix 10.
49 */
50static char*
51itoa(int32_t i, char* buf)
52{
53    char* result = buf;
54
55    // Handle negative
56    if (i < 0)
57    {
58        *buf++ = '-';
59        i = -i;
60    }
61
62    // Output digits in reverse order
63    char* p = buf;
64    do
65    {
66        *p++ = (char)('0' + (i % 10));
67        i /= 10;
68    }
69    while (i);
70    *p-- = 0;
71
72    // Reverse the string
73    while (buf < p)
74    {
75        char c = *buf;
76        *buf++ = *p;
77        *p-- = c;
78    }
79
80    return result;
81}
82
83
84
85//***************************************************************************************
86
87// Array of our test objects
88
89static struct
90{
91    const char* name;
92    Locale *locale;
93    UErrorCode expected_constructor_status;
94    E_Where where;
95    UBool like[e_Where_count];
96    UBool inherits[e_Where_count];
97}
98param[] =
99{
100    // "te" means test
101    // "IN" means inherits
102    // "NE" or "ne" means "does not exist"
103
104    { "root",       0,   U_ZERO_ERROR,             e_Root,      { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } },
105    { "te",         0,   U_ZERO_ERROR,             e_te,        { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE  } },
106    { "te_IN",      0,   U_ZERO_ERROR,             e_te_IN,     { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE   } },
107    { "te_NE",      0,   U_USING_FALLBACK_WARNING, e_te,        { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE  } },
108    { "te_IN_NE",   0,   U_USING_FALLBACK_WARNING, e_te_IN,     { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE   } },
109    { "ne",         0,   U_USING_DEFAULT_WARNING,  e_Root,      { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }
110};
111
112static int32_t bundles_count = UPRV_LENGTHOF(param);
113
114//***************************************************************************************
115
116/**
117 * Return a random unsigned long l where 0N <= l <= ULONG_MAX.
118 */
119
120static uint32_t
121randul()
122{
123    static UBool initialized = FALSE;
124    if (!initialized)
125    {
126        srand((unsigned)time(NULL));
127        initialized = TRUE;
128    }
129    // Assume rand has at least 12 bits of precision
130    uint32_t l = 0;
131    for (uint32_t i=0; i<sizeof(l); ++i)
132        ((char*)&l)[i] = (char)((rand() & 0x0FF0) >> 4);
133    return l;
134}
135
136/**
137 * Return a random double x where 0.0 <= x < 1.0.
138 */
139static double
140randd()
141{
142    return (double)(randul() / ULONG_MAX);
143}
144
145/**
146 * Return a random integer i where 0 <= i < n.
147 */
148static int32_t randi(int32_t n)
149{
150    return (int32_t)(randd() * n);
151}
152
153//***************************************************************************************
154
155/*
156 Don't use more than one of these at a time because of the Locale names
157*/
158NewResourceBundleTest::NewResourceBundleTest()
159: pass(0),
160  fail(0)
161{
162    if (param[5].locale == NULL) {
163        param[0].locale = new Locale("root");
164        param[1].locale = new Locale("te");
165        param[2].locale = new Locale("te", "IN");
166        param[3].locale = new Locale("te", "NE");
167        param[4].locale = new Locale("te", "IN", "NE");
168        param[5].locale = new Locale("ne");
169    }
170}
171
172NewResourceBundleTest::~NewResourceBundleTest()
173{
174    if (param[5].locale) {
175        int idx;
176        for (idx = 0; idx < UPRV_LENGTHOF(param); idx++) {
177            delete param[idx].locale;
178            param[idx].locale = NULL;
179        }
180    }
181}
182
183void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
184{
185    if (exec) logln("TestSuite ResourceBundleTest: ");
186    switch (index) {
187#if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
188    case 0: name = "TestResourceBundles"; if (exec) TestResourceBundles(); break;
189    case 1: name = "TestConstruction"; if (exec) TestConstruction(); break;
190    case 2: name = "TestIteration"; if (exec) TestIteration(); break;
191    case 3: name = "TestOtherAPI";  if(exec) TestOtherAPI(); break;
192    case 4: name = "TestNewTypes";  if(exec) TestNewTypes(); break;
193#else
194    case 0: case 1: case 2: case 3: case 4: name = "skip"; break;
195#endif
196
197    case 5: name = "TestGetByFallback";  if(exec) TestGetByFallback(); break;
198        default: name = ""; break; //needed to end loop
199    }
200}
201
202//***************************************************************************************
203
204void
205NewResourceBundleTest::TestResourceBundles()
206{
207    UErrorCode status = U_ZERO_ERROR;
208    loadTestData(status);
209    if(U_FAILURE(status))
210    {
211        dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(status)));
212        return;
213    }
214
215    /* Make sure that users using te_IN for the default locale don't get test failures. */
216    Locale originalDefault;
217    if (Locale::getDefault() == Locale("te_IN")) {
218        Locale::setDefault(Locale("en_US"), status);
219    }
220
221    testTag("only_in_Root", TRUE, FALSE, FALSE);
222    testTag("only_in_te", FALSE, TRUE, FALSE);
223    testTag("only_in_te_IN", FALSE, FALSE, TRUE);
224    testTag("in_Root_te", TRUE, TRUE, FALSE);
225    testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE);
226    testTag("in_Root_te_IN", TRUE, FALSE, TRUE);
227    testTag("in_te_te_IN", FALSE, TRUE, TRUE);
228    testTag("nonexistent", FALSE, FALSE, FALSE);
229    logln("Passed: %d\nFailed: %d", pass, fail);
230
231    /* Restore the default locale for the other tests. */
232    Locale::setDefault(originalDefault, status);
233}
234
235void
236NewResourceBundleTest::TestConstruction()
237{
238    UErrorCode   err = U_ZERO_ERROR;
239    Locale       locale("te", "IN");
240
241    const char* testdatapath;
242    testdatapath=loadTestData(err);
243    if(U_FAILURE(err))
244    {
245        dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err)));
246        return;
247    }
248
249    /* Make sure that users using te_IN for the default locale don't get test failures. */
250    Locale originalDefault;
251    if (Locale::getDefault() == Locale("te_IN")) {
252        Locale::setDefault(Locale("en_US"), err);
253    }
254
255    ResourceBundle  test1((UnicodeString)testdatapath, err);
256    ResourceBundle  test2(testdatapath, locale, err);
257
258    UnicodeString   result1;
259    UnicodeString   result2;
260
261    result1 = test1.getStringEx("string_in_Root_te_te_IN", err);
262    result2 = test2.getStringEx("string_in_Root_te_te_IN", err);
263    if (U_FAILURE(err)) {
264        errln("Something threw an error in TestConstruction()");
265        return;
266    }
267
268    logln("for string_in_Root_te_te_IN, root.txt had " + result1);
269    logln("for string_in_Root_te_te_IN, te_IN.txt had " + result2);
270
271    if (result1 != "ROOT" || result2 != "TE_IN") {
272        errln("Construction test failed; run verbose for more information");
273    }
274
275    const char* version1;
276    const char* version2;
277
278    version1 = test1.getVersionNumber();
279    version2 = test2.getVersionNumber();
280
281    char *versionID1 = new char[1 + strlen(U_ICU_VERSION) + strlen(version1)]; // + 1 for zero byte
282    char *versionID2 = new char[1 + strlen(U_ICU_VERSION) + strlen(version2)]; // + 1 for zero byte
283
284    strcpy(versionID1, "44.0");  // hardcoded, please change if the default.txt file or ResourceBundle::kVersionSeparater is changed.
285
286    strcpy(versionID2, "55.0");  // hardcoded, please change if the te_IN.txt file or ResourceBundle::kVersionSeparater is changed.
287
288    logln(UnicodeString("getVersionNumber on default.txt returned ") + version1 + UnicodeString(" Expect: " ) + versionID1);
289    logln(UnicodeString("getVersionNumber on te_IN.txt returned ") + version2 + UnicodeString(" Expect: " ) + versionID2);
290
291    if (strcmp(version1, versionID1) != 0) {
292        errln("getVersionNumber(version1) failed. %s != %s", version1, versionID1);
293    }
294    if (strcmp(version2, versionID2) != 0) {
295        errln("getVersionNumber(version2) failed. %s != %s", version2, versionID2);
296    }
297    delete[] versionID1;
298    delete[] versionID2;
299
300    /* Restore the default locale for the other tests. */
301    Locale::setDefault(originalDefault, err);
302}
303
304void
305NewResourceBundleTest::TestIteration()
306{
307    UErrorCode   err = U_ZERO_ERROR;
308    const char* testdatapath;
309    const char* data[]={
310        "string_in_Root_te_te_IN",   "1",
311        "array_in_Root_te_te_IN",    "5",
312        "array_2d_in_Root_te_te_IN", "4",
313    };
314
315    Locale       *locale=new Locale("te_IN");
316
317    testdatapath=loadTestData(err);
318    if(U_FAILURE(err))
319    {
320        dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err)));
321        return;
322    }
323
324    ResourceBundle  test1(testdatapath, *locale, err);
325    if(U_FAILURE(err)){
326        errln("Construction failed");
327    }
328    uint32_t i;
329    int32_t count, row=0, col=0;
330    char buf[5];
331    UnicodeString expected;
332    UnicodeString element("TE_IN");
333    UnicodeString action;
334
335
336    for(i=0; i<UPRV_LENGTHOF(data); i=i+2){
337        action = "te_IN";
338        action +=".get(";
339        action += data[i];
340        action +=", err)";
341        err=U_ZERO_ERROR;
342        ResourceBundle bundle = test1.get(data[i], err);
343        if(!U_FAILURE(err)){
344            action = "te_IN";
345            action +=".getKey()";
346
347            CONFIRM_EQ((UnicodeString)bundle.getKey(), (UnicodeString)data[i]);
348
349            count=0;
350            row=0;
351            while(bundle.hasNext()){
352                action = data[i];
353                action +=".getNextString(err)";
354                row=count;
355                UnicodeString got=bundle.getNextString(err);
356                if(U_SUCCESS(err)){
357                    expected=element;
358                    if(bundle.getSize() > 1){
359                        CONFIRM_EQ(bundle.getType(), URES_ARRAY);
360                        expected+=itoa(row, buf);
361                        ResourceBundle rowbundle=bundle.get(row, err);
362                        if(!U_FAILURE(err) && rowbundle.getSize()>1){
363                            col=0;
364                            while(rowbundle.hasNext()){
365                                expected=element;
366                                got=rowbundle.getNextString(err);
367                                if(!U_FAILURE(err)){
368                                    expected+=itoa(row, buf);
369                                    expected+=itoa(col, buf);
370                                    col++;
371                                    CONFIRM_EQ(got, expected);
372                                }
373                            }
374                            CONFIRM_EQ(col, rowbundle.getSize());
375                        }
376                    }
377                    else{
378                        CONFIRM_EQ(bundle.getType(), (int32_t)URES_STRING);
379                    }
380                }
381                CONFIRM_EQ(got, expected);
382                count++;
383            }
384            action = data[i];
385            action +=".getSize()";
386            CONFIRM_EQ(bundle.getSize(), count);
387            CONFIRM_EQ(count, atoi(data[i+1]));
388            //after reaching the end
389            err=U_ZERO_ERROR;
390            ResourceBundle errbundle=bundle.getNext(err);
391            action = "After reaching the end of the Iterator:-  ";
392            action +=data[i];
393            action +=".getNext()";
394            CONFIRM_NE(err, (int32_t)U_ZERO_ERROR);
395            CONFIRM_EQ(u_errorName(err), u_errorName(U_INDEX_OUTOFBOUNDS_ERROR));
396            //reset the iterator
397            err = U_ZERO_ERROR;
398            bundle.resetIterator();
399         /*  The following code is causing a crash
400         ****CRASH******
401         */
402
403            bundle.getNext(err);
404            if(U_FAILURE(err)){
405                errln("ERROR: getNext()  throw an error");
406            }
407        }
408    }
409    delete locale;
410}
411
412// TODO: add operator== and != to ResourceBundle
413static UBool
414equalRB(ResourceBundle &a, ResourceBundle &b) {
415    UResType type;
416    UErrorCode status;
417
418    type=a.getType();
419    status=U_ZERO_ERROR;
420    return
421        type==b.getType() &&
422        a.getLocale()==b.getLocale() &&
423        0==strcmp(a.getName(), b.getName()) &&
424        type==URES_STRING ?
425            a.getString(status)==b.getString(status) :
426            type==URES_INT ?
427                a.getInt(status)==b.getInt(status) :
428                TRUE;
429}
430
431void
432NewResourceBundleTest::TestOtherAPI(){
433    UErrorCode   err = U_ZERO_ERROR;
434    const char* testdatapath=loadTestData(err);
435    UnicodeString tDataPathUS = UnicodeString(testdatapath, "");
436
437    if(U_FAILURE(err))
438    {
439        dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err)));
440        return;
441    }
442
443    /* Make sure that users using te_IN for the default locale don't get test failures. */
444    Locale originalDefault;
445    if (Locale::getDefault() == Locale("te_IN")) {
446        Locale::setDefault(Locale("en_US"), err);
447    }
448
449    Locale       *locale=new Locale("te_IN");
450
451    ResourceBundle test0(tDataPathUS, *locale, err);
452    if(U_FAILURE(err)){
453        errln("Construction failed");
454        return;
455    }
456
457    ResourceBundle  test1(testdatapath, *locale, err);
458    if(U_FAILURE(err)){
459        errln("Construction failed");
460        return;
461    }
462
463    logln("Testing getLocale()\n");
464    if(strcmp(test1.getLocale().getName(), locale->getName()) !=0 ){
465        errln("FAIL: ResourceBundle::getLocale() failed\n");
466    }
467
468    delete locale;
469
470    logln("Testing ResourceBundle(UErrorCode)\n");
471    ResourceBundle defaultresource(err);
472    ResourceBundle explicitdefaultresource(NULL, Locale::getDefault(), err);
473    if(U_FAILURE(err)){
474        errcheckln(err, "Construction of default resourcebundle failed - %s", u_errorName(err));
475        return;
476    }
477    // You can't compare the default locale to the resolved locale in the
478    // resource bundle due to aliasing, keywords in the default locale
479    // or the chance that the machine running these tests is using a locale
480    // that isn't available in ICU.
481    if(strcmp(defaultresource.getLocale().getName(), explicitdefaultresource.getLocale().getName()) != 0){
482        errln("Construction of default resourcebundle didn't take the defaultlocale. Expected %s Got %s err=%s\n",
483            explicitdefaultresource.getLocale().getName(), defaultresource.getLocale().getName(), u_errorName(err));
484    }
485
486
487    ResourceBundle copyRes(defaultresource);
488    if(strcmp(copyRes.getName(), defaultresource.getName() ) !=0  ||
489        strcmp(test1.getName(), defaultresource.getName() ) ==0 ||
490        strcmp(copyRes.getLocale().getName(), defaultresource.getLocale().getName() ) !=0  ||
491        strcmp(test1.getLocale().getName(), defaultresource.getLocale().getName() ) ==0 )
492    {
493        errln("copy construction failed\n");
494    }
495
496    ResourceBundle defaultSub = defaultresource.get((int32_t)0, err);
497    ResourceBundle defSubCopy(defaultSub);
498    if(strcmp(defSubCopy.getName(), defaultSub.getName() ) !=0  ||
499        strcmp(defSubCopy.getLocale().getName(), defaultSub.getLocale().getName() ) !=0  ){
500        errln("copy construction for subresource failed\n");
501    }
502
503    ResourceBundle *p;
504
505    p = defaultresource.clone();
506    if(p == &defaultresource || !equalRB(*p, defaultresource)) {
507        errln("ResourceBundle.clone() failed");
508    }
509    delete p;
510
511    p = defaultSub.clone();
512    if(p == &defaultSub || !equalRB(*p, defaultSub)) {
513        errln("2nd ResourceBundle.clone() failed");
514    }
515    delete p;
516
517    UVersionInfo ver;
518    copyRes.getVersion(ver);
519
520    logln("Version returned: [%d.%d.%d.%d]\n", ver[0], ver[1], ver[2], ver[3]);
521
522    logln("Testing C like UnicodeString APIs\n");
523
524    UResourceBundle *testCAPI = NULL, *bundle = NULL, *rowbundle = NULL, *temp = NULL;
525    err = U_ZERO_ERROR;
526    const char* data[]={
527        "string_in_Root_te_te_IN",   "1",
528        "array_in_Root_te_te_IN",    "5",
529        "array_2d_in_Root_te_te_IN", "4",
530    };
531
532
533    testCAPI = ures_open(testdatapath, "te_IN", &err);
534
535    if(U_SUCCESS(err)) {
536        // Do the testing
537        // first iteration
538
539        uint32_t i;
540        int32_t count, row=0, col=0;
541        char buf[5];
542        UnicodeString expected;
543        UnicodeString element("TE_IN");
544        UnicodeString action;
545
546
547        for(i=0; i<UPRV_LENGTHOF(data); i=i+2){
548            action = "te_IN";
549            action +=".get(";
550            action += data[i];
551            action +=", err)";
552            err=U_ZERO_ERROR;
553            bundle = ures_getByKey(testCAPI, data[i], bundle, &err);
554            if(!U_FAILURE(err)){
555                const char* key = NULL;
556                action = "te_IN";
557                action +=".getKey()";
558
559                CONFIRM_EQ((UnicodeString)ures_getKey(bundle), (UnicodeString)data[i]);
560
561                count=0;
562                row=0;
563                while(ures_hasNext(bundle)){
564                    action = data[i];
565                    action +=".getNextString(err)";
566                    row=count;
567                    UnicodeString got=ures_getNextUnicodeString(bundle, &key, &err);
568                    if(U_SUCCESS(err)){
569                        expected=element;
570                        if(ures_getSize(bundle) > 1){
571                            CONFIRM_EQ(ures_getType(bundle), URES_ARRAY);
572                            expected+=itoa(row, buf);
573                            rowbundle=ures_getByIndex(bundle, row, rowbundle, &err);
574                            if(!U_FAILURE(err) && ures_getSize(rowbundle)>1){
575                                col=0;
576                                while(ures_hasNext(rowbundle)){
577                                    expected=element;
578                                    got=ures_getNextUnicodeString(rowbundle, &key, &err);
579                                    temp = ures_getByIndex(rowbundle, col, temp, &err);
580                                    UnicodeString bla = ures_getUnicodeString(temp, &err);
581                                    UnicodeString bla2 = ures_getUnicodeStringByIndex(rowbundle, col, &err);
582                                    if(!U_FAILURE(err)){
583                                        expected+=itoa(row, buf);
584                                        expected+=itoa(col, buf);
585                                        col++;
586                                        CONFIRM_EQ(got, expected);
587                                        CONFIRM_EQ(bla, expected);
588                                        CONFIRM_EQ(bla2, expected);
589                                    }
590                                }
591                                CONFIRM_EQ(col, ures_getSize(rowbundle));
592                            }
593                        }
594                        else{
595                            CONFIRM_EQ(ures_getType(bundle), (int32_t)URES_STRING);
596                        }
597                    }
598                    CONFIRM_EQ(got, expected);
599                    count++;
600                }
601            }
602        }
603
604        // Check that ures_getUnicodeString() & variants return a bogus string if failure.
605        // Same relevant code path whether the failure code is passed in
606        // or comes from a lookup error.
607        UErrorCode failure = U_INTERNAL_PROGRAM_ERROR;
608        assertTrue("ures_getUnicodeString(failure).isBogus()",
609                   ures_getUnicodeString(testCAPI, &failure).isBogus());
610        assertTrue("ures_getNextUnicodeString(failure).isBogus()",
611                   ures_getNextUnicodeString(testCAPI, NULL, &failure).isBogus());
612        assertTrue("ures_getUnicodeStringByIndex(failure).isBogus()",
613                   ures_getUnicodeStringByIndex(testCAPI, 999, &failure).isBogus());
614        assertTrue("ures_getUnicodeStringByKey(failure).isBogus()",
615                   ures_getUnicodeStringByKey(testCAPI, "bogus key", &failure).isBogus());
616
617        ures_close(temp);
618        ures_close(rowbundle);
619        ures_close(bundle);
620        ures_close(testCAPI);
621    } else {
622        errln("failed to open a resource bundle\n");
623    }
624
625    /* Restore the default locale for the other tests. */
626    Locale::setDefault(originalDefault, err);
627}
628
629
630
631
632//***************************************************************************************
633
634UBool
635NewResourceBundleTest::testTag(const char* frag,
636                            UBool in_Root,
637                            UBool in_te,
638                            UBool in_te_IN)
639{
640    int32_t failOrig = fail;
641
642    // Make array from input params
643
644    UBool is_in[] = { in_Root, in_te, in_te_IN };
645
646    const char* NAME[] = { "ROOT", "TE", "TE_IN" };
647
648    // Now try to load the desired items
649
650    char tag[100];
651    UnicodeString action;
652
653    int32_t i,j,row,col, actual_bundle;
654    int32_t index;
655    const char* testdatapath;
656
657    UErrorCode status = U_ZERO_ERROR;
658    testdatapath=loadTestData(status);
659    if(U_FAILURE(status))
660    {
661        dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(status)));
662        return FALSE;
663    }
664
665    for (i=0; i<bundles_count; ++i)
666    {
667        action = "Constructor for ";
668        action += param[i].name;
669
670        status = U_ZERO_ERROR;
671        ResourceBundle theBundle( testdatapath, *param[i].locale, status);
672        //ResourceBundle theBundle( "c:\\icu\\icu\\source\\test\\testdata\\testdata", *param[i].locale, status);
673        CONFIRM_UErrorCode(status,param[i].expected_constructor_status);
674
675        if(i == 5)
676          actual_bundle = 0; /* ne -> default */
677        else if(i == 3)
678          actual_bundle = 1; /* te_NE -> te */
679        else if(i == 4)
680          actual_bundle = 2; /* te_IN_NE -> te_IN */
681        else
682          actual_bundle = i;
683
684
685        UErrorCode expected_resource_status = U_MISSING_RESOURCE_ERROR;
686        for (j=e_te_IN; j>=e_Root; --j)
687        {
688            if (is_in[j] && param[i].inherits[j])
689              {
690                if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */
691                  expected_resource_status = U_ZERO_ERROR;
692                else if(j == 0)
693                  expected_resource_status = U_USING_DEFAULT_WARNING;
694                else
695                  expected_resource_status = U_USING_FALLBACK_WARNING;
696
697                break;
698            }
699        }
700
701        UErrorCode expected_status;
702
703        UnicodeString base;
704        for (j=param[i].where; j>=0; --j)
705        {
706            if (is_in[j])
707            {
708                base = NAME[j];
709                break;
710            }
711        }
712
713        //--------------------------------------------------------------------------
714        // string
715
716        uprv_strcpy(tag, "string_");
717        uprv_strcat(tag, frag);
718
719        action = param[i].name;
720        action += ".getStringEx(";
721        action += tag;
722        action += ")";
723
724
725        status = U_ZERO_ERROR;
726        UnicodeString string = theBundle.getStringEx(tag, status);
727        if(U_FAILURE(status)) {
728            string.setTo(TRUE, kErrorUChars, kErrorLength);
729        }
730
731        CONFIRM_UErrorCode(status, expected_resource_status);
732
733        UnicodeString expected_string(kErrorUChars);
734        if (U_SUCCESS(status)) {
735            expected_string = base;
736        }
737
738        CONFIRM_EQ(string, expected_string);
739
740        //--------------------------------------------------------------------------
741        // array   ResourceBundle using the key
742
743        uprv_strcpy(tag, "array_");
744        uprv_strcat(tag, frag);
745
746        action = param[i].name;
747        action += ".get(";
748        action += tag;
749        action += ")";
750
751        int32_t count = kERROR_COUNT;
752        status = U_ZERO_ERROR;
753        ResourceBundle array = theBundle.get(tag, status);
754        CONFIRM_UErrorCode(status,expected_resource_status);
755
756
757        if (U_SUCCESS(status))
758        {
759            //confirm the resource type is an array
760            UResType bundleType=array.getType();
761            CONFIRM_EQ(bundleType, URES_ARRAY);
762
763            count=array.getSize();
764            CONFIRM_GE(count,1);
765
766            for (j=0; j<count; ++j)
767            {
768                char buf[32];
769                expected_string = base;
770                expected_string += itoa(j,buf);
771                CONFIRM_EQ(array.getNextString(status),expected_string);
772            }
773
774        }
775        else
776        {
777            CONFIRM_EQ(count,kERROR_COUNT);
778            //       CONFIRM_EQ((int32_t)(unsigned long)array,(int32_t)0);
779            count = 0;
780        }
781
782        //--------------------------------------------------------------------------
783        // arrayItem ResourceBundle using the index
784
785
786        for (j=0; j<100; ++j)
787        {
788            index = count ? (randi(count * 3) - count) : (randi(200) - 100);
789            status = U_ZERO_ERROR;
790            string = kErrorUChars;
791            ResourceBundle array = theBundle.get(tag, status);
792            if(!U_FAILURE(status)){
793                UnicodeString t = array.getStringEx(index, status);
794                if(!U_FAILURE(status)) {
795                   string=t;
796                }
797            }
798
799            expected_status = (index >= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR;
800            CONFIRM_UErrorCode(status,expected_status);
801
802            if (U_SUCCESS(status)){
803                char buf[32];
804                expected_string = base;
805                expected_string += itoa(index,buf);
806            } else {
807                expected_string = kErrorUChars;
808            }
809               CONFIRM_EQ(string,expected_string);
810
811        }
812
813        //--------------------------------------------------------------------------
814        // 2dArray
815
816        uprv_strcpy(tag, "array_2d_");
817        uprv_strcat(tag, frag);
818
819        action = param[i].name;
820        action += ".get(";
821        action += tag;
822        action += ")";
823
824
825        int32_t row_count = kERROR_COUNT, column_count = kERROR_COUNT;
826        status = U_ZERO_ERROR;
827        ResourceBundle array2d=theBundle.get(tag, status);
828
829        //const UnicodeString** array2d = theBundle.get2dArray(tag, row_count, column_count, status);
830        CONFIRM_UErrorCode(status,expected_resource_status);
831
832        if (U_SUCCESS(status))
833        {
834            //confirm the resource type is an 2darray
835            UResType bundleType=array2d.getType();
836            CONFIRM_EQ(bundleType, URES_ARRAY);
837
838            row_count=array2d.getSize();
839            CONFIRM_GE(row_count,1);
840
841            for(row=0; row<row_count; ++row){
842                ResourceBundle tablerow=array2d.get(row, status);
843                CONFIRM_UErrorCode(status, expected_resource_status);
844                if(U_SUCCESS(status)){
845                    //confirm the resourcetype of each table row is an array
846                    UResType rowType=tablerow.getType();
847                    CONFIRM_EQ(rowType, URES_ARRAY);
848
849                    column_count=tablerow.getSize();
850                    CONFIRM_GE(column_count,1);
851
852                    for (col=0; j<column_count; ++j) {
853                           char buf[32];
854                           expected_string = base;
855                           expected_string += itoa(row,buf);
856                           expected_string += itoa(col,buf);
857                           CONFIRM_EQ(tablerow.getNextString(status),expected_string);
858                    }
859                }
860            }
861        }else{
862            CONFIRM_EQ(row_count,kERROR_COUNT);
863            CONFIRM_EQ(column_count,kERROR_COUNT);
864             row_count=column_count=0;
865        }
866
867
868
869
870       //--------------------------------------------------------------------------
871       // 2dArrayItem
872       for (j=0; j<200; ++j)
873       {
874           row = row_count ? (randi(row_count * 3) - row_count) : (randi(200) - 100);
875           col = column_count ? (randi(column_count * 3) - column_count) : (randi(200) - 100);
876           status = U_ZERO_ERROR;
877           string = kErrorUChars;
878           ResourceBundle array2d=theBundle.get(tag, status);
879           if(U_SUCCESS(status)){
880                ResourceBundle tablerow=array2d.get(row, status);
881                if(U_SUCCESS(status)) {
882                    UnicodeString t=tablerow.getStringEx(col, status);
883                    if(U_SUCCESS(status)){
884                       string=t;
885                    }
886                }
887           }
888           expected_status = (row >= 0 && row < row_count && col >= 0 && col < column_count) ?
889                                  expected_resource_status: U_MISSING_RESOURCE_ERROR;
890           CONFIRM_UErrorCode(status,expected_status);
891
892           if (U_SUCCESS(status)){
893               char buf[32];
894               expected_string = base;
895               expected_string += itoa(row,buf);
896               expected_string += itoa(col,buf);
897           } else {
898               expected_string = kErrorUChars;
899           }
900               CONFIRM_EQ(string,expected_string);
901
902        }
903
904        //--------------------------------------------------------------------------
905        // taggedArray
906
907        uprv_strcpy(tag, "tagged_array_");
908        uprv_strcat(tag, frag);
909
910        action = param[i].name;
911        action += ".get(";
912        action += tag;
913        action += ")";
914
915        int32_t         tag_count;
916        status = U_ZERO_ERROR;
917
918        ResourceBundle tags=theBundle.get(tag, status);
919        CONFIRM_UErrorCode(status, expected_resource_status);
920
921        if (U_SUCCESS(status)) {
922            UResType bundleType=tags.getType();
923            CONFIRM_EQ(bundleType, URES_TABLE);
924
925            tag_count=tags.getSize();
926            CONFIRM_GE((int32_t)tag_count, (int32_t)0);
927
928            for(index=0; index <tag_count; index++){
929                ResourceBundle tagelement=tags.get(index, status);
930                UnicodeString key=tagelement.getKey();
931                UnicodeString value=tagelement.getNextString(status);
932                logln("tag = " + key + ", value = " + value );
933                if(key.startsWith("tag") && value.startsWith(base)){
934                    record_pass();
935                }else{
936                    record_fail();
937                }
938
939            }
940
941            for(index=0; index <tag_count; index++){
942                ResourceBundle tagelement=tags.get(index, status);
943                const char *tkey=NULL;
944                UnicodeString value=tagelement.getNextString(&tkey, status);
945                UnicodeString key(tkey);
946                logln("tag = " + key + ", value = " + value );
947                if(value.startsWith(base)){
948                    record_pass();
949                }else{
950                    record_fail();
951                }
952            }
953
954        }else{
955            tag_count=0;
956        }
957
958
959
960
961        //--------------------------------------------------------------------------
962        // taggedArrayItem
963
964        action = param[i].name;
965        action += ".get(";
966        action += tag;
967        action += ")";
968
969        count = 0;
970        for (index=-20; index<20; ++index)
971        {
972            char buf[32];
973            status = U_ZERO_ERROR;
974            string = kErrorUChars;
975            char item_tag[8];
976            uprv_strcpy(item_tag, "tag");
977            uprv_strcat(item_tag, itoa(index,buf));
978            ResourceBundle tags=theBundle.get(tag, status);
979            if(U_SUCCESS(status)){
980                ResourceBundle tagelement=tags.get(item_tag, status);
981                if(!U_FAILURE(status)){
982                    UResType elementType=tagelement.getType();
983                    CONFIRM_EQ(elementType, (int32_t)URES_STRING);
984                    const char* key=tagelement.getKey();
985                    CONFIRM_EQ((UnicodeString)key, (UnicodeString)item_tag);
986                    UnicodeString t=tagelement.getString(status);
987                    if(!U_FAILURE(status)){
988                        string=t;
989                    }
990                }
991                if (index < 0) {
992                    CONFIRM_UErrorCode(status,U_MISSING_RESOURCE_ERROR);
993                }
994                else{
995                   if (status != U_MISSING_RESOURCE_ERROR) {
996                       count++;
997                       expected_string = base;
998                       expected_string += buf;
999                       CONFIRM_EQ(string,expected_string);
1000                   }
1001                }
1002            }
1003
1004        }
1005        CONFIRM_EQ(count, tag_count);
1006
1007    }
1008    return (UBool)(failOrig == fail);
1009}
1010
1011void
1012NewResourceBundleTest::record_pass()
1013{
1014  ++pass;
1015}
1016void
1017NewResourceBundleTest::record_fail()
1018{
1019  err();
1020  ++fail;
1021}
1022
1023
1024void
1025NewResourceBundleTest::TestNewTypes() {
1026    char action[256];
1027    const char* testdatapath;
1028    UErrorCode status = U_ZERO_ERROR;
1029    uint8_t *binResult = NULL;
1030    int32_t len = 0;
1031    int32_t i = 0;
1032    int32_t intResult = 0;
1033    uint32_t uintResult = 0;
1034    UChar expected[] = { 'a','b','c','\0','d','e','f' };
1035    const char* expect ="tab:\t cr:\r ff:\f newline:\n backslash:\\\\ quote=\\\' doubleQuote=\\\" singlequoutes=''";
1036    UChar uExpect[200];
1037
1038    testdatapath=loadTestData(status);
1039
1040    if(U_FAILURE(status))
1041    {
1042        dataerrln("Could not load testdata.dat %s \n",u_errorName(status));
1043        return;
1044    }
1045
1046    ResourceBundle theBundle(testdatapath, "testtypes", status);
1047    ResourceBundle bundle(testdatapath, Locale("te_IN"),status);
1048
1049    UnicodeString emptyStr = theBundle.getStringEx("emptystring", status);
1050    if(emptyStr.length() != 0) {
1051      logln("Empty string returned invalid value\n");
1052    }
1053
1054    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1055
1056    /* This test reads the string "abc\u0000def" from the bundle   */
1057    /* if everything is working correctly, the size of this string */
1058    /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/
1059
1060    strcpy(action, "getting and testing of string with embeded zero");
1061    ResourceBundle res = theBundle.get("zerotest", status);
1062    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1063    CONFIRM_EQ(res.getType(), URES_STRING);
1064    UnicodeString zeroString=res.getString(status);
1065    len = zeroString.length();
1066    if(U_SUCCESS(status)){
1067        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1068        CONFIRM_EQ(len, 7);
1069        CONFIRM_NE(len, 3);
1070    }
1071    for(i=0;i<len;i++){
1072        if(zeroString[i]!= expected[i]){
1073            logln("Output didnot match Expected: \\u%4X Got: \\u%4X", expected[i], zeroString[i]);
1074        }
1075    }
1076
1077    strcpy(action, "getting and testing of binary type");
1078    res = theBundle.get("binarytest", status);
1079    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1080    CONFIRM_EQ(res.getType(), URES_BINARY);
1081    binResult=(uint8_t*)res.getBinary(len, status);
1082    if(U_SUCCESS(status)){
1083        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1084        CONFIRM_EQ(len, 15);
1085        for(i = 0; i<15; i++) {
1086            CONFIRM_EQ(binResult[i], i);
1087        }
1088    }
1089
1090    strcpy(action, "getting and testing of imported binary type");
1091    res = theBundle.get("importtest",status);
1092    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1093    CONFIRM_EQ(res.getType(), URES_BINARY);
1094    binResult=(uint8_t*)res.getBinary(len, status);
1095    if(U_SUCCESS(status)){
1096        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1097        CONFIRM_EQ(len, 15);
1098        for(i = 0; i<15; i++) {
1099            CONFIRM_EQ(binResult[i], i);
1100        }
1101    }
1102
1103    strcpy(action, "getting and testing of integer types");
1104    res = theBundle.get("one",  status);
1105    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1106    CONFIRM_EQ(res.getType(), URES_INT);
1107    intResult=res.getInt(status);
1108    uintResult = res.getUInt(status);
1109    if(U_SUCCESS(status)){
1110        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1111        CONFIRM_EQ(uintResult, (uint32_t)intResult);
1112        CONFIRM_EQ(intResult, 1);
1113    }
1114
1115    strcpy(action, "getting minusone");
1116    res = theBundle.get((const char*)"minusone", status);
1117    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1118    CONFIRM_EQ(res.getType(), URES_INT);
1119    intResult=res.getInt(status);
1120    uintResult = res.getUInt(status);
1121    if(U_SUCCESS(status)){
1122        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1123        CONFIRM_EQ(uintResult, 0x0FFFFFFF); /* a 28 bit integer */
1124        CONFIRM_EQ(intResult, -1);
1125        CONFIRM_NE(uintResult, (uint32_t)intResult);
1126    }
1127
1128    strcpy(action, "getting plusone");
1129    res = theBundle.get("plusone",status);
1130    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1131    CONFIRM_EQ(res.getType(), URES_INT);
1132    intResult=res.getInt(status);
1133    uintResult = res.getUInt(status);
1134    if(U_SUCCESS(status)){
1135        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1136        CONFIRM_EQ(uintResult, (uint32_t)intResult);
1137        CONFIRM_EQ(intResult, 1);
1138    }
1139
1140    res = theBundle.get("onehundredtwentythree",status);
1141    CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1142    CONFIRM_EQ(res.getType(), URES_INT);
1143    intResult=res.getInt(status);
1144    if(U_SUCCESS(status)){
1145        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1146        CONFIRM_EQ(intResult, 123);
1147    }
1148
1149    /* this tests if escapes are preserved or not */
1150    {
1151        UnicodeString str = theBundle.getStringEx("testescape",status);
1152        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1153        if(U_SUCCESS(status)){
1154            u_charsToUChars(expect,uExpect,(int32_t)uprv_strlen(expect)+1);
1155            if(str.compare(uExpect)!=0){
1156                errln("Did not get the expected string for testescape expected. Expected : "
1157                    +UnicodeString(uExpect )+ " Got: " + str);
1158            }
1159        }
1160    }
1161    /* test for jitterbug#1435 */
1162    {
1163        UnicodeString str = theBundle.getStringEx("test_underscores",status);
1164        expect ="test message ....";
1165        CONFIRM_UErrorCode(status, U_ZERO_ERROR);
1166        u_charsToUChars(expect,uExpect,(int32_t)uprv_strlen(expect)+1);
1167        if(str.compare(uExpect)!=0){
1168            errln("Did not get the expected string for test_underscores.\n");
1169        }
1170    }
1171
1172
1173}
1174
1175void
1176NewResourceBundleTest::TestGetByFallback() {
1177    UErrorCode status = U_ZERO_ERROR;
1178
1179    ResourceBundle heRes(NULL, "he", status);
1180
1181    heRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("DateTime", status);
1182    if(U_SUCCESS(status)) {
1183        errln("he locale's Islamic-civil DateTime resource exists. How did it get here?\n");
1184    }
1185    status = U_ZERO_ERROR;
1186
1187    heRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("eras", status);
1188    if(U_FAILURE(status)) {
1189        dataerrln("Didn't get Islamic Eras. I know they are there! - %s", u_errorName(status));
1190    }
1191    status = U_ZERO_ERROR;
1192
1193    ResourceBundle rootRes(NULL, "root", status);
1194    rootRes.getWithFallback("calendar", status).getWithFallback("islamic-civil", status).getWithFallback("DateTime", status);
1195    if(U_SUCCESS(status)) {
1196        errln("Root's Islamic-civil's DateTime resource exists. How did it get here?\n");
1197    }
1198    status = U_ZERO_ERROR;
1199
1200}
1201//eof
1202
1203