1 /*
2  ***********************************************************************
3  * © 2016 and later: Unicode, Inc. and others.
4  * License & terms of use: http://www.unicode.org/copyright.html
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 
usage(const char * prog)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 
testMatch(const char * aName)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 
main(int argc,char * const * argv)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:
~HowExpensiveTest()154   virtual ~HowExpensiveTest(){}
155 protected:
HowExpensiveTest(const char * name,const char * file,int32_t line)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;
warmup()162   virtual void warmup() {  run(); }
163 public:
getName()164   virtual const char *getName() { return fName; }
165 public:
runTest(double * subTime)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 
runTests(double * subTime,double * marginOfError)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 
runTestOn(HowExpensiveTest & t)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:
~SieveTest()238   virtual ~SieveTest(){}
SieveTest()239   SieveTest():HowExpensiveTest("SieveTest",__FILE__,__LINE__){}
run()240   virtual int32_t run(){return 0;} // dummy
runTest(double * subTime)241   int32_t runTest(double *subTime) {
242     *subTime = uprv_getSieveTime(NULL);
243     return U_LOTS_OF_TIMES;
244   }
runTests(double * subTime,double * marginOfError)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:
getName()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:
initFmt()283   virtual UNumberFormat* initFmt() {
284     return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
285   }
getClassName()286   virtual const char *getClassName() {
287     return "NumTest";
288   }
289 public:
NumTest(const char * pat,const char * num,double expect,const char * FILE,int LINE)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   }
warmup()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   }
run()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   }
~NumTest()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:
getClassName()337   virtual const char *getClassName() {
338     sprintf(name2,"AttrNumTest:%d=%d", fAttr,fAttrValue);
339     return name2;
340   }
341 public:
AttrNumTest(const char * pat,const char * num,double expect,const char * FILE,int LINE,UNumberFormatAttribute attr,int32_t newValue)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   }
initFmt()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:
getClassName()365   virtual const char *getClassName() {
366     sprintf(name2,"NOXNumTest:%d=%d", fAttr,fAttrValue);
367     return name2;
368   }
369 public:
NOXNumTest(const char * pat,const char * num,double expect,const char * FILE,int LINE)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   }
initFmt()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:
getName()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:
initFmt()411   virtual UNumberFormat* initFmt() {
412     return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
413   }
getClassName()414   virtual const char *getClassName() {
415     return "NumFmtTest";
416   }
417 public:
NumFmtTest(const char * pat,const char * num,double expect,const char * FILE,int LINE)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   }
warmup()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   }
run()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   }
~NumFmtTest()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:
getName()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:
initFmt()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   }
getClassName()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:
NumFmtInt64Test(const char * pat,const char * num,int64_t expect,const char * FILE,int LINE,EMode mode)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   }
warmup()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   }
run()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   }
~NumFmtInt64Test()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:
getName()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:
initFmt()623   virtual UNumberFormat* initFmt() {
624     DecimalFormat *d = new DecimalFormat(setupStatus);
625     UParseError pe;
626     d->applyPattern(fPat, pe, setupStatus);
627     return (UNumberFormat*) d;
628   }
getClassName()629   virtual const char *getClassName() {
630     return "NumFmtStringPieceTest";
631   }
632 public:
NumFmtStringPieceTest(const char * pat,const char * num,const StringPiece & expect,const char * FILE,int LINE)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   }
warmup()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 
run()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   }
~NumFmtStringPieceTest()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 
runTests()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