Home | History | Annotate | Download | only in howExpensiveIs
      1 /*
      2  ***********************************************************************
      3  *  2016 and later: Unicode, Inc. and others.
      4  * License & terms of use: http://www.unicode.org/copyright.html#License
      5  ***********************************************************************
      6  ***********************************************************************
      7  * Copyright (c) 2011-2016,International Business Machines
      8  * Corporation and others.  All Rights Reserved.
      9  ***********************************************************************
     10  */
     11 #include <stdio.h>
     12 #include <string.h>
     13 
     14 #include "cmemory.h"
     15 #include "sieve.h"
     16 #include "unicode/utimer.h"
     17 #include "udbgutil.h"
     18 #include "unicode/ustring.h"
     19 #include "unicode/decimfmt.h"
     20 #include "unicode/udat.h"
     21 U_NAMESPACE_USE
     22 
     23 #if U_PLATFORM_IMPLEMENTS_POSIX
     24 #include <unistd.h>
     25 
     26 static void usage(const char *prog) {
     27   fprintf(stderr, "Usage: %s [ -f outfile.xml ] [ -t 'TestName' ]\n", prog);
     28 }
     29 #endif
     30 
     31 void runTests(void);
     32 
     33 #ifndef ITERATIONS
     34 #define ITERATIONS 5
     35 #endif
     36 
     37 #ifndef TEST_LOCALE
     38 #define TEST_LOCALE "en_US"
     39 #endif
     40 
     41 FILE *out = NULL;
     42 UErrorCode setupStatus = U_ZERO_ERROR;
     43 const char *outName = NULL;
     44 int listmode = 0;
     45 const char *testName = NULL;
     46 const char *progname = NULL;
     47 int errflg = 0;
     48 int testhit = 0;
     49 
     50 int testMatch(const char *aName) {
     51   if(testName==NULL) return 1;
     52   int len = strlen(testName);
     53   if(testName[len-1]=='*') {
     54     return strncmp(testName,aName,len-1);
     55   } else {
     56     return strcmp(testName,aName);
     57   }
     58 }
     59 
     60 int main(int argc, char * const * argv){
     61 #if U_DEBUG
     62   fprintf(stderr,"%s: warning: U_DEBUG is on.\n", argv[0]);
     63 #endif
     64 #if U_DEBUG
     65   {
     66     double m;
     67     double s = uprv_getSieveTime(&m);
     68     fprintf(stderr, "** Standard sieve time: %.9fs +/- %.9fs (%d iterations)\n", s,m, (int)U_LOTS_OF_TIMES);
     69   }
     70 #endif
     71 
     72 #if U_PLATFORM_IMPLEMENTS_POSIX
     73   int c;
     74   //extern int optind;
     75   extern char *optarg;
     76   while((c=getopt(argc,argv,"lf:t:")) != EOF) {
     77     switch(c) {
     78     case 'f':
     79       outName = optarg;
     80       break;
     81     case 'l':
     82       listmode++;
     83       break;
     84     case 't':
     85       testName = optarg;
     86       break;
     87     case '?':
     88       errflg++;
     89     }
     90     if(errflg) {
     91       usage(progname);
     92       return 0;
     93     }
     94   }
     95   /* for ( ; optind < argc; optind++) {     ... argv[optind] } */
     96 #else
     97   if(argc==2) {
     98     outName = argv[1];
     99   } else if(argc>2) {
    100     fprintf(stderr, "Err: usage: %s [ output-file.xml ]\n", argv[0]);
    101   }
    102 #endif
    103 
    104     if(listmode && outName != NULL ) {
    105       fprintf(stderr, "Warning: no output when list mode\n");
    106       outName=NULL;
    107     }
    108 
    109   if(outName != NULL) {
    110 
    111 
    112     out=fopen(outName,"w");
    113     if(out==NULL) {
    114       fprintf(stderr,"Err: can't open %s for writing.\n", outName);
    115       return 1;
    116     } else {
    117       fprintf(stderr, "# writing results to %s\n", outName);
    118     }
    119     fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
    120     fprintf(out, "<tests icu=\"%s\">\n", U_ICU_VERSION);
    121     fprintf(out, "<!-- %s -->\n", U_COPYRIGHT_STRING);
    122   } else {
    123     fprintf(stderr, "# (no output)\n");
    124   }
    125 
    126   if(listmode && testName!=NULL) {
    127     fprintf(stderr, "ERR: no -l mode when specific test with -t\n");
    128     usage(progname);
    129     return 1;
    130   }
    131 
    132 
    133   runTests();
    134 
    135 
    136   if(out!=NULL) {
    137 #ifndef SKIP_INFO
    138     udbg_writeIcuInfo(out);
    139 #endif
    140     fprintf(out, "</tests>\n");
    141     fclose(out);
    142   }
    143 
    144   if(U_FAILURE(setupStatus)) {
    145     fprintf(stderr, "Error in tests: %s\n", u_errorName(setupStatus));
    146     return 1;
    147   }
    148 
    149   return 0;
    150 }
    151 
    152 class HowExpensiveTest {
    153 public:
    154   virtual ~HowExpensiveTest(){}
    155 protected:
    156   HowExpensiveTest(const char *name, const char *file, int32_t line) : fName(name), fFile(file), fLine(line) {}
    157 protected:
    158   /**
    159    * @return number of iterations
    160    */
    161   virtual int32_t run() = 0;
    162   virtual void warmup() {  run(); }
    163 public:
    164   virtual const char *getName() { return fName; }
    165 public:
    166   virtual int32_t runTest(double *subTime) {
    167     UTimer a,b;
    168     utimer_getTime(&a);
    169     int32_t iter = run();
    170     utimer_getTime(&b);
    171     *subTime = utimer_getDeltaSeconds(&a,&b);
    172     return iter;
    173   }
    174 
    175   virtual int32_t runTests(double *subTime, double *marginOfError) {
    176     warmup(); /* warmup */
    177     double times[ITERATIONS];
    178     int subIterations = 0;
    179     for(int i=0;i<ITERATIONS;i++) {
    180       subIterations = runTest(&times[i]);
    181 #if U_DEBUG
    182       fprintf(stderr, "trial: %d/%d = %.9fs\n", i, ITERATIONS,times[i]);
    183       fflush(stderr);
    184 #endif
    185     }
    186     uint32_t iterations = ITERATIONS;
    187     *subTime = uprv_getMeanTime(times,&iterations,marginOfError);
    188     return subIterations;
    189   }
    190 public:
    191   const char *fName;
    192   const char *fFile;
    193   int32_t fLine;
    194   int32_t fIterations;
    195 };
    196 
    197 void runTestOn(HowExpensiveTest &t) {
    198   if(U_FAILURE(setupStatus)) return; // silently
    199   const char *tn = t.getName();
    200   if(testName!=NULL && testMatch(tn)) return; // skipped.
    201   if(listmode) {
    202     fprintf(stderr, "%s:%d:\t%s\n", t.fFile, t.fLine, t.getName());
    203     testhit++;
    204     return;
    205   } else {
    206     fprintf(stderr, "%s:%d: Running: %s\n", t.fFile, t.fLine, t.getName());
    207     testhit++;
    208   }
    209   double sieveTime = uprv_getSieveTime(NULL);
    210   double st;
    211   double me;
    212 
    213   fflush(stdout);
    214   fflush(stderr);
    215   int32_t iter = t.runTests(&st,&me);
    216   if(U_FAILURE(setupStatus)) {
    217     fprintf(stderr, "Error in tests: %s\n", u_errorName(setupStatus));
    218     return;
    219   }
    220   fflush(stdout);
    221   fflush(stderr);
    222 
    223   double stn = st/sieveTime;
    224 
    225   printf("%s\t%.9f\t%.9f +/- %.9f,  @ %d iter\n", t.getName(),stn,st,me,iter);
    226 
    227   if(out!=NULL) {
    228     fprintf(out, "   <test name=\"%s\" standardizedTime=\"%f\" realDuration=\"%f\" marginOfError=\"%f\" iterations=\"%d\" />\n",
    229             tn,stn,st,me,iter);
    230     fflush(out);
    231   }
    232 }
    233 
    234 /* ------------------- test code here --------------------- */
    235 
    236 class SieveTest : public HowExpensiveTest {
    237 public:
    238   virtual ~SieveTest(){}
    239   SieveTest():HowExpensiveTest("SieveTest",__FILE__,__LINE__){}
    240   virtual int32_t run(){return 0;} // dummy
    241   int32_t runTest(double *subTime) {
    242     *subTime = uprv_getSieveTime(NULL);
    243     return U_LOTS_OF_TIMES;
    244   }
    245   virtual int32_t runTests(double *subTime, double *marginOfError) {
    246     *subTime = uprv_getSieveTime(marginOfError);
    247     return U_LOTS_OF_TIMES;
    248   }
    249 };
    250 
    251 
    252 /* ------- NumParseTest ------------- */
    253 #include "unicode/unum.h"
    254 /* open and close tests */
    255 #define OCName(svc,ub,testn,suffix,n) testn ## svc ## ub ## suffix ## n
    256 #define OCStr(svc,ub,suffix,n) "Test_" # svc # ub # suffix # n
    257 #define OCRun(svc,ub,suffix) svc ## ub ## suffix
    258 // TODO: run away screaming
    259 #define OpenCloseTest(n, svc,suffix,c,a,d) class OCName(svc,_,Test_,suffix,n) : public HowExpensiveTest { public: OCName(svc,_,Test_,suffix,n)():HowExpensiveTest(OCStr(svc,_,suffix,n),__FILE__,__LINE__) c int32_t run() { int32_t i; for(i=0;i<U_LOTS_OF_TIMES;i++){ OCRun(svc,_,close) (  OCRun(svc,_,suffix) a );  } return i; }   void warmup() { OCRun(svc,_,close) ( OCRun(svc,_,suffix) a); } virtual ~ OCName(svc,_,Test_,suffix,n) () d };
    260 #define QuickTest(n,c,r,d)  class n : public HowExpensiveTest { public: n():HowExpensiveTest(#n,__FILE__,__LINE__) c int32_t run() r virtual ~n () d };
    261 
    262 class NumTest : public HowExpensiveTest {
    263 private:
    264   double fExpect;
    265   UNumberFormat *fFmt;
    266   UnicodeString fPat;
    267   UnicodeString fString;
    268   const UChar *fStr;
    269   int32_t fLen;
    270   const char *fFile;
    271   int fLine;
    272   const char *fCPat;
    273   const char *fCStr;
    274   char name[100];
    275 public:
    276   virtual const char *getName() {
    277     if(name[0]==0) {
    278       sprintf(name,"%s:p=|%s|,str=|%s|",getClassName(),fCPat,fCStr);
    279     }
    280     return name;
    281   }
    282 protected:
    283   virtual UNumberFormat* initFmt() {
    284     return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
    285   }
    286   virtual const char *getClassName() {
    287     return "NumTest";
    288   }
    289 public:
    290   NumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE)
    291     : HowExpensiveTest("(n/a)",FILE, LINE),
    292       fExpect(expect),
    293       fFmt(0),
    294       fPat(pat, -1, US_INV),
    295       fString(num,-1,US_INV),
    296       fStr(fString.getTerminatedBuffer()),
    297       fLen(u_strlen(fStr)),
    298       fFile(FILE),
    299       fLine(LINE),
    300       fCPat(pat),
    301       fCStr(num)
    302   {
    303     name[0]=0;
    304   }
    305   void warmup() {
    306     fFmt = initFmt();
    307     if(U_SUCCESS(setupStatus)) {
    308       double trial = unum_parseDouble(fFmt,fStr,fLen, NULL, &setupStatus);
    309       if(U_SUCCESS(setupStatus) && trial!=fExpect) {
    310         setupStatus = U_INTERNAL_PROGRAM_ERROR;
    311         printf("%s:%d: warmup() %s got %.8f expected %.8f\n",
    312                fFile,fLine,getName(),trial,fExpect);
    313       }
    314     }
    315   }
    316   int32_t run() {
    317     double trial=0.0;
    318     int i;
    319     for(i=0;i<U_LOTS_OF_TIMES;i++){
    320       trial = unum_parse(fFmt,fStr,fLen, NULL, &setupStatus);
    321     }
    322     return i;
    323   }
    324   virtual ~NumTest(){}
    325 };
    326 
    327 #define DO_NumTest(p,n,x) { NumTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
    328 
    329 
    330 class AttrNumTest : public NumTest
    331 {
    332 private:
    333   UNumberFormatAttribute fAttr;
    334   int32_t fAttrValue;
    335   char name2[100];
    336 protected:
    337   virtual const char *getClassName() {
    338     sprintf(name2,"AttrNumTest:%d=%d", fAttr,fAttrValue);
    339     return name2;
    340   }
    341 public:
    342   AttrNumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE, UNumberFormatAttribute attr, int32_t newValue)
    343     : NumTest(pat,num,expect,FILE,LINE),
    344       fAttr(attr),
    345       fAttrValue(newValue)
    346   {
    347   }
    348   virtual UNumberFormat* initFmt() {
    349     UNumberFormat *fmt = NumTest::initFmt();
    350     unum_setAttribute(fmt, fAttr,fAttrValue);
    351     return fmt;
    352   }
    353 };
    354 
    355 #define DO_AttrNumTest(p,n,x,a,v) { AttrNumTest t(p,n,x,__FILE__,__LINE__,a,v); runTestOn(t); }
    356 
    357 
    358 class NOXNumTest : public NumTest
    359 {
    360 private:
    361   UNumberFormatAttribute fAttr;
    362   int32_t fAttrValue;
    363   char name2[100];
    364 protected:
    365   virtual const char *getClassName() {
    366     sprintf(name2,"NOXNumTest:%d=%d", fAttr,fAttrValue);
    367     return name2;
    368   }
    369 public:
    370   NOXNumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE /*, UNumberFormatAttribute attr, int32_t newValue */)
    371     : NumTest(pat,num,expect,FILE,LINE) /* ,
    372       fAttr(attr),
    373       fAttrValue(newValue) */
    374   {
    375   }
    376   virtual UNumberFormat* initFmt() {
    377     UNumberFormat *fmt = NumTest::initFmt();
    378     //unum_setAttribute(fmt, fAttr,fAttrValue);
    379     return fmt;
    380   }
    381 };
    382 
    383 #define DO_NOXNumTest(p,n,x) { NOXNumTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
    384 
    385 #define DO_TripleNumTest(p,n,x) DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_YES) \
    386                                 DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_NO) \
    387                                 DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_MAYBE)
    388 
    389 
    390 class NumFmtTest : public HowExpensiveTest {
    391 private:
    392   double fExpect;
    393   UNumberFormat *fFmt;
    394   UnicodeString fPat;
    395   UnicodeString fString;
    396   const UChar *fStr;
    397   int32_t fLen;
    398   const char *fFile;
    399   int fLine;
    400   const char *fCPat;
    401   const char *fCStr;
    402   char name[100];
    403 public:
    404   virtual const char *getName() {
    405     if(name[0]==0) {
    406       sprintf(name,"%s:p=|%s|,str=|%s|",getClassName(),fCPat,fCStr);
    407     }
    408     return name;
    409   }
    410 protected:
    411   virtual UNumberFormat* initFmt() {
    412     return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
    413   }
    414   virtual const char *getClassName() {
    415     return "NumFmtTest";
    416   }
    417 public:
    418   NumFmtTest(const char *pat, const char *num, double expect, const char *FILE, int LINE)
    419     : HowExpensiveTest("(n/a)",FILE, LINE),
    420       fExpect(expect),
    421       fFmt(0),
    422       fPat(pat, -1, US_INV),
    423       fString(num,-1,US_INV),
    424       fStr(fString.getTerminatedBuffer()),
    425       fLen(u_strlen(fStr)),
    426       fFile(FILE),
    427       fLine(LINE),
    428       fCPat(pat),
    429       fCStr(num)
    430   {
    431     name[0]=0;
    432   }
    433   void warmup() {
    434     fFmt = initFmt();
    435     UChar buf[100];
    436     if(U_SUCCESS(setupStatus)) {
    437       int32_t trial = unum_formatDouble(fFmt,fExpect, buf, 100, NULL, &setupStatus);
    438       if(!U_SUCCESS(setupStatus)
    439          || trial!=fLen
    440          ||trial<=0
    441          || u_strncmp(fStr,buf,trial)  ) {
    442         char strBuf[200];
    443         u_strToUTF8(strBuf,200,NULL,buf,trial+1,&setupStatus);
    444         printf("%s:%d: warmup() %s got %s expected %s, err %s\n",
    445                fFile,fLine,getName(),strBuf,fCStr, u_errorName(setupStatus));
    446         setupStatus = U_INTERNAL_PROGRAM_ERROR;
    447       }
    448     }
    449   }
    450   int32_t run() {
    451     int32_t trial;
    452     int i;
    453     UChar buf[100];
    454     if(U_SUCCESS(setupStatus)) {
    455       for(i=0;i<U_LOTS_OF_TIMES;i++){
    456         trial = unum_formatDouble(fFmt,fExpect, buf, 100, NULL, &setupStatus);
    457       }
    458     }
    459     return i;
    460   }
    461   virtual ~NumFmtTest(){}
    462 };
    463 
    464 #define DO_NumFmtTest(p,n,x) { NumFmtTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
    465 
    466 class NumFmtInt64Test : public HowExpensiveTest {
    467 public:
    468   enum EMode {
    469     kDefault,
    470     kPattern,
    471     kApplyPattern,
    472     kGroupOff,
    473     kApplyGroupOff
    474   };
    475 private:
    476   EMode   fMode;
    477   int64_t fExpect;
    478   UNumberFormat *fFmt;
    479   UnicodeString fPat;
    480   UnicodeString fString;
    481   const UChar *fStr;
    482   int32_t fLen;
    483   const char *fFile;
    484   int fLine;
    485   const char *fCPat;
    486   const char *fCStr;
    487   char name[100];
    488 public:
    489   virtual const char *getName() {
    490     if(name[0]==0) {
    491       sprintf(name,"%s:p=|%s|,str=|%s|",getClassName(),fCPat,fCStr);
    492     }
    493     return name;
    494   }
    495 protected:
    496   virtual UNumberFormat* initFmt() {
    497     switch(fMode) {
    498     case kPattern:
    499       return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
    500     case kApplyPattern:
    501       {
    502         UNumberFormat *fmt = unum_open(UNUM_DECIMAL, NULL, -1, TEST_LOCALE, 0, &setupStatus);
    503         unum_applyPattern(fmt, FALSE, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
    504         return fmt;
    505       }
    506     case kGroupOff:
    507       {
    508         UNumberFormat *fmt = unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
    509         unum_setAttribute(fmt, UNUM_GROUPING_USED, UNUM_NO);
    510         return fmt;
    511       }
    512     case kApplyGroupOff:
    513       {
    514         UNumberFormat *fmt = unum_open(UNUM_DECIMAL, NULL, -1, TEST_LOCALE, 0, &setupStatus);
    515         unum_applyPattern(fmt, FALSE, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
    516         unum_setAttribute(fmt, UNUM_GROUPING_USED, UNUM_NO);
    517         return fmt;
    518       }
    519     default:
    520     case kDefault:
    521       return unum_open(UNUM_DEFAULT, NULL, -1, TEST_LOCALE, 0, &setupStatus);
    522     }
    523   }
    524   virtual const char *getClassName() {
    525     switch(fMode) {
    526     case EMode::kDefault:
    527       return "NumFmtInt64Test (default)";
    528     case EMode::kPattern:
    529       return "NumFmtInt64Test (pattern)";
    530     case EMode::kApplyPattern:
    531       return "NumFmtInt64Test (applypattern)";
    532     case EMode::kGroupOff:
    533       return "NumFmtInt64Test (pattern, group=off)";
    534     case EMode::kApplyGroupOff:
    535       return "NumFmtInt64Test (applypattern, group=off)";
    536     default:
    537       return "NumFmtInt64Test (? ? ?)";
    538     }
    539   }
    540 public:
    541   NumFmtInt64Test(const char *pat, const char *num, int64_t expect, const char *FILE, int LINE, EMode mode)
    542     : HowExpensiveTest("(n/a)",FILE, LINE),
    543       fMode(mode),
    544       fExpect(expect),
    545       fFmt(0),
    546       fPat(pat, -1, US_INV),
    547       fString(num,-1,US_INV),
    548       fStr(fString.getTerminatedBuffer()),
    549       fLen(u_strlen(fStr)),
    550       fFile(FILE),
    551       fLine(LINE),
    552       fCPat(pat),
    553       fCStr(num)
    554   {
    555     name[0]=0;
    556   }
    557   void warmup() {
    558     fFmt = initFmt();
    559     UChar buf[100];
    560     if(U_SUCCESS(setupStatus)) {
    561       int32_t trial = unum_formatInt64(fFmt,fExpect, buf, 100, NULL, &setupStatus);
    562       if(!U_SUCCESS(setupStatus)
    563          || trial!=fLen
    564          ||trial<=0
    565          || u_strncmp(fStr,buf,trial)  ) {
    566         char strBuf[200];
    567         u_strToUTF8(strBuf,200,NULL,buf,trial+1,&setupStatus);
    568         printf("%s:%d: warmup() %s got %s (len %d) expected %s (len %d), err %s\n",
    569                fFile,fLine,getName(),strBuf,trial,fCStr,fLen, u_errorName(setupStatus));
    570         setupStatus = U_INTERNAL_PROGRAM_ERROR;
    571       }
    572     }
    573   }
    574   int32_t run() {
    575     int32_t trial;
    576     int i;
    577     UChar buf[100];
    578     if(U_SUCCESS(setupStatus)) {
    579       for(i=0;i<U_LOTS_OF_TIMES;i++){
    580         trial = unum_formatInt64(fFmt,fExpect, buf, 100, NULL, &setupStatus);
    581       }
    582     }
    583     return i;
    584   }
    585   virtual ~NumFmtInt64Test(){}
    586 };
    587 
    588 /**
    589  * unum_open .. with pattern, == new DecimalFormat(pattern)
    590  */
    591 #define DO_NumFmtInt64Test(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kPattern); runTestOn(t); }
    592 /**
    593  * unum_open(UNUM_DECIMAL), then
    594  */
    595 #define DO_NumFmtInt64Test_apply(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kApplyPattern); runTestOn(t); }
    596 
    597 #define DO_NumFmtInt64Test_default(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kDefault); runTestOn(t); }
    598 #define DO_NumFmtInt64Test_gr0(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kGroupOff); runTestOn(t); }
    599 #define DO_NumFmtInt64Test_applygr0(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kApplyGroupOff); runTestOn(t); }
    600 
    601 
    602 class NumFmtStringPieceTest : public HowExpensiveTest {
    603 private:
    604   const StringPiece &fExpect;
    605   UNumberFormat *fFmt;
    606   UnicodeString fPat;
    607   UnicodeString fString;
    608   const UChar *fStr;
    609   int32_t fLen;
    610   const char *fFile;
    611   int fLine;
    612   const char *fCPat;
    613   const char *fCStr;
    614   char name[100];
    615 public:
    616   virtual const char *getName() {
    617     if(name[0]==0) {
    618       sprintf(name,"%s:p=|%s|,str=|%s|,sp=|%s|",getClassName(),fCPat,fCStr, fExpect.data());
    619     }
    620     return name;
    621   }
    622 protected:
    623   virtual UNumberFormat* initFmt() {
    624     DecimalFormat *d = new DecimalFormat(setupStatus);
    625     UParseError pe;
    626     d->applyPattern(fPat, pe, setupStatus);
    627     return (UNumberFormat*) d;
    628   }
    629   virtual const char *getClassName() {
    630     return "NumFmtStringPieceTest";
    631   }
    632 public:
    633   NumFmtStringPieceTest(const char *pat, const char *num, const StringPiece& expect, const char *FILE, int LINE)
    634     : HowExpensiveTest("(n/a)",FILE, LINE),
    635       fExpect(expect),
    636       fFmt(0),
    637       fPat(pat, -1, US_INV),
    638       fString(num,-1,US_INV),
    639       fStr(fString.getTerminatedBuffer()),
    640       fLen(u_strlen(fStr)),
    641       fFile(FILE),
    642       fLine(LINE),
    643       fCPat(pat),
    644       fCStr(num)
    645   {
    646     name[0]=0;
    647   }
    648   void warmup() {
    649     fFmt = initFmt();
    650     UnicodeString buf;
    651     if(U_SUCCESS(setupStatus)) {
    652       buf.remove();
    653       ((const DecimalFormat*)fFmt)->format(fExpect, buf, NULL, setupStatus);
    654       if(!U_SUCCESS(setupStatus)
    655          || fString!=buf
    656          ) {
    657         char strBuf[200];
    658         u_strToUTF8(strBuf,200,NULL,buf.getTerminatedBuffer(),buf.length()+1,&setupStatus);
    659         printf("%s:%d: warmup() %s got %s (len %d) expected %s (len %d), err %s\n",
    660                fFile,fLine,getName(),strBuf,buf.length(),fCStr,fLen, u_errorName(setupStatus));
    661         setupStatus = U_INTERNAL_PROGRAM_ERROR;
    662       }
    663     }
    664   }
    665 
    666   int32_t run() {
    667 #if U_DEBUG
    668     int32_t trial;
    669 #endif
    670     int i=0;
    671     UnicodeString buf;
    672     if(U_SUCCESS(setupStatus)) {
    673       for(i=0;i<U_LOTS_OF_TIMES;i++){
    674         buf.remove();
    675         ((const DecimalFormat*)fFmt)->format(fExpect, buf, NULL, setupStatus);
    676       }
    677     }
    678     return i;
    679   }
    680   virtual ~NumFmtStringPieceTest(){}
    681 };
    682 
    683 #define DO_NumFmtStringPieceTest(p,n,x) { NumFmtStringPieceTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
    684 
    685 // TODO: move, scope.
    686 static UChar pattern[] = { 0x23 }; // '#'
    687 static UChar strdot[] = { '2', '.', '0', 0 };
    688 static UChar strspc[] = { '2', ' ', 0 };
    689 static UChar strgrp[] = {'2',',','2','2','2', 0 };
    690 static UChar strbeng[] = {0x09E8,0x09E8,0x09E8,0x09E8, 0 };
    691 
    692 UNumberFormat *NumParseTest_fmt;
    693 
    694 // TODO: de-uglify.
    695 QuickTest(NumParseTest,{    static UChar pattern[] = { 0x23 };    NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL,         pattern,                    1,                    TEST_LOCALE,                    0,                    &setupStatus);  },{    int32_t i;    static UChar str[] = { 0x31 };double val;    for(i=0;i<U_LOTS_OF_TIMES;i++) {      val=unum_parse(NumParseTest_fmt,str,1,NULL,&setupStatus);    }    return i;  },{unum_close(NumParseTest_fmt);})
    696 
    697 QuickTest(NumParseTestdot,{    static UChar pattern[] = { 0x23 };    NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL,         pattern,                    1,                    TEST_LOCALE,                    0,                    &setupStatus);  },{    int32_t i;  double val;    for(i=0;i<U_LOTS_OF_TIMES;i++) {      val=unum_parse(NumParseTest_fmt,strdot,1,NULL,&setupStatus);    }    return i;  },{unum_close(NumParseTest_fmt);})
    698 QuickTest(NumParseTestspc,{    static UChar pattern[] = { 0x23 };    NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL,         pattern,                    1,                    TEST_LOCALE,                    0,                    &setupStatus);  },{    int32_t i;    double val;    for(i=0;i<U_LOTS_OF_TIMES;i++) {      val=unum_parse(NumParseTest_fmt,strspc,1,NULL,&setupStatus);    }    return i;  },{unum_close(NumParseTest_fmt);})
    699 QuickTest(NumParseTestgrp,{    static UChar pattern[] = { 0x23 };    NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL,         pattern,                    1,                    TEST_LOCALE,                    0,                    &setupStatus);  },{    int32_t i;    double val;    for(i=0;i<U_LOTS_OF_TIMES;i++) {      val=unum_parse(NumParseTest_fmt,strgrp,-1,NULL,&setupStatus);    }    return i;  },{unum_close(NumParseTest_fmt);})
    700 
    701 QuickTest(NumParseTestbeng,{    static UChar pattern[] = { 0x23 };    NumParseTest_fmt = unum_open(UNUM_PATTERN_DECIMAL,         pattern,                    1,                    TEST_LOCALE,                    0,                    &setupStatus);  },{    int32_t i;    double val;    for(i=0;i<U_LOTS_OF_TIMES;i++) {      val=unum_parse(NumParseTest_fmt,strbeng,-1,NULL,&setupStatus);    }    return i;  },{unum_close(NumParseTest_fmt);})
    702 
    703 UDateFormat *DateFormatTest_fmt = NULL;
    704 UDate sometime = 100000000.0;
    705 UChar onekbuf[1024];
    706 const int32_t onekbuf_len = UPRV_LENGTHOF(onekbuf);
    707 
    708 
    709 QuickTest(DateFormatTestBasic, \
    710           { \
    711             DateFormatTest_fmt = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, -1, &setupStatus); \
    712           }, \
    713           { \
    714             int i; \
    715             for(i=0;i<U_LOTS_OF_TIMES;i++)  \
    716             { \
    717               udat_format(DateFormatTest_fmt, sometime, onekbuf, onekbuf_len, NULL, &setupStatus); \
    718             } \
    719             return i; \
    720           }, \
    721           { \
    722             udat_close(DateFormatTest_fmt); \
    723           } \
    724       )
    725 
    726 
    727 QuickTest(NullTest,{},{int j=U_LOTS_OF_TIMES;while(--j);return U_LOTS_OF_TIMES;},{})
    728 
    729 #if 0
    730 #include <time.h>
    731 
    732 QuickTest(RandomTest,{},{timespec ts; ts.tv_sec=rand()%4; int j=U_LOTS_OF_TIMES;while(--j) { ts.tv_nsec=100000+(rand()%10000)*1000000; nanosleep(&ts,NULL); return j;} return U_LOTS_OF_TIMES;},{})
    733 #endif
    734 
    735 OpenCloseTest(pattern,unum,open,{},(UNUM_PATTERN_DECIMAL,pattern,1,TEST_LOCALE,0,&setupStatus),{})
    736 OpenCloseTest(default,unum,open,{},(UNUM_DEFAULT,NULL,-1,TEST_LOCALE,0,&setupStatus),{})
    737 #if !UCONFIG_NO_CONVERSION
    738 #include "unicode/ucnv.h"
    739 OpenCloseTest(gb18030,ucnv,open,{},("gb18030",&setupStatus),{})
    740 #endif
    741 #include "unicode/ures.h"
    742 OpenCloseTest(root,ures,open,{},(NULL,"root",&setupStatus),{})
    743 
    744 void runTests() {
    745   {
    746     SieveTest t;
    747     runTestOn(t);
    748   }
    749 #if 0
    750   {
    751     RandomTest t;
    752     runTestOn(t);
    753   }
    754 #endif
    755   {
    756     NullTest t;
    757     runTestOn(t);
    758   }
    759 
    760 #ifndef SKIP_DATEFMT_TESTS
    761   {
    762     DateFormatTestBasic t;
    763     runTestOn(t);
    764   }
    765 #endif
    766 
    767 #ifndef SKIP_NUMPARSE_TESTS
    768   {
    769     // parse tests
    770 
    771     DO_NumTest("#","0",0.0);
    772     DO_NumTest("#","2.0",2.0);
    773     DO_NumTest("#","2 ",2);
    774     DO_NumTest("#","-2 ",-2);
    775     DO_NumTest("+#","+2",2);
    776     DO_NumTest("#,###.0","2222.0",2222.0);
    777     DO_NumTest("#.0","1.000000000000000000000000000000000000000000000000000000000000000000000000000000",1.0);
    778     DO_NumTest("#","123456",123456);
    779 
    780     // attr
    781 #ifdef HAVE_UNUM_MAYBE
    782     DO_AttrNumTest("#","0",0.0,UNUM_PARSE_ALL_INPUT,UNUM_YES);
    783     DO_AttrNumTest("#","0",0.0,UNUM_PARSE_ALL_INPUT,UNUM_NO);
    784     DO_AttrNumTest("#","0",0.0,UNUM_PARSE_ALL_INPUT,UNUM_MAYBE);
    785     DO_TripleNumTest("#","2.0",2.0);
    786     DO_AttrNumTest("#.0","1.000000000000000000000000000000000000000000000000000000000000000000000000000000",1.0,UNUM_PARSE_ALL_INPUT,UNUM_NO);
    787 #endif
    788 
    789 
    790     //  {    NumParseTestgrp t;    runTestOn(t);  }
    791     {    NumParseTestbeng t;    runTestOn(t);  }
    792 
    793   }
    794 #endif
    795 
    796 #ifndef SKIP_NUMFORMAT_TESTS
    797   // format tests
    798   {
    799 
    800     DO_NumFmtInt64Test("0000","0001",1);
    801     DO_NumFmtInt64Test("0000","0000",0);
    802     StringPiece sp3456("3456");
    803     DO_NumFmtStringPieceTest("0000","3456",sp3456);
    804     DO_NumFmtStringPieceTest("#","3456",sp3456);
    805     StringPiece sp3("3");
    806     DO_NumFmtStringPieceTest("0000","0003",sp3);
    807     DO_NumFmtStringPieceTest("#","3",sp3);
    808     StringPiece spn3("-3");
    809     DO_NumFmtStringPieceTest("0000","-0003",spn3);
    810     DO_NumFmtStringPieceTest("#","-3",spn3);
    811     StringPiece spPI("123.456");
    812     DO_NumFmtStringPieceTest("#.0000","123.4560",spPI);
    813     DO_NumFmtStringPieceTest("#.00","123.46",spPI);
    814 
    815     DO_NumFmtTest("#","0",0.0);
    816     DO_NumFmtTest("#","12345",12345);
    817     DO_NumFmtTest("#","-2",-2);
    818     DO_NumFmtTest("+#","+2",2);
    819 
    820     DO_NumFmtInt64Test("#","-682",-682);
    821     DO_NumFmtInt64Test("#","0",0);
    822     DO_NumFmtInt64Test("#","12345",12345);
    823     DO_NumFmtInt64Test("#,###","12,345",12345);
    824     DO_NumFmtInt64Test("#","1234",1234);
    825     DO_NumFmtInt64Test("#","123",123);
    826     DO_NumFmtInt64Test("#,###","123",123);
    827     DO_NumFmtInt64Test_apply("#","123",123);
    828     DO_NumFmtInt64Test_apply("#","12345",12345);
    829     DO_NumFmtInt64Test_apply("#,###","123",123);
    830     DO_NumFmtInt64Test_apply("#,###","12,345",12345);
    831     DO_NumFmtInt64Test_default("","123",123);
    832     DO_NumFmtInt64Test_default("","12,345",12345);
    833     DO_NumFmtInt64Test_applygr0("#","123",123);
    834     DO_NumFmtInt64Test_applygr0("#","12345",12345);
    835     DO_NumFmtInt64Test_applygr0("#,###","123",123);
    836     DO_NumFmtInt64Test_applygr0("#,###","12345",12345);
    837     DO_NumFmtInt64Test_gr0("#","123",123);
    838     DO_NumFmtInt64Test_gr0("#","12345",12345);
    839     DO_NumFmtInt64Test_gr0("#,###","123",123);
    840     DO_NumFmtInt64Test_gr0("#,###","12345",12345);
    841     DO_NumFmtInt64Test("#","-2",-2);
    842     DO_NumFmtInt64Test("+#","+2",2);
    843   }
    844 
    845 #ifndef SKIP_NUM_OPEN_TEST
    846   {
    847     Test_unum_opendefault t;
    848     runTestOn(t);
    849   }
    850   {
    851     Test_unum_openpattern t;
    852     runTestOn(t);
    853   }
    854 #endif
    855 
    856 #endif /* skip numformat tests */
    857 #if !UCONFIG_NO_CONVERSION
    858   {
    859     Test_ucnv_opengb18030 t;
    860     runTestOn(t);
    861   }
    862 #endif
    863   {
    864     Test_ures_openroot t;
    865     runTestOn(t);
    866   }
    867 
    868   if(testhit==0) {
    869     fprintf(stderr, "ERROR: no tests matched.\n");
    870   }
    871 }
    872