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