/******************************************************************** * COPYRIGHT: * Copyright (c) 1997-2001, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ #include #include #include #define RESTEST_HEAP_CHECK 0 #include "unicode/utypes.h" #if defined(_WIN32) && !defined(__WINDOWS__) #define _CRTDBG_MAP_ALLOC #include #endif #include "cstring.h" #include "unicode/unistr.h" #include "unicode/resbund.h" #include "restsnew.h" #include //*************************************************************************************** static const UChar kErrorUChars[] = { 0x45, 0x52, 0x52, 0x4f, 0x52, 0 }; static const int32_t kErrorLength = 5; static const int32_t kERROR_COUNT = -1234567; //*************************************************************************************** enum E_Where { e_Root, e_te, e_te_IN, e_Where_count }; //*************************************************************************************** #define CONFIRM_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << (actual) << " instead of " << (expected) << endl; } #define CONFIRM_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); OUT << action << " returned " << (actual) << " instead of x >= " << (expected) << endl; } #define CONFIRM_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << (actual) << " instead of x != " << (expected) << endl; } #define CONFIRM_UErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); OUT << action << " returned " << u_errorName(actual) << " instead of " << u_errorName(expected) << endl; } //*************************************************************************************** /** * Convert an integer, positive or negative, to a character string radix 10. */ static char* itoa(int32_t i, char* buf) { char* result = buf; // Handle negative if (i < 0) { *buf++ = '-'; i = -i; } // Output digits in reverse order char* p = buf; do { *p++ = (char)('0' + (i % 10)); i /= 10; } while (i); *p-- = 0; // Reverse the string while (buf < p) { char c = *buf; *buf++ = *p; *p-- = c; } return result; } //*************************************************************************************** // Array of our test objects static struct { const char* name; Locale *locale; UErrorCode expected_constructor_status; E_Where where; UBool like[e_Where_count]; UBool inherits[e_Where_count]; } param[] = { // "te" means test // "IN" means inherits // "NE" or "ne" means "does not exist" { "root", 0, U_ZERO_ERROR, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }, { "te", 0, U_ZERO_ERROR, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } }, { "te_IN", 0, U_ZERO_ERROR, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } }, { "te_NE", 0, U_USING_FALLBACK_ERROR, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } }, { "te_IN_NE", 0, U_USING_FALLBACK_ERROR, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } }, { "ne", 0, U_USING_DEFAULT_ERROR, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } } }; static int32_t bundles_count = sizeof(param) / sizeof(param[0]); //*************************************************************************************** /** * Return a random unsigned long l where 0N <= l <= ULONG_MAX. */ static uint32_t randul() { static UBool initialized = FALSE; if (!initialized) { srand((unsigned)time(NULL)); initialized = TRUE; } // Assume rand has at least 12 bits of precision uint32_t l = 0; for (uint32_t i=0; i> 4); return l; } /** * Return a random double x where 0.0 <= x < 1.0. */ static double randd() { return (double)(randul() / ULONG_MAX); } /** * Return a random integer i where 0 <= i < n. */ static int32_t randi(int32_t n) { return (int32_t)(randd() * n); } //*************************************************************************************** /* Don't use more than one of these at a time because of the Locale names */ NewResourceBundleTest::NewResourceBundleTest() : pass(0), fail(0), OUT(it_out) { if (param[5].locale == NULL) { param[0].locale = new Locale("root"); param[1].locale = new Locale("te"); param[2].locale = new Locale("te", "IN"); param[3].locale = new Locale("te", "NE"); param[4].locale = new Locale("te", "IN", "NE"); param[5].locale = new Locale("ne"); } } NewResourceBundleTest::~NewResourceBundleTest() { if (param[5].locale) { int idx; for (idx = 0; idx < (int)(sizeof(param)/sizeof(param[0])); idx++) { delete param[idx].locale; param[idx].locale = NULL; } } } void NewResourceBundleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { if (exec) logln("TestSuite ResourceBundleTest: "); switch (index) { case 0: name = "TestResourceBundles"; if (exec) TestResourceBundles(); break; case 1: name = "TestConstruction"; if (exec) TestConstruction(); break; case 2: name = "TestIteration"; if (exec) TestIteration(); break; case 3: name = "TestOtherAPI"; if(exec) TestOtherAPI(); break; default: name = ""; break; //needed to end loop } } //*************************************************************************************** void NewResourceBundleTest::TestResourceBundles() { #if defined(_WIN32) && !defined(__WINDOWS__) #if defined(_DEBUG) && RESTEST_HEAP_CHECK /* * Set the debug-heap flag to keep freed blocks in the * heap's linked list - This will allow us to catch any * inadvertent use of freed memory */ int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF; tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF; tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF; _CrtSetDbgFlag(tmpDbgFlag); _CrtMemState memstate; _CrtMemCheckpoint(&memstate); { #endif #endif testTag("only_in_Root", TRUE, FALSE, FALSE); testTag("only_in_te", FALSE, TRUE, FALSE); testTag("only_in_te_IN", FALSE, FALSE, TRUE); testTag("in_Root_te", TRUE, TRUE, FALSE); testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE); testTag("in_Root_te_IN", TRUE, FALSE, TRUE); testTag("in_te_te_IN", FALSE, TRUE, TRUE); testTag("nonexistent", FALSE, FALSE, FALSE); OUT << "Passed: " << pass << "\nFailed: " << fail << endl; #if defined(_WIN32) && !defined(__WINDOWS__) #if defined(_DEBUG) && RESTEST_HEAP_CHECK } _CrtMemDumpAllObjectsSince(&memstate); /* * Set the debug-heap flag to keep freed blocks in the * heap's linked list - This will allow us to catch any * inadvertent use of freed memory */ tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF; tmpDbgFlag &= ~_CRTDBG_LEAK_CHECK_DF; tmpDbgFlag &= ~_CRTDBG_CHECK_ALWAYS_DF; _CrtSetDbgFlag(tmpDbgFlag); #endif #endif } void NewResourceBundleTest::TestConstruction() { { UErrorCode err = U_ZERO_ERROR; const char *directory; char testdatapath[256]; Locale locale("te", "IN"); directory=u_getDataDirectory(); uprv_strcpy(testdatapath, directory); uprv_strcat(testdatapath, "testdata"); ResourceBundle test1((UnicodeString)testdatapath, err); ResourceBundle test2(testdatapath, locale, err); UnicodeString result1; UnicodeString result2; result1 = test1.getStringEx("string_in_Root_te_te_IN", err); result2 = test2.getStringEx("string_in_Root_te_te_IN", err); if (U_FAILURE(err)) { errln("Something threw an error in TestConstruction()"); return; } logln("for string_in_Root_te_te_IN, root.txt had " + result1); logln("for string_in_Root_te_te_IN, te_IN.txt had " + result2); if (result1 != "ROOT" || result2 != "TE_IN") errln("Construction test failed; run verbose for more information"); const char* version1; const char* version2; version1 = test1.getVersionNumber(); version2 = test2.getVersionNumber(); char *versionID1 = new char[1 + strlen(U_ICU_VERSION) + strlen(version1)]; // + 1 for zero byte char *versionID2 = new char[1 + strlen(U_ICU_VERSION) + strlen(version2)]; // + 1 for zero byte strcpy(versionID1, "44"); // hardcoded, please change if the default.txt file or ResourceBundle::kVersionSeparater is changed. strcpy(versionID2, "55"); // hardcoded, please change if the te_IN.txt file or ResourceBundle::kVersionSeparater is changed. logln(UnicodeString("getVersionNumber on default.txt returned ") + version1 + UnicodeString(" Expect: " ) + versionID1); logln(UnicodeString("getVersionNumber on te_IN.txt returned ") + version2 + UnicodeString(" Expect: " ) + versionID2); if (strcmp(version1, versionID1) != 0 || strcmp(version2, versionID2) != 0) errln("getVersionNumber() failed"); delete[] versionID1; delete[] versionID2; } { UErrorCode err = U_ZERO_ERROR; const char *directory; char testdatapath[256]; Locale locale("te", "IN"); directory=u_getDataDirectory(); uprv_strcpy(testdatapath, directory); uprv_strcat(testdatapath, "testdata"); wchar_t* wideDirectory = new wchar_t[256]; mbstowcs(wideDirectory, testdatapath, 256); ResourceBundle test2(wideDirectory, locale, err); UnicodeString result2; result2 = test2.getStringEx("string_in_Root_te_te_IN", err); if (U_FAILURE(err)) { errln("Something threw an error in TestConstruction()"); return; } logln("for string_in_Root_te_te_IN, te_IN.txt had " + result2); if (result2 != "TE_IN") errln("Construction test failed; run verbose for more information"); delete[] wideDirectory; } } void NewResourceBundleTest::TestIteration() { UErrorCode err = U_ZERO_ERROR; const char *directory; char testdatapath[256]; const char* data[]={ "string_in_Root_te_te_IN", "1", "array_in_Root_te_te_IN", "5", "array_2d_in_Root_te_te_IN", "4", }; Locale *locale=new Locale("te_IN"); directory=u_getDataDirectory(); uprv_strcpy(testdatapath, directory); uprv_strcat(testdatapath, "testdata"); ResourceBundle test1(testdatapath, *locale, err); if(U_FAILURE(err)){ errln("Construction failed"); } uint32_t i; int32_t count, row=0, col=0; char buf[5]; UnicodeString expected; UnicodeString element("TE_IN"); UnicodeString action; for(i=0; i 1){ CONFIRM_EQ(bundle.getType(), RES_ARRAY); expected+=itoa(row, buf); ResourceBundle rowbundle=bundle.get(row, err); if(!U_FAILURE(err) && rowbundle.getSize()>1){ col=0; while(rowbundle.hasNext()){ expected=element; got=rowbundle.getNextString(err); if(!U_FAILURE(err)){ expected+=itoa(row, buf); expected+=itoa(col, buf); col++; CONFIRM_EQ(got, expected); } } CONFIRM_EQ(col, rowbundle.getSize()); } } else{ CONFIRM_EQ(bundle.getType(), (int32_t)RES_STRING); } } CONFIRM_EQ(got, expected); count++; } action = data[i]; action +=".getSize()"; CONFIRM_EQ(bundle.getSize(), count); CONFIRM_EQ(count, atoi(data[i+1])); //after reaching the end err=U_ZERO_ERROR; ResourceBundle errbundle=bundle.getNext(err); action = "After reaching the end of the Iterator:- "; action +=data[i]; action +=".getNext()"; CONFIRM_NE(err, (int32_t)U_ZERO_ERROR); CONFIRM_EQ(u_errorName(err), u_errorName(U_INDEX_OUTOFBOUNDS_ERROR)); //reset the iterator err = U_ZERO_ERROR; bundle.resetIterator(); /* The following code is causing a crash ****CRASH****** */ bundle.getNext(err); if(U_FAILURE(err)){ errln("ERROR: getNext() throw an error"); }/**/ } } delete locale; } void NewResourceBundleTest::TestOtherAPI(){ UErrorCode err = U_ZERO_ERROR; const char *directory; char testdatapath[256]; Locale *locale=new Locale("te_IN"); directory=u_getDataDirectory(); uprv_strcpy(testdatapath, directory); uprv_strcat(testdatapath, "testdata"); ResourceBundle test1(testdatapath, *locale, err); if(U_FAILURE(err)){ errln("Construction failed"); return; } logln("Testing getLocale()\n"); if(strcmp(test1.getLocale().getName(), locale->getName()) !=0 ){ errln("FAIL: ResourceBundle::getLocale() failed\n"); } delete locale; logln("Testing ResourceBundle(UErrorCode)\n"); ResourceBundle defaultresource(err); if(U_FAILURE(err)){ errln("Construction of default resourcebundle failed"); } if(strcmp(defaultresource.getLocale().getName(), Locale::getDefault().getName()) != 0){ errln("Construction of default resourcebundle didn't take the defaultlocale\n"); } ResourceBundle copyRes(defaultresource); if(strcmp(copyRes.getName(), defaultresource.getName() ) !=0 || strcmp(test1.getName(), defaultresource.getName() ) ==0 || strcmp(copyRes.getLocale().getName(), defaultresource.getLocale().getName() ) !=0 || strcmp(test1.getLocale().getName(), defaultresource.getLocale().getName() ) ==0 ){ errln("copy construction failed\n"); } ResourceBundle defaultSub = defaultresource.get(1, err); ResourceBundle defSubCopy(defaultSub); if(strcmp(defSubCopy.getName(), defaultSub.getName() ) !=0 || strcmp(defSubCopy.getLocale().getName(), defaultSub.getLocale().getName() ) !=0 ){ errln("copy construction for subresource failed\n"); } UVersionInfo ver; copyRes.getVersion(ver); logln("Version returned: [%d.%d.%d.%d]\n", ver[0], ver[1], ver[2], ver[3]); logln("Testing C like UnicodeString APIs\n"); UResourceBundle *testCAPI = NULL, *bundle = NULL, *rowbundle = NULL, *temp = NULL; err = U_ZERO_ERROR; const char* data[]={ "string_in_Root_te_te_IN", "1", "array_in_Root_te_te_IN", "5", "array_2d_in_Root_te_te_IN", "4", }; testCAPI = ures_open(testdatapath, "te_IN", &err); if(U_SUCCESS(err)) { // Do the testing // first iteration uint32_t i; int32_t count, row=0, col=0; char buf[5]; UnicodeString expected; UnicodeString element("TE_IN"); UnicodeString action; for(i=0; i 1){ CONFIRM_EQ(ures_getType(bundle), RES_ARRAY); expected+=itoa(row, buf); rowbundle=ures_getByIndex(bundle, row, rowbundle, &err); if(!U_FAILURE(err) && ures_getSize(rowbundle)>1){ col=0; while(ures_hasNext(rowbundle)){ expected=element; got=ures_getNextUnicodeString(rowbundle, &err); temp = ures_getByIndex(rowbundle, col, temp, &err); UnicodeString bla = ures_getUnicodeString(temp, &err); UnicodeString bla2 = ures_getUnicodeStringByIndex(rowbundle, col, &err); if(!U_FAILURE(err)){ expected+=itoa(row, buf); expected+=itoa(col, buf); col++; CONFIRM_EQ(got, expected); CONFIRM_EQ(bla, expected); CONFIRM_EQ(bla2, expected); } } CONFIRM_EQ(col, ures_getSize(rowbundle)); } } else{ CONFIRM_EQ(ures_getType(bundle), (int32_t)RES_STRING); } } CONFIRM_EQ(got, expected); count++; } } } ures_close(temp); ures_close(rowbundle); ures_close(bundle); ures_close(testCAPI); } else { errln("failed to open a resource bundle\n"); } } //*************************************************************************************** UBool NewResourceBundleTest::testTag(const char* frag, UBool in_Root, UBool in_te, UBool in_te_IN) { int32_t failOrig = fail; // Make array from input params UBool is_in[] = { in_Root, in_te, in_te_IN }; const char* NAME[] = { "ROOT", "TE", "TE_IN" }; // Now try to load the desired items char tag[100]; UnicodeString action; int32_t i,j,row,col, actual_bundle; int32_t index; const char *directory; char testdatapath[256]; directory=u_getDataDirectory(); uprv_strcpy(testdatapath, directory); uprv_strcat(testdatapath, "testdata"); for (i=0; i default */ else if(i == 3) actual_bundle = 1; /* te_NE -> te */ else if(i == 4) actual_bundle = 2; /* te_IN_NE -> te_IN */ else actual_bundle = i; UErrorCode expected_resource_status = U_MISSING_RESOURCE_ERROR; for (j=e_te_IN; j>=e_Root; --j) { if (is_in[j] && param[i].inherits[j]) { if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */ expected_resource_status = U_ZERO_ERROR; else if(j == 0) expected_resource_status = U_USING_DEFAULT_ERROR; else expected_resource_status = U_USING_FALLBACK_ERROR; break; } } UErrorCode expected_status; UnicodeString base; for (j=param[i].where; j>=0; --j) { if (is_in[j]) { base = NAME[j]; break; } } //-------------------------------------------------------------------------- // string uprv_strcpy(tag, "string_"); uprv_strcat(tag, frag); action = param[i].name; action += ".getStringEx("; action += tag; action += ")"; status = U_ZERO_ERROR; UnicodeString string = theBundle.getStringEx(tag, status); if(U_FAILURE(status)) { string.setTo(TRUE, kErrorUChars, kErrorLength); } CONFIRM_UErrorCode(status, expected_resource_status); UnicodeString expected_string(kErrorUChars); if (U_SUCCESS(status)) { expected_string = base; } CONFIRM_EQ(string, expected_string); //-------------------------------------------------------------------------- // array ResourceBundle using the key uprv_strcpy(tag, "array_"); uprv_strcat(tag, frag); action = param[i].name; action += ".get("; action += tag; action += ")"; int32_t count = kERROR_COUNT; status = U_ZERO_ERROR; ResourceBundle array = theBundle.get(tag, status); CONFIRM_UErrorCode(status,expected_resource_status); if (U_SUCCESS(status)) { //confirm the resource type is an array UResType bundleType=array.getType(); CONFIRM_EQ(bundleType, RES_ARRAY); count=array.getSize(); CONFIRM_GE(count,1); for (j=0; j= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR; CONFIRM_UErrorCode(status,expected_status); if (U_SUCCESS(status)){ char buf[32]; expected_string = base; expected_string += itoa(index,buf); } else { expected_string = kErrorUChars; } CONFIRM_EQ(string,expected_string); } //-------------------------------------------------------------------------- // 2dArray uprv_strcpy(tag, "array_2d_"); uprv_strcat(tag, frag); action = param[i].name; action += ".get("; action += tag; action += ")"; int32_t row_count = kERROR_COUNT, column_count = kERROR_COUNT; status = U_ZERO_ERROR; ResourceBundle array2d=theBundle.get(tag, status); //const UnicodeString** array2d = theBundle.get2dArray(tag, row_count, column_count, status); CONFIRM_UErrorCode(status,expected_resource_status); if (U_SUCCESS(status)) { //confirm the resource type is an 2darray UResType bundleType=array2d.getType(); CONFIRM_EQ(bundleType, RES_ARRAY); row_count=array2d.getSize(); CONFIRM_GE(row_count,1); for(row=0; row= 0 && row < row_count && col >= 0 && col < column_count) ? expected_resource_status: U_MISSING_RESOURCE_ERROR; CONFIRM_UErrorCode(status,expected_status); if (U_SUCCESS(status)){ char buf[32]; expected_string = base; expected_string += itoa(row,buf); expected_string += itoa(col,buf); } else { expected_string = kErrorUChars; } CONFIRM_EQ(string,expected_string); } //-------------------------------------------------------------------------- // taggedArray uprv_strcpy(tag, "tagged_array_"); uprv_strcat(tag, frag); action = param[i].name; action += ".get("; action += tag; action += ")"; int32_t tag_count; status = U_ZERO_ERROR; ResourceBundle tags=theBundle.get(tag, status); CONFIRM_UErrorCode(status, expected_resource_status); if (U_SUCCESS(status)) { UResType bundleType=tags.getType(); CONFIRM_EQ(bundleType, RES_TABLE); tag_count=tags.getSize(); CONFIRM_GE((int32_t)tag_count, (int32_t)0); for(index=0; index