From a7c0726f935e65de60da05397045238c3c416e17 Mon Sep 17 00:00:00 2001
From: "Steven R. Loomis" <srl@icu-project.org>
Date: Fri, 14 Oct 2011 19:00:49 +0000
Subject: [PATCH] ICU-8802 improve robustness, also test against stdio
 sscanf/sprintf for doubles

X-SVN-Rev: 30823
---
 .../test/perf/DateFmtPerf/DateFmtPerf.cpp     | 84 ++++++++++++-------
 .../test/perf/DateFmtPerf/DateFmtPerf.h       | 63 ++++++++++++++
 2 files changed, 117 insertions(+), 30 deletions(-)

diff --git a/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.cpp b/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.cpp
index afb98212443..909ec6de3a0 100644
--- a/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.cpp
+++ b/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.cpp
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-* Copyright (c) 2002-2010,International Business Machines
+* Copyright (c) 2002-2011,International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 **********************************************************************
@@ -33,11 +33,11 @@ UPerfFunction* DateFormatPerfTest::runIndexedTest(int32_t index, UBool exec,cons
     switch (index) {
         TESTCASE(0,DateFmt250);
         TESTCASE(1,DateFmt10000);
-		TESTCASE(2,DateFmt100000);
+        TESTCASE(2,DateFmt100000);
         TESTCASE(3,BreakItWord250);
-		TESTCASE(4,BreakItWord10000);
-		TESTCASE(5,BreakItChar250);
-		TESTCASE(6,BreakItChar10000);
+        TESTCASE(4,BreakItWord10000);
+        TESTCASE(5,BreakItChar250);
+        TESTCASE(6,BreakItChar10000);
         TESTCASE(7,NumFmt10000);
         TESTCASE(8,NumFmt100000);
         TESTCASE(9,Collation10000);
@@ -122,49 +122,73 @@ int main(int argc, const char* argv[]){
 		cout << "ICU version - " << U_ICU_VERSION << endl;
         UErrorCode status = U_ZERO_ERROR;
 
+#define FUNCTION_COUNT 6
         // Declare functions
-        UPerfFunction *functions[5];
+        UPerfFunction *functions[FUNCTION_COUNT];
+
         functions[0] = new DateFmtFunction(40, "en");
         functions[1] = new BreakItFunction(10000, true); // breakIterator word
         functions[2] = new BreakItFunction(10000, false); // breakIterator char
         functions[3] = new NumFmtFunction(100000, "en");
         functions[4] = new CollationFunction(400, "en");
-        
-        // Perform time recording
-        double t[5];
-        for(int i = 0; i < 5; i++) t[i] = 0;
+        functions[5] = new StdioNumFmtFunction(100000, "en");
 
-        for(int i = 0; i < 10; i++)
-            for(int j = 0; j < 5; j++)
-               t[j] += (functions[j]->time(1, &status) / 10);
+        // Perform time recording
+        double t[FUNCTION_COUNT];
+        for(int i = 0; i < FUNCTION_COUNT; i++) t[i] = 0;
+
+#define ITER_COUNT 10
+#ifdef U_DEBUG
+        cout << "Doing " << ITER_COUNT << " iterations:" << endl;
+        cout << "__________| Running...\r";
+        cout.flush();
+#endif
+        for(int i = 0; i < ITER_COUNT; i++) {
+#ifdef U_DEBUG
+          cout << '*' << flush;
+#endif
+          for(int j = 0; U_SUCCESS(status)&& j < FUNCTION_COUNT; j++)
+            t[j] += (functions[j]->time(1, &status) / ITER_COUNT);
+        }
+#ifdef U_DEBUG
+        cout << " Done                   " << endl;
+#endif
 
+        if(U_SUCCESS(status)) {
 
-        // Output results as .xml
-        ofstream out;
-        out.open(argv[2]);
+          // Output results as .xml
+          ofstream out;
+          out.open(argv[2]);
 
-        out << "<perfTestResults icu=\"c\" version=\"" << U_ICU_VERSION << "\">" << endl;
+          out << "<perfTestResults icu=\"c\" version=\"" << U_ICU_VERSION << "\">" << endl;
 
-        for(int i = 0; i < 5; i++)
-        {
-            out << "    <perfTestResult" << endl;
-            out << "        test=\"";
-            switch(i)
+          for(int i = 0; i < FUNCTION_COUNT; i++)
             {
+              out << "    <perfTestResult" << endl;
+              out << "        test=\"";
+              switch(i)
+                {
                 case 0: out << "DateFormat"; break;
                 case 1: out << "BreakIterator Word"; break;
                 case 2: out << "BreakIterator Char"; break;
                 case 3: out << "NumbFormat"; break;
                 case 4: out << "Collation"; break;
+                case 5: out << "StdioNumbFormat"; break;
+                default: out << "Unknown "  << i; break;
+                }
+              out << "\"" << endl;
+              out << "        iterations=\"" << functions[i]->getOperationsPerIteration() << "\"" << endl;
+              out << "        time=\"" << t[i] << "\" />" << endl;
             }
-            out << "\"" << endl;
-            int iter = 10000;
-            if(i > 2) iter = 100000;
-            out << "        iterations=\"" << iter << "\"" << endl;
-            out << "        time=\"" << t[i] << "\" />" << endl;
+          out << "</perfTestResults>" << endl;
+          out.close();
+          cout << " Wrote to " << argv[2] << endl;
+        }
+
+        if(U_FAILURE(status)) {
+          cout << "Error! " << u_errorName(status) << endl;
+          return 1;
         }
-        out << "</perfTestResults>" << endl;
-        out.close();
 
         return 0;
     }
@@ -190,4 +214,4 @@ int main(int argc, const char* argv[]){
 	cout << "done!" << endl;
 
     return 0;
-}
\ No newline at end of file
+}
diff --git a/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.h b/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.h
index 2a87c43780b..7aeb316418d 100644
--- a/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.h
+++ b/icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.h
@@ -356,6 +356,69 @@ public:
     }
 };
 
+
+
+#define NUM_STRING "9876543210.123"
+#define NUM_NUM 9876543210.123
+class StdioNumFmtFunction : public UPerfFunction
+{
+
+ private:
+  int num;
+  char locale[25];
+ public:
+	
+  StdioNumFmtFunction()
+    {
+      num = -1;
+    }
+
+  StdioNumFmtFunction(int a, const char* loc)
+    {
+      num = a;
+      strcpy(locale, loc);
+    }
+
+  virtual void call(UErrorCode* status2)
+  {
+    Locale loc(locale);
+    UErrorCode status = U_ZERO_ERROR;
+        
+    // Parse a string.  The string uses the digits '0' through '9'
+    // and the decimal separator '.', standard in the US locale
+
+    double result;
+    char outbuf[500];
+    const char *str = NUM_STRING;
+        
+    for(int i = 0; i < num; i++)
+      {
+        if(sscanf(str, "%lg", &result)!=1) {
+          cout << "Failed Stdio: failed to sscanf" << endl;
+          *status2 = U_PARSE_ERROR;
+          return;
+        }
+
+        sprintf(outbuf, "%lg", result);
+      }
+    
+    if(result!=NUM_NUM) {
+      cout << "Failed Stdio: sscanf got wrong result, expected " << NUM_NUM << " got " << result << endl;
+      *status2 = U_PARSE_ERROR;
+    }
+    if(strcmp(str,NUM_STRING)) {
+      cout << "Failed Stdio: sprintf got wrong result, expected " << NUM_STRING << " got " << str << endl;
+      *status2 = U_PARSE_ERROR;
+    }
+  }
+ 
+  virtual long getOperationsPerIteration()
+  {
+    return num;
+  }
+    
+};
+
 class CollationFunction : public UPerfFunction
 {
 
-- 
2.40.0