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 
usage(const char * prog)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 
testMatch(const char * aName)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 
main(int argc,char * const * argv)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:
~HowExpensiveTest()149   virtual ~HowExpensiveTest(){}
150 protected:
HowExpensiveTest(const char * name,const char * file,int32_t line)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;
warmup()157   virtual void warmup() {  run(); }
158 public:
getName()159   virtual const char *getName() { return fName; }
160 public:
runTest(double * subTime)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 
runTests(double * subTime,double * marginOfError)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 
runTestOn(HowExpensiveTest & t)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:
~SieveTest()233   virtual ~SieveTest(){}
SieveTest()234   SieveTest():HowExpensiveTest("SieveTest",__FILE__,__LINE__){}
run()235   virtual int32_t run(){return 0;} // dummy
runTest(double * subTime)236   int32_t runTest(double *subTime) {
237     *subTime = uprv_getSieveTime(NULL);
238     return U_LOTS_OF_TIMES;
239   }
runTests(double * subTime,double * marginOfError)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:
getName()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:
initFmt()278   virtual UNumberFormat* initFmt() {
279     return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
280   }
getClassName()281   virtual const char *getClassName() {
282     return "NumTest";
283   }
284 public:
NumTest(const char * pat,const char * num,double expect,const char * FILE,int LINE)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   }
warmup()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   }
run()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   }
~NumTest()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:
getClassName()332   virtual const char *getClassName() {
333     sprintf(name2,"AttrNumTest:%d=%d", fAttr,fAttrValue);
334     return name2;
335   }
336 public:
AttrNumTest(const char * pat,const char * num,double expect,const char * FILE,int LINE,UNumberFormatAttribute attr,int32_t newValue)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   }
initFmt()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:
getClassName()360   virtual const char *getClassName() {
361     sprintf(name2,"NOXNumTest:%d=%d", fAttr,fAttrValue);
362     return name2;
363   }
364 public:
NOXNumTest(const char * pat,const char * num,double expect,const char * FILE,int LINE)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   }
initFmt()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:
getName()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:
initFmt()406   virtual UNumberFormat* initFmt() {
407     return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
408   }
getClassName()409   virtual const char *getClassName() {
410     return "NumFmtTest";
411   }
412 public:
NumFmtTest(const char * pat,const char * num,double expect,const char * FILE,int LINE)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   }
warmup()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   }
run()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   }
~NumFmtTest()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:
getName()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:
initFmt()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   }
getClassName()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:
NumFmtInt64Test(const char * pat,const char * num,int64_t expect,const char * FILE,int LINE,EMode mode)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   }
warmup()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   }
run()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   }
~NumFmtInt64Test()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:
getName()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:
initFmt()618   virtual UNumberFormat* initFmt() {
619     DecimalFormat *d = new DecimalFormat(setupStatus);
620     UParseError pe;
621     d->applyPattern(fPat, pe, setupStatus);
622     return (UNumberFormat*) d;
623   }
getClassName()624   virtual const char *getClassName() {
625     return "NumFmtStringPieceTest";
626   }
627 public:
NumFmtStringPieceTest(const char * pat,const char * num,const StringPiece & expect,const char * FILE,int LINE)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   }
warmup()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 
run()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   }
~NumFmtStringPieceTest()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 
runTests()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