Android patch: Android support for ICU4C tests (Part 2)
am: 1df5a99fd7
Change-Id: I7ad4478171baad277b5bd50181c23a8805e59882
diff --git a/icu4c/source/test/cintltst/cintltst.c b/icu4c/source/test/cintltst/cintltst.c
index c341d1e..6194da9 100644
--- a/icu4c/source/test/cintltst/cintltst.c
+++ b/icu4c/source/test/cintltst/cintltst.c
@@ -42,6 +42,13 @@
# include <console.h>
#endif
+// ANDROID_USE_ICU_REG is defined when building against the Android OS source tree.
+// androidicuinit is a static library which helps initialize ICU4C using the data
+// on the device.
+#if defined(__ANDROID__) && defined(ANDROID_USE_ICU_REG)
+#include <androidicuinit/android_icu_reg.h>
+#endif
+
#define CTST_MAX_ALLOC 8192
/* Array used as a queue */
static void * ctst_allocated_stuff[CTST_MAX_ALLOC] = {0};
@@ -249,7 +256,11 @@
(int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
(int)(diffTime%U_MILLIS_PER_SECOND));
+#ifdef ZERO_EXIT_CODE_FOR_FAILURES
+ return 0;
+#else
return nerrors ? 1 : 0;
+#endif
}
/*
@@ -301,7 +312,11 @@
* tests dynamically load some data.
*/
void ctest_setICU_DATA() {
+ #if defined(__ANDROID__) && defined(ANDROID_USE_ICU_REG)
+ android_icu_register();
+ #else
u_setDataDirectory(ctest_dataOutDir());
+ #endif
}
/* These tests do cleanup and reinitialize ICU in the course of their operation.
@@ -322,12 +337,16 @@
UErrorCode status = U_ZERO_ERROR;
char *dataDir = safeGetICUDataDirectory();
+ #if defined(__ANDROID__) && defined(ANDROID_USE_ICU_REG)
+ android_icu_deregister();
+ #else
u_cleanup();
+ #endif
if (!initArgs(gOrigArgc, gOrigArgv, NULL, NULL)) {
/* Error already displayed. */
return FALSE;
}
- u_setDataDirectory(dataDir);
+ ctest_setICU_DATA();
free(dataDir);
u_init(&status);
if (U_FAILURE(status)) {
diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp
index 7bb9032..e726866 100644
--- a/icu4c/source/test/intltest/intltest.cpp
+++ b/icu4c/source/test/intltest/intltest.cpp
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>
#include <cmath>
+#include <iostream>
#include "unicode/ctest.h" // for str_timeDelta
#include "unicode/curramt.h"
@@ -45,6 +46,13 @@
#include "umutex.h"
#include "uoptions.h"
+// ANDROID_USE_ICU_REG is defined when building against the Android OS source tree.
+// androidicuinit is a static library which helps initialize ICU4C using the data
+// on the device.
+#if defined(__ANDROID__) && defined(ANDROID_USE_ICU_REG)
+#include <androidicuinit/android_icu_reg.h>
+#endif
+
#ifdef XP_MAC_CONSOLE
#include <console.h>
#include "Files.h"
@@ -419,7 +427,11 @@
* tests dynamically load some data.
*/
void IntlTest::setICU_DATA() {
+ #if defined(__ANDROID__) && defined(ANDROID_USE_ICU_REG)
+ android_icu_register();
+ #else
u_setDataDirectory(ctest_dataOutDir());
+ #endif
}
@@ -537,13 +549,15 @@
}
}
-UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
+UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par, const char* basename)
{
execCount--; // correct a previously assumed test-exec, as this only calls a subtest
testToBeCalled.setCaller( this );
- strcpy(testToBeCalled.basePath, this->basePath );
- UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath );
- strcpy(testToBeCalled.basePath, this->basePath ); // reset it.
+ strcpy(testToBeCalled.basePath, basename);
+ strcat(testToBeCalled.basePath, this->basePath);
+ UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath);
+ strcpy(testToBeCalled.basePath, basename); // reset it.
+ strcat(testToBeCalled.basePath, this->basePath);
return result;
}
@@ -667,6 +681,27 @@
}
+static std::string string_replace_all(std::string str, const std::string& from, const std::string& to) {
+ size_t start = 0;
+ while((start = str.find(from, start)) != std::string::npos) {
+ str.replace(start, from.length(), to);
+ start += to.length();
+ }
+ return str;
+}
+
+/**
+ * Escape some known characters, but the list is not perfect.
+ */
+static std::string escape_xml_attribute(std::string str) {
+ str = string_replace_all(str, "&", "&");
+ str = string_replace_all(str, "\"", """);
+ str = string_replace_all(str, "'", "'");
+ str = string_replace_all(str, "<", "<");
+ str = string_replace_all(str, ">", ">");
+ return str;
+}
+
UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
{
int32_t index = 0;
@@ -712,6 +747,7 @@
strcpy(saveBaseLoc,name);
strcat(saveBaseLoc,"/");
+ currErr = ""; // Reset the current error message
strcpy(currName, name); // set
this->runIndexedTest( index, TRUE, name, par );
currName[0]=0; // reset
@@ -729,7 +765,9 @@
strcpy(saveBaseLoc,name);
- ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL);
+ std::string err = currErr;
+ err = escape_xml_attribute(err);
+ ctest_xml_testcase(name, baseName, secs, (lastErrorCount!=errorCount)?err.c_str():NULL);
saveBaseLoc[0]=0; /* reset path */
@@ -841,13 +879,13 @@
void IntlTest::err( const UnicodeString &message )
{
IncErrorCount();
- if (!no_err_msg) LL_message( message, FALSE );
+ if (!no_err_msg) LL_err_message( message, FALSE );
}
void IntlTest::errln( const UnicodeString &message )
{
IncErrorCount();
- if (!no_err_msg) LL_message( message, TRUE );
+ if (!no_err_msg) LL_err_message( message, TRUE );
}
void IntlTest::dataerr( const UnicodeString &message )
@@ -858,7 +896,7 @@
IncErrorCount();
}
- if (!no_err_msg) LL_message( message, FALSE );
+ if (!no_err_msg) LL_err_message( message, FALSE );
}
void IntlTest::dataerrln( const UnicodeString &message )
@@ -874,9 +912,9 @@
if (!no_err_msg) {
if ( errCount == 1) {
- LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
+ LL_err_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
} else {
- LL_message( msg , TRUE );
+ LL_err_message( msg , TRUE );
}
}
}
@@ -1031,7 +1069,7 @@
void IntlTest::printErrors()
{
- IntlTest::LL_message(errorList, TRUE);
+ IntlTest::LL_err_message(errorList, TRUE);
}
UBool IntlTest::printKnownIssues()
@@ -1045,8 +1083,12 @@
}
}
+void IntlTest::LL_err_message( const UnicodeString& message, UBool newline ) {
+ this->LL_message(message, newline, true);
+}
-void IntlTest::LL_message( UnicodeString message, UBool newline )
+
+void IntlTest::LL_message( UnicodeString message, UBool newline, UBool isErr )
{
// Synchronize this function.
// All error messages generated by tests funnel through here.
@@ -1080,6 +1122,7 @@
length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
if (length > 0) {
fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
+ if (isErr) currErr.append(buffer, length);
}
// replace each LineFeed by the indentation string
@@ -1090,11 +1133,13 @@
if (length > 0) {
length = length > 30000 ? 30000 : length;
fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
+ if (isErr) currErr.append(buffer, length);
}
if (newline) {
char newLine = '\n';
fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
+ if (isErr) currErr += newLine;
}
// A newline usually flushes the buffer, but
@@ -1424,8 +1469,7 @@
char* name = argv[i];
fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
- char baseName[1024];
- sprintf(baseName, "/%s/", name);
+ char baseName[1024] = "/";
char* parameter = strchr( name, '@' );
if (parameter) {
@@ -1518,7 +1562,12 @@
if(ctest_xml_fini())
return 1;
+#ifdef ZERO_EXIT_CODE_FOR_FAILURES
+ // Exit code 0 to indicate the test completed.
+ return 0;
+#else
return major.getErrors();
+#endif
}
const char* IntlTest::loadTestData(UErrorCode& err){
diff --git a/icu4c/source/test/intltest/intltest.h b/icu4c/source/test/intltest/intltest.h
index 902f721..995eae4 100644
--- a/icu4c/source/test/intltest/intltest.h
+++ b/icu4c/source/test/intltest/intltest.h
@@ -324,7 +324,7 @@
virtual int32_t IncDataErrorCount( void );
- virtual UBool callTest( IntlTest& testToBeCalled, char* par );
+ virtual UBool callTest( IntlTest& testToBeCalled, char* par, const char* basename = "");
UBool verbose;
@@ -354,8 +354,10 @@
int32_t numProps;
protected:
+ std::string currErr; // Error message of the current test case
- virtual void LL_message( UnicodeString message, UBool newline );
+ virtual void LL_err_message( const UnicodeString& message, UBool newline );
+ virtual void LL_message( UnicodeString message, UBool newlin, UBool isErr = FALSE );
// used for collation result reporting, defined here for convenience
diff --git a/icu4c/source/test/intltest/itmajor.cpp b/icu4c/source/test/intltest/itmajor.cpp
index 84bee28..c7b54bd 100644
--- a/icu4c/source/test/intltest/itmajor.cpp
+++ b/icu4c/source/test/intltest/itmajor.cpp
@@ -56,7 +56,7 @@
if (exec) {
logln("TestSuite Utilities---"); logln();
IntlTestUtilities test;
- callTest( test, par );
+ callTest( test, par, name );
}
break;
@@ -65,7 +65,7 @@
if (exec) {
logln("TestSuite Normalize---"); logln();
IntlTestNormalize test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -75,7 +75,7 @@
if (exec) {
logln("TestSuite Collator---"); logln();
IntlTestCollator test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -85,7 +85,7 @@
if (exec) {
logln("TestSuite Regex---"); logln();
RegexTest test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -95,7 +95,7 @@
if (exec) {
logln("TestSuite Format---"); logln();
IntlTestFormat test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -105,7 +105,7 @@
if (exec) {
logln("TestSuite Transliterator---"); logln();
IntlTestTransliterator test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -115,7 +115,7 @@
if (exec) {
logln("TestSuite RuleBasedBreakIterator---"); logln();
IntlTestRBBI test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -124,7 +124,7 @@
if (exec) {
logln("TestSuite RuleBasedNumberFormat----"); logln();
IntlTestRBNF test;
- callTest(test, par);
+ callTest(test, par, name);
}
#endif
break;
@@ -133,7 +133,7 @@
if (exec) {
logln("TestSuite RuleBasedNumberFormat RT----"); logln();
RbnfRoundTripTest test;
- callTest(test, par);
+ callTest(test, par, name);
}
#endif
break;
@@ -143,7 +143,7 @@
if (exec) {
logln("TestSuite ICUService---"); logln();
ICUServiceTest test;
- callTest(test, par);
+ callTest(test, par, name);
}
#endif
break;
@@ -152,7 +152,7 @@
if(exec){
logln("TestSuite IDNA----"); logln();
TestIDNA test;
- callTest(test,par);
+ callTest(test,par, name);
}
#endif
break;
@@ -161,7 +161,7 @@
if (exec) {
logln("TestSuite Conversion---"); logln();
ConversionTest test;
- callTest( test, par );
+ callTest( test, par, name );
}
#endif
break;
@@ -171,7 +171,7 @@
if (exec) {
logln("TestSuite RuleBasedNumberParse ----"); logln();
IntlTestRBNFParse test;
- callTest(test, par);
+ callTest(test, par, name);
}
#endif
break;
@@ -180,7 +180,7 @@
if (exec) {
logln("TestSuite CharsetDetection---"); logln();
CharsetDetectionTest test;
- callTest(test, par);
+ callTest(test, par, name);
}
break;
@@ -191,7 +191,7 @@
if (exec) {
logln("TestSuite SpoofDetection---"); logln();
IntlTestSpoof test;
- callTest(test, par);
+ callTest(test, par, name);
}
#else
name = "skip";
@@ -202,7 +202,7 @@
if (exec) {
logln("TestSuite bidi---"); logln();
LocalPointer<IntlTest> test(createBiDiConformanceTest());
- callTest(*test, par);
+ callTest(*test, par, name);
}
break;
diff --git a/icu4c/source/tools/ctestfw/ctest.c b/icu4c/source/tools/ctestfw/ctest.c
index b56c85b..7608c28 100644
--- a/icu4c/source/tools/ctestfw/ctest.c
+++ b/icu4c/source/tools/ctestfw/ctest.c
@@ -1334,7 +1334,7 @@
ctest_xml_testcase(const char *classname, const char *name, const char *timeSeconds, const char *failMsg) {
if(!XML_FILE) return 0;
- fprintf(XML_FILE, "\t<testcase classname=\"%s:%s\" name=\"%s:%s\" time=\"%s\"", XML_PREFIX, classname, XML_PREFIX, name, timeSeconds);
+ fprintf(XML_FILE, "\t<testcase classname=\"%s\" name=\"%s\" time=\"%s\"", name, classname, timeSeconds);
if(failMsg) {
fprintf(XML_FILE, ">\n\t\t<failure type=\"err\" message=\"%s\"/>\n\t</testcase>\n", failMsg);
} else {