1/*
2 ***********************************************************************
3 * © 2016 and later: Unicode, Inc. and others.
4 * License & terms of use: http://www.unicode.org/copyright.html#License
5 ***********************************************************************
6 ***********************************************************************
7 * Copyright (c) 2011-2016,International Business Machines
8 * Corporation and others.  All Rights Reserved.
9 ***********************************************************************
10 */
11#include <stdio.h>
12#include <string.h>
13
14#include "cmemory.h"
15#include "sieve.h"
16#include "unicode/utimer.h"
17#include "udbgutil.h"
18#include "unicode/ustring.h"
19#include "unicode/decimfmt.h"
20#include "unicode/udat.h"
21U_NAMESPACE_USE
22
23#if U_PLATFORM_IMPLEMENTS_POSIX
24#include <unistd.h>
25
26static void usage(const char *prog) {
27  fprintf(stderr, "Usage: %s [ -f outfile.xml ] [ -t 'TestName' ]\n", prog);
28}
29#endif
30
31void 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
41FILE *out = NULL;
42UErrorCode setupStatus = U_ZERO_ERROR;
43const char *outName = NULL;
44int listmode = 0;
45const char *testName = NULL;
46const char *progname = NULL;
47int errflg = 0;
48int testhit = 0;
49
50int 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
60int 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
152class HowExpensiveTest {
153public:
154  virtual ~HowExpensiveTest(){}
155protected:
156  HowExpensiveTest(const char *name, const char *file, int32_t line) : fName(name), fFile(file), fLine(line) {}
157protected:
158  /**
159   * @return number of iterations
160   */
161  virtual int32_t run() = 0;
162  virtual void warmup() {  run(); }
163public:
164  virtual const char *getName() { return fName; }
165public:
166  virtual int32_t runTest(double *subTime) {
167    UTimer a,b;
168    utimer_getTime(&a);
169    int32_t iter = run();
170    utimer_getTime(&b);
171    *subTime = utimer_getDeltaSeconds(&a,&b);
172    return iter;
173  }
174
175  virtual int32_t runTests(double *subTime, double *marginOfError) {
176    warmup(); /* warmup */
177    double times[ITERATIONS];
178    int subIterations = 0;
179    for(int i=0;i<ITERATIONS;i++) {
180      subIterations = runTest(&times[i]);
181#if U_DEBUG
182      fprintf(stderr, "trial: %d/%d = %.9fs\n", i, ITERATIONS,times[i]);
183      fflush(stderr);
184#endif
185    }
186    uint32_t iterations = ITERATIONS;
187    *subTime = uprv_getMeanTime(times,&iterations,marginOfError);
188    return subIterations;
189  }
190public:
191  const char *fName;
192  const char *fFile;
193  int32_t fLine;
194  int32_t fIterations;
195};
196
197void 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
236class SieveTest : public HowExpensiveTest {
237public:
238  virtual ~SieveTest(){}
239  SieveTest():HowExpensiveTest("SieveTest",__FILE__,__LINE__){}
240  virtual int32_t run(){return 0;} // dummy
241  int32_t runTest(double *subTime) {
242    *subTime = uprv_getSieveTime(NULL);
243    return U_LOTS_OF_TIMES;
244  }
245  virtual int32_t runTests(double *subTime, double *marginOfError) {
246    *subTime = uprv_getSieveTime(marginOfError);
247    return U_LOTS_OF_TIMES;
248  }
249};
250
251
252/* ------- NumParseTest ------------- */
253#include "unicode/unum.h"
254/* open and close tests */
255#define OCName(svc,ub,testn,suffix,n) testn ## svc ## ub ## suffix ## n
256#define OCStr(svc,ub,suffix,n) "Test_" # svc # ub # suffix # n
257#define OCRun(svc,ub,suffix) svc ## ub ## suffix
258// TODO: run away screaming
259#define OpenCloseTest(n, svc,suffix,c,a,d) class OCName(svc,_,Test_,suffix,n) : public HowExpensiveTest { public: OCName(svc,_,Test_,suffix,n)():HowExpensiveTest(OCStr(svc,_,suffix,n),__FILE__,__LINE__) c int32_t run() { int32_t i; for(i=0;i<U_LOTS_OF_TIMES;i++){ OCRun(svc,_,close) (  OCRun(svc,_,suffix) a );  } return i; }   void warmup() { OCRun(svc,_,close) ( OCRun(svc,_,suffix) a); } virtual ~ OCName(svc,_,Test_,suffix,n) () d };
260#define QuickTest(n,c,r,d)  class n : public HowExpensiveTest { public: n():HowExpensiveTest(#n,__FILE__,__LINE__) c int32_t run() r virtual ~n () d };
261
262class NumTest : public HowExpensiveTest {
263private:
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];
275public:
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  }
282protected:
283  virtual UNumberFormat* initFmt() {
284    return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
285  }
286  virtual const char *getClassName() {
287    return "NumTest";
288  }
289public:
290  NumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE)
291    : HowExpensiveTest("(n/a)",FILE, LINE),
292      fExpect(expect),
293      fFmt(0),
294      fPat(pat, -1, US_INV),
295      fString(num,-1,US_INV),
296      fStr(fString.getTerminatedBuffer()),
297      fLen(u_strlen(fStr)),
298      fFile(FILE),
299      fLine(LINE),
300      fCPat(pat),
301      fCStr(num)
302  {
303    name[0]=0;
304  }
305  void warmup() {
306    fFmt = initFmt();
307    if(U_SUCCESS(setupStatus)) {
308      double trial = unum_parseDouble(fFmt,fStr,fLen, NULL, &setupStatus);
309      if(U_SUCCESS(setupStatus) && trial!=fExpect) {
310        setupStatus = U_INTERNAL_PROGRAM_ERROR;
311        printf("%s:%d: warmup() %s got %.8f expected %.8f\n",
312               fFile,fLine,getName(),trial,fExpect);
313      }
314    }
315  }
316  int32_t run() {
317    double trial=0.0;
318    int i;
319    for(i=0;i<U_LOTS_OF_TIMES;i++){
320      trial = unum_parse(fFmt,fStr,fLen, NULL, &setupStatus);
321    }
322    return i;
323  }
324  virtual ~NumTest(){}
325};
326
327#define DO_NumTest(p,n,x) { NumTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
328
329
330class AttrNumTest : public NumTest
331{
332private:
333  UNumberFormatAttribute fAttr;
334  int32_t fAttrValue;
335  char name2[100];
336protected:
337  virtual const char *getClassName() {
338    sprintf(name2,"AttrNumTest:%d=%d", fAttr,fAttrValue);
339    return name2;
340  }
341public:
342  AttrNumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE, UNumberFormatAttribute attr, int32_t newValue)
343    : NumTest(pat,num,expect,FILE,LINE),
344      fAttr(attr),
345      fAttrValue(newValue)
346  {
347  }
348  virtual UNumberFormat* initFmt() {
349    UNumberFormat *fmt = NumTest::initFmt();
350    unum_setAttribute(fmt, fAttr,fAttrValue);
351    return fmt;
352  }
353};
354
355#define DO_AttrNumTest(p,n,x,a,v) { AttrNumTest t(p,n,x,__FILE__,__LINE__,a,v); runTestOn(t); }
356
357
358class NOXNumTest : public NumTest
359{
360private:
361  UNumberFormatAttribute fAttr;
362  int32_t fAttrValue;
363  char name2[100];
364protected:
365  virtual const char *getClassName() {
366    sprintf(name2,"NOXNumTest:%d=%d", fAttr,fAttrValue);
367    return name2;
368  }
369public:
370  NOXNumTest(const char *pat, const char *num, double expect, const char *FILE, int LINE /*, UNumberFormatAttribute attr, int32_t newValue */)
371    : NumTest(pat,num,expect,FILE,LINE) /* ,
372      fAttr(attr),
373      fAttrValue(newValue) */
374  {
375  }
376  virtual UNumberFormat* initFmt() {
377    UNumberFormat *fmt = NumTest::initFmt();
378    //unum_setAttribute(fmt, fAttr,fAttrValue);
379    return fmt;
380  }
381};
382
383#define DO_NOXNumTest(p,n,x) { NOXNumTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
384
385#define DO_TripleNumTest(p,n,x) DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_YES) \
386                                DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_NO) \
387                                DO_AttrNumTest(p,n,x,UNUM_PARSE_ALL_INPUT,UNUM_MAYBE)
388
389
390class NumFmtTest : public HowExpensiveTest {
391private:
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];
403public:
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  }
410protected:
411  virtual UNumberFormat* initFmt() {
412    return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
413  }
414  virtual const char *getClassName() {
415    return "NumFmtTest";
416  }
417public:
418  NumFmtTest(const char *pat, const char *num, double expect, const char *FILE, int LINE)
419    : HowExpensiveTest("(n/a)",FILE, LINE),
420      fExpect(expect),
421      fFmt(0),
422      fPat(pat, -1, US_INV),
423      fString(num,-1,US_INV),
424      fStr(fString.getTerminatedBuffer()),
425      fLen(u_strlen(fStr)),
426      fFile(FILE),
427      fLine(LINE),
428      fCPat(pat),
429      fCStr(num)
430  {
431    name[0]=0;
432  }
433  void warmup() {
434    fFmt = initFmt();
435    UChar buf[100];
436    if(U_SUCCESS(setupStatus)) {
437      int32_t trial = unum_formatDouble(fFmt,fExpect, buf, 100, NULL, &setupStatus);
438      if(!U_SUCCESS(setupStatus)
439         || trial!=fLen
440         ||trial<=0
441         || u_strncmp(fStr,buf,trial)  ) {
442        char strBuf[200];
443        u_strToUTF8(strBuf,200,NULL,buf,trial+1,&setupStatus);
444        printf("%s:%d: warmup() %s got %s expected %s, err %s\n",
445               fFile,fLine,getName(),strBuf,fCStr, u_errorName(setupStatus));
446        setupStatus = U_INTERNAL_PROGRAM_ERROR;
447      }
448    }
449  }
450  int32_t run() {
451    int32_t trial;
452    int i;
453    UChar buf[100];
454    if(U_SUCCESS(setupStatus)) {
455      for(i=0;i<U_LOTS_OF_TIMES;i++){
456        trial = unum_formatDouble(fFmt,fExpect, buf, 100, NULL, &setupStatus);
457      }
458    }
459    return i;
460  }
461  virtual ~NumFmtTest(){}
462};
463
464#define DO_NumFmtTest(p,n,x) { NumFmtTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
465
466class NumFmtInt64Test : public HowExpensiveTest {
467public:
468  enum EMode {
469    kDefault,
470    kPattern,
471    kApplyPattern,
472    kGroupOff,
473    kApplyGroupOff
474  };
475private:
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];
488public:
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  }
495protected:
496  virtual UNumberFormat* initFmt() {
497    switch(fMode) {
498    case kPattern:
499      return unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
500    case kApplyPattern:
501      {
502        UNumberFormat *fmt = unum_open(UNUM_DECIMAL, NULL, -1, TEST_LOCALE, 0, &setupStatus);
503        unum_applyPattern(fmt, FALSE, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
504        return fmt;
505      }
506    case kGroupOff:
507      {
508        UNumberFormat *fmt = unum_open(UNUM_PATTERN_DECIMAL, fPat.getTerminatedBuffer(), -1, TEST_LOCALE, 0, &setupStatus);
509        unum_setAttribute(fmt, UNUM_GROUPING_USED, UNUM_NO);
510        return fmt;
511      }
512    case kApplyGroupOff:
513      {
514        UNumberFormat *fmt = unum_open(UNUM_DECIMAL, NULL, -1, TEST_LOCALE, 0, &setupStatus);
515        unum_applyPattern(fmt, FALSE, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
516        unum_setAttribute(fmt, UNUM_GROUPING_USED, UNUM_NO);
517        return fmt;
518      }
519    default:
520    case kDefault:
521      return unum_open(UNUM_DEFAULT, NULL, -1, TEST_LOCALE, 0, &setupStatus);
522    }
523  }
524  virtual const char *getClassName() {
525    switch(fMode) {
526    case EMode::kDefault:
527      return "NumFmtInt64Test (default)";
528    case EMode::kPattern:
529      return "NumFmtInt64Test (pattern)";
530    case EMode::kApplyPattern:
531      return "NumFmtInt64Test (applypattern)";
532    case EMode::kGroupOff:
533      return "NumFmtInt64Test (pattern, group=off)";
534    case EMode::kApplyGroupOff:
535      return "NumFmtInt64Test (applypattern, group=off)";
536    default:
537      return "NumFmtInt64Test (? ? ?)";
538    }
539  }
540public:
541  NumFmtInt64Test(const char *pat, const char *num, int64_t expect, const char *FILE, int LINE, EMode mode)
542    : HowExpensiveTest("(n/a)",FILE, LINE),
543      fMode(mode),
544      fExpect(expect),
545      fFmt(0),
546      fPat(pat, -1, US_INV),
547      fString(num,-1,US_INV),
548      fStr(fString.getTerminatedBuffer()),
549      fLen(u_strlen(fStr)),
550      fFile(FILE),
551      fLine(LINE),
552      fCPat(pat),
553      fCStr(num)
554  {
555    name[0]=0;
556  }
557  void warmup() {
558    fFmt = initFmt();
559    UChar buf[100];
560    if(U_SUCCESS(setupStatus)) {
561      int32_t trial = unum_formatInt64(fFmt,fExpect, buf, 100, NULL, &setupStatus);
562      if(!U_SUCCESS(setupStatus)
563         || trial!=fLen
564         ||trial<=0
565         || u_strncmp(fStr,buf,trial)  ) {
566        char strBuf[200];
567        u_strToUTF8(strBuf,200,NULL,buf,trial+1,&setupStatus);
568        printf("%s:%d: warmup() %s got %s (len %d) expected %s (len %d), err %s\n",
569               fFile,fLine,getName(),strBuf,trial,fCStr,fLen, u_errorName(setupStatus));
570        setupStatus = U_INTERNAL_PROGRAM_ERROR;
571      }
572    }
573  }
574  int32_t run() {
575    int32_t trial;
576    int i;
577    UChar buf[100];
578    if(U_SUCCESS(setupStatus)) {
579      for(i=0;i<U_LOTS_OF_TIMES;i++){
580        trial = unum_formatInt64(fFmt,fExpect, buf, 100, NULL, &setupStatus);
581      }
582    }
583    return i;
584  }
585  virtual ~NumFmtInt64Test(){}
586};
587
588/**
589 * unum_open .. with pattern, == new DecimalFormat(pattern)
590 */
591#define DO_NumFmtInt64Test(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kPattern); runTestOn(t); }
592/**
593 * unum_open(UNUM_DECIMAL), then
594 */
595#define DO_NumFmtInt64Test_apply(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kApplyPattern); runTestOn(t); }
596
597#define DO_NumFmtInt64Test_default(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kDefault); runTestOn(t); }
598#define DO_NumFmtInt64Test_gr0(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kGroupOff); runTestOn(t); }
599#define DO_NumFmtInt64Test_applygr0(p,n,x) { NumFmtInt64Test t(p,n,x,__FILE__,__LINE__,NumFmtInt64Test::EMode::kApplyGroupOff); runTestOn(t); }
600
601
602class NumFmtStringPieceTest : public HowExpensiveTest {
603private:
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];
615public:
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  }
622protected:
623  virtual UNumberFormat* initFmt() {
624    DecimalFormat *d = new DecimalFormat(setupStatus);
625    UParseError pe;
626    d->applyPattern(fPat, pe, setupStatus);
627    return (UNumberFormat*) d;
628  }
629  virtual const char *getClassName() {
630    return "NumFmtStringPieceTest";
631  }
632public:
633  NumFmtStringPieceTest(const char *pat, const char *num, const StringPiece& expect, const char *FILE, int LINE)
634    : HowExpensiveTest("(n/a)",FILE, LINE),
635      fExpect(expect),
636      fFmt(0),
637      fPat(pat, -1, US_INV),
638      fString(num,-1,US_INV),
639      fStr(fString.getTerminatedBuffer()),
640      fLen(u_strlen(fStr)),
641      fFile(FILE),
642      fLine(LINE),
643      fCPat(pat),
644      fCStr(num)
645  {
646    name[0]=0;
647  }
648  void warmup() {
649    fFmt = initFmt();
650    UnicodeString buf;
651    if(U_SUCCESS(setupStatus)) {
652      buf.remove();
653      ((const DecimalFormat*)fFmt)->format(fExpect, buf, NULL, setupStatus);
654      if(!U_SUCCESS(setupStatus)
655         || fString!=buf
656         ) {
657        char strBuf[200];
658        u_strToUTF8(strBuf,200,NULL,buf.getTerminatedBuffer(),buf.length()+1,&setupStatus);
659        printf("%s:%d: warmup() %s got %s (len %d) expected %s (len %d), err %s\n",
660               fFile,fLine,getName(),strBuf,buf.length(),fCStr,fLen, u_errorName(setupStatus));
661        setupStatus = U_INTERNAL_PROGRAM_ERROR;
662      }
663    }
664  }
665
666  int32_t run() {
667#if U_DEBUG
668    int32_t trial;
669#endif
670    int i=0;
671    UnicodeString buf;
672    if(U_SUCCESS(setupStatus)) {
673      for(i=0;i<U_LOTS_OF_TIMES;i++){
674        buf.remove();
675        ((const DecimalFormat*)fFmt)->format(fExpect, buf, NULL, setupStatus);
676      }
677    }
678    return i;
679  }
680  virtual ~NumFmtStringPieceTest(){}
681};
682
683#define DO_NumFmtStringPieceTest(p,n,x) { NumFmtStringPieceTest t(p,n,x,__FILE__,__LINE__); runTestOn(t); }
684
685// TODO: move, scope.
686static UChar pattern[] = { 0x23 }; // '#'
687static UChar strdot[] = { '2', '.', '0', 0 };
688static UChar strspc[] = { '2', ' ', 0 };
689static UChar strgrp[] = {'2',',','2','2','2', 0 };
690static UChar strbeng[] = {0x09E8,0x09E8,0x09E8,0x09E8, 0 };
691
692UNumberFormat *NumParseTest_fmt;
693
694// TODO: de-uglify.
695QuickTest(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
697QuickTest(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);})
698QuickTest(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);})
699QuickTest(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
701QuickTest(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
703UDateFormat *DateFormatTest_fmt = NULL;
704UDate sometime = 100000000.0;
705UChar onekbuf[1024];
706const int32_t onekbuf_len = UPRV_LENGTHOF(onekbuf);
707
708
709QuickTest(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
727QuickTest(NullTest,{},{int j=U_LOTS_OF_TIMES;while(--j);return U_LOTS_OF_TIMES;},{})
728
729#if 0
730#include <time.h>
731
732QuickTest(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
735OpenCloseTest(pattern,unum,open,{},(UNUM_PATTERN_DECIMAL,pattern,1,TEST_LOCALE,0,&setupStatus),{})
736OpenCloseTest(default,unum,open,{},(UNUM_DEFAULT,NULL,-1,TEST_LOCALE,0,&setupStatus),{})
737#if !UCONFIG_NO_CONVERSION
738#include "unicode/ucnv.h"
739OpenCloseTest(gb18030,ucnv,open,{},("gb18030",&setupStatus),{})
740#endif
741#include "unicode/ures.h"
742OpenCloseTest(root,ures,open,{},(NULL,"root",&setupStatus),{})
743
744void 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