Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / test / intltest / intltest.cpp
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2013, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6
7
8 #include "unicode/utypes.h"
9
10 /**
11  * IntlTest is a base class for tests.
12  */
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <stdarg.h>
18 #include <stdlib.h>
19
20 #include "unicode/unistr.h"
21 #include "unicode/ures.h"
22 #include "unicode/smpdtfmt.h"
23 #include "unicode/ucnv.h"
24 #include "unicode/uclean.h"
25 #include "unicode/timezone.h"
26 #include "unicode/curramt.h"
27 #include "unicode/putil.h"
28
29 #include "intltest.h"
30 #include "caltztst.h"
31 #include "itmajor.h"
32 #include "cstring.h"
33 #include "umutex.h"
34 #include "uassert.h"
35 #include "cmemory.h"
36 #include "uoptions.h"
37
38 #include "putilimp.h" // for uprv_getRawUTCtime()
39 #include "unicode/locid.h"
40 #include "unicode/ctest.h" // for str_timeDelta
41 #include "udbgutil.h"
42
43 #ifdef XP_MAC_CONSOLE
44 #include <console.h>
45 #include "Files.h"
46 #endif
47
48
49 static char* _testDataPath=NULL;
50
51 // Static list of errors found
52 static UnicodeString errorList;
53 static void *knownList = NULL; // known issues
54 static UBool noKnownIssues = FALSE; // if TRUE, don't emit known issues
55
56 //-----------------------------------------------------------------------------
57 //convenience classes to ease porting code that uses the Java
58 //string-concatenation operator (moved from findword test by rtg)
59
60 // [LIU] Just to get things working
61 UnicodeString
62 UCharToUnicodeString(UChar c)
63 { return UnicodeString(c); }
64
65 // [rtg] Just to get things working
66 UnicodeString
67 operator+(const UnicodeString& left,
68       long num)
69 {
70     char buffer[64];    // nos changed from 10 to 64
71     char danger = 'p';  // guard against overrunning the buffer (rtg)
72
73     sprintf(buffer, "%ld", num);
74     assert(danger == 'p');
75
76     return left + buffer;
77 }
78
79 UnicodeString
80 operator+(const UnicodeString& left,
81       unsigned long num)
82 {
83     char buffer[64];    // nos changed from 10 to 64
84     char danger = 'p';  // guard against overrunning the buffer (rtg)
85
86     sprintf(buffer, "%lu", num);
87     assert(danger == 'p');
88
89     return left + buffer;
90 }
91
92 UnicodeString
93 Int64ToUnicodeString(int64_t num)
94 {
95     char buffer[64];    // nos changed from 10 to 64
96     char danger = 'p';  // guard against overrunning the buffer (rtg)
97
98 #if defined(_MSC_VER)
99     sprintf(buffer, "%I64d", num);
100 #else
101     sprintf(buffer, "%lld", (long long)num);
102 #endif
103     assert(danger == 'p');
104
105     return buffer;
106 }
107
108 // [LIU] Just to get things working
109 UnicodeString
110 operator+(const UnicodeString& left,
111       double num)
112 {
113     char buffer[64];   // was 32, made it arbitrarily bigger (rtg)
114     char danger = 'p'; // guard against overrunning the buffer (rtg)
115
116     // IEEE floating point has 52 bits of mantissa, plus one assumed bit
117     //  53*log(2)/log(10) = 15.95
118     // so there is no need to show more than 16 digits. [alan]
119
120     sprintf(buffer, "%.17g", num);
121     assert(danger == 'p');
122
123     return left + buffer;
124 }
125
126 #if 0
127 UnicodeString
128 operator+(const UnicodeString& left,
129           int64_t num) {
130   return left + Int64ToUnicodeString(num);
131 }
132 #endif
133
134 #if !UCONFIG_NO_FORMATTING
135
136 /**
137  * Return a string display for this, without surrounding braces.
138  */
139 UnicodeString _toString(const Formattable& f) {
140     UnicodeString s;
141     switch (f.getType()) {
142     case Formattable::kDate:
143         {
144             UErrorCode status = U_ZERO_ERROR;
145             SimpleDateFormat fmt(status);
146             if (U_SUCCESS(status)) {
147                 FieldPosition pos;
148                 fmt.format(f.getDate(), s, pos);
149                 s.insert(0, "Date:");
150             } else {
151                 s = UnicodeString("Error creating date format]");
152             }
153         }
154         break;
155     case Formattable::kDouble:
156         s = UnicodeString("double:") + f.getDouble();
157         break;
158     case Formattable::kLong:
159         s = UnicodeString("long:") + f.getLong();
160         break;
161
162     case Formattable::kInt64:
163         s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64());
164         break;
165
166     case Formattable::kString:
167         f.getString(s);
168         s.insert(0, "String:");
169         break;
170     case Formattable::kArray:
171         {
172             int32_t i, n;
173             const Formattable* array = f.getArray(n);
174             s.insert(0, UnicodeString("Array:"));
175             UnicodeString delim(", ");
176             for (i=0; i<n; ++i) {
177                 if (i > 0) {
178                     s.append(delim);
179                 }
180                 s = s + _toString(array[i]);
181             }
182         }
183         break;
184     case Formattable::kObject: {
185         const CurrencyAmount* c = dynamic_cast<const CurrencyAmount*>(f.getObject());
186         if (c != NULL) {
187             s = _toString(c->getNumber()) + " " + UnicodeString(c->getISOCurrency());
188         } else {
189             s = UnicodeString("Unknown UObject");
190         }
191         break;
192     }
193     default:
194         s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType();
195         break;
196     }
197     return s;
198 }
199
200 /**
201  * Originally coded this as operator+, but that makes the expression
202  * + char* ambiguous. - liu
203  */
204 UnicodeString toString(const Formattable& f) {
205     UnicodeString s((UChar)91/*[*/);
206     s.append(_toString(f));
207     s.append((UChar)0x5d/*]*/);
208     return s;
209 }
210
211 #endif
212
213 // useful when operator+ won't cooperate
214 UnicodeString toString(int32_t n) {
215     return UnicodeString() + (long)n;
216 }
217
218
219
220 UnicodeString toString(UBool b) {
221   return b ? UnicodeString("TRUE"):UnicodeString("FALSE");
222 }
223
224 // stephen - cleaned up 05/05/99
225 UnicodeString operator+(const UnicodeString& left, char num)
226 { return left + (long)num; }
227 UnicodeString operator+(const UnicodeString& left, short num)
228 { return left + (long)num; }
229 UnicodeString operator+(const UnicodeString& left, int num)
230 { return left + (long)num; }
231 UnicodeString operator+(const UnicodeString& left, unsigned char num)
232 { return left + (unsigned long)num; }
233 UnicodeString operator+(const UnicodeString& left, unsigned short num)
234 { return left + (unsigned long)num; }
235 UnicodeString operator+(const UnicodeString& left, unsigned int num)
236 { return left + (unsigned long)num; }
237 UnicodeString operator+(const UnicodeString& left, float num)
238 { return left + (double)num; }
239
240 //------------------
241
242 // Append a hex string to the target
243 UnicodeString&
244 IntlTest::appendHex(uint32_t number,
245             int32_t digits,
246             UnicodeString& target)
247 {
248     static const UChar digitString[] = {
249         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
250         0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
251     }; /* "0123456789ABCDEF" */
252
253     if (digits < 0) {  // auto-digits
254         digits = 2;
255         uint32_t max = 0xff;
256         while (number > max) {
257             digits += 2;
258             max = (max << 8) | 0xff;
259         }
260     }
261     switch (digits)
262     {
263     case 8:
264         target += digitString[(number >> 28) & 0xF];
265     case 7:
266         target += digitString[(number >> 24) & 0xF];
267     case 6:
268         target += digitString[(number >> 20) & 0xF];
269     case 5:
270         target += digitString[(number >> 16) & 0xF];
271     case 4:
272         target += digitString[(number >> 12) & 0xF];
273     case 3:
274         target += digitString[(number >>  8) & 0xF];
275     case 2:
276         target += digitString[(number >>  4) & 0xF];
277     case 1:
278         target += digitString[(number >>  0) & 0xF];
279         break;
280     default:
281         target += "**";
282     }
283     return target;
284 }
285
286 UnicodeString
287 IntlTest::toHex(uint32_t number, int32_t digits) {
288     UnicodeString result;
289     appendHex(number, digits, result);
290     return result;
291 }
292
293 static inline UBool isPrintable(UChar32 c) {
294     return c <= 0x7E && (c >= 0x20 || c == 9 || c == 0xA || c == 0xD);
295 }
296
297 // Replace nonprintable characters with unicode escapes
298 UnicodeString&
299 IntlTest::prettify(const UnicodeString &source,
300            UnicodeString &target)
301 {
302     int32_t i;
303
304     target.remove();
305     target += "\"";
306
307     for (i = 0; i < source.length(); )
308     {
309         UChar32 ch = source.char32At(i);
310         i += U16_LENGTH(ch);
311
312         if (!isPrintable(ch))
313         {
314             if (ch <= 0xFFFF) {
315                 target += "\\u";
316                 appendHex(ch, 4, target);
317             } else {
318                 target += "\\U";
319                 appendHex(ch, 8, target);
320             }
321         }
322         else
323         {
324             target += ch;
325         }
326     }
327
328     target += "\"";
329
330     return target;
331 }
332
333 // Replace nonprintable characters with unicode escapes
334 UnicodeString
335 IntlTest::prettify(const UnicodeString &source, UBool parseBackslash)
336 {
337     int32_t i;
338     UnicodeString target;
339     target.remove();
340     target += "\"";
341
342     for (i = 0; i < source.length();)
343     {
344         UChar32 ch = source.char32At(i);
345         i += U16_LENGTH(ch);
346
347         if (!isPrintable(ch))
348         {
349             if (parseBackslash) {
350                 // If we are preceded by an odd number of backslashes,
351                 // then this character has already been backslash escaped.
352                 // Delete a backslash.
353                 int32_t backslashCount = 0;
354                 for (int32_t j=target.length()-1; j>=0; --j) {
355                     if (target.charAt(j) == (UChar)92) {
356                         ++backslashCount;
357                     } else {
358                         break;
359                     }
360                 }
361                 if ((backslashCount % 2) == 1) {
362                     target.truncate(target.length() - 1);
363                 }
364             }
365             if (ch <= 0xFFFF) {
366                 target += "\\u";
367                 appendHex(ch, 4, target);
368             } else {
369                 target += "\\U";
370                 appendHex(ch, 8, target);
371             }
372         }
373         else
374         {
375             target += ch;
376         }
377     }
378
379     target += "\"";
380
381     return target;
382 }
383
384 /*  IntlTest::setICU_DATA  - if the ICU_DATA environment variable is not already
385  *                       set, try to deduce the directory in which ICU was built,
386  *                       and set ICU_DATA to "icu/source/data" in that location.
387  *                       The intent is to allow the tests to have a good chance
388  *                       of running without requiring that the user manually set
389  *                       ICU_DATA.  Common data isn't a problem, since it is
390  *                       picked up via a static (build time) reference, but the
391  *                       tests dynamically load some data.
392  */
393 void IntlTest::setICU_DATA() {
394     const char *original_ICU_DATA = getenv("ICU_DATA");
395
396     if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) {
397         /*  If the user set ICU_DATA, don't second-guess the person. */
398         return;
399     }
400
401     // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
402     //              to point to the top of the build hierarchy, which may or
403     //              may not be the same as the source directory, depending on
404     //              the configure options used.  At any rate,
405     //              set the data path to the built data from this directory.
406     //              The value is complete with quotes, so it can be used
407     //              as-is as a string constant.
408
409 #if defined (U_TOPBUILDDIR)
410     {
411         static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
412         u_setDataDirectory(env_string);
413         return;
414     }
415
416 #else
417     // Use #else so we don't get compiler warnings due to the return above.
418
419     /* On Windows, the file name obtained from __FILE__ includes a full path.
420      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
421      *             Change to    "wherever\icu\source\data"
422      */
423     {
424         char p[sizeof(__FILE__) + 10];
425         char *pBackSlash;
426         int i;
427
428         strcpy(p, __FILE__);
429         /* We want to back over three '\' chars.                            */
430         /*   Only Windows should end up here, so looking for '\' is safe.   */
431         for (i=1; i<=3; i++) {
432             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
433             if (pBackSlash != NULL) {
434                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
435             }
436         }
437
438         if (pBackSlash != NULL) {
439             /* We found and truncated three names from the path.
440              *  Now append "source\data" and set the environment
441              */
442             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
443             u_setDataDirectory(p);     /*  p is "ICU_DATA=wherever\icu\source\data"    */
444             return;
445         }
446         else {
447             /* __FILE__ on MSVC7 does not contain the directory */
448             u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
449             return;
450         }
451     }
452 #endif
453
454     /* No location for the data dir was identifiable.
455      *   Add other fallbacks for the test data location here if the need arises
456      */
457 }
458
459
460 //--------------------------------------------------------------------------------------
461
462 static const int32_t indentLevel_offset = 3;
463 static const char delim = '/';
464
465 IntlTest* IntlTest::gTest = NULL;
466
467 static int32_t execCount = 0;
468
469 void it_log( UnicodeString message )
470 {
471     if (IntlTest::gTest)
472         IntlTest::gTest->log( message );
473 }
474
475 void it_logln( UnicodeString message )
476 {
477     if (IntlTest::gTest)
478         IntlTest::gTest->logln( message );
479 }
480
481 void it_logln( void )
482 {
483     if (IntlTest::gTest)
484         IntlTest::gTest->logln();
485 }
486
487 void it_info( UnicodeString message )
488 {
489     if (IntlTest::gTest)
490         IntlTest::gTest->info( message );
491 }
492
493 void it_infoln( UnicodeString message )
494 {
495     if (IntlTest::gTest)
496         IntlTest::gTest->infoln( message );
497 }
498
499 void it_infoln( void )
500 {
501     if (IntlTest::gTest)
502         IntlTest::gTest->infoln();
503 }
504
505 void it_err()
506 {
507     if (IntlTest::gTest)
508         IntlTest::gTest->err();
509 }
510
511 void it_err( UnicodeString message )
512 {
513     if (IntlTest::gTest)
514         IntlTest::gTest->err( message );
515 }
516
517 void it_errln( UnicodeString message )
518 {
519     if (IntlTest::gTest)
520         IntlTest::gTest->errln( message );
521 }
522
523 void it_dataerr( UnicodeString message )
524 {
525     if (IntlTest::gTest)
526         IntlTest::gTest->dataerr( message );
527 }
528
529 void it_dataerrln( UnicodeString message )
530 {
531     if (IntlTest::gTest)
532         IntlTest::gTest->dataerrln( message );
533 }
534
535 IntlTest::IntlTest()
536 {
537     caller = NULL;
538     testPath = NULL;
539     LL_linestart = TRUE;
540     errorCount = 0;
541     dataErrorCount = 0;
542     verbose = FALSE;
543     no_time = FALSE;
544     no_err_msg = FALSE;
545     warn_on_missing_data = FALSE;
546     quick = FALSE;
547     leaks = FALSE;
548     threadCount = 1;
549     testoutfp = stdout;
550     LL_indentlevel = indentLevel_offset;
551     numProps = 0;
552     strcpy(basePath, "/");
553     currName[0]=0;
554 }
555
556 void IntlTest::setCaller( IntlTest* callingTest )
557 {
558     caller = callingTest;
559     if (caller) {
560         warn_on_missing_data = caller->warn_on_missing_data;
561         verbose = caller->verbose;
562         no_err_msg = caller->no_err_msg;
563         quick = caller->quick;
564         testoutfp = caller->testoutfp;
565         LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
566         numProps = caller->numProps;
567         for (int32_t i = 0; i < numProps; i++) {
568             proplines[i] = caller->proplines[i];
569         }
570     }
571 }
572
573 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
574 {
575     execCount--; // correct a previously assumed test-exec, as this only calls a subtest
576     testToBeCalled.setCaller( this );
577     strcpy(testToBeCalled.basePath, this->basePath );
578     UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath );
579     strcpy(testToBeCalled.basePath, this->basePath ); // reset it.
580     return result;
581 }
582
583 void IntlTest::setPath( char* pathVal )
584 {
585     this->testPath = pathVal;
586 }
587
588 UBool IntlTest::setVerbose( UBool verboseVal )
589 {
590     UBool rval = this->verbose;
591     this->verbose = verboseVal;
592     return rval;
593 }
594
595 UBool IntlTest::setNotime( UBool no_time )
596 {
597     UBool rval = this->no_time;
598     this->no_time = no_time;
599     return rval;
600 }
601
602 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
603 {
604     UBool rval = this->warn_on_missing_data;
605     this->warn_on_missing_data = warn_on_missing_dataVal;
606     return rval;
607 }
608
609 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
610 {
611     UBool rval = this->no_err_msg;
612     this->no_err_msg = no_err_msgVal;
613     return rval;
614 }
615
616 UBool IntlTest::setQuick( UBool quickVal )
617 {
618     UBool rval = this->quick;
619     this->quick = quickVal;
620     return rval;
621 }
622
623 UBool IntlTest::setLeaks( UBool leaksVal )
624 {
625     UBool rval = this->leaks;
626     this->leaks = leaksVal;
627     return rval;
628 }
629
630 int32_t IntlTest::setThreadCount( int32_t count )
631 {
632     int32_t rval = this->threadCount;
633     this->threadCount = count;
634     return rval;
635 }
636
637 int32_t IntlTest::getErrors( void )
638 {
639     return errorCount;
640 }
641
642 int32_t IntlTest::getDataErrors( void )
643 {
644     return dataErrorCount;
645 }
646
647 UBool IntlTest::runTest( char* name, char* par, char *baseName )
648 {
649     UBool rval;
650     char* pos = NULL;
651
652     char* baseNameBuffer = NULL;
653
654     if(baseName == NULL) {
655       baseNameBuffer = (char*)malloc(1024);
656       baseName=baseNameBuffer;
657       strcpy(baseName, "/");
658     }
659
660     if (name)
661         pos = strchr( name, delim ); // check if name contains path (by looking for '/')
662     if (pos) {
663         testPath = pos+1;   // store subpath for calling subtest
664         *pos = 0;       // split into two strings
665     }else{
666         testPath = NULL;
667     }
668
669     if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
670       rval = runTestLoop( NULL, par, baseName );
671
672     }else if (strcmp( name, "LIST" ) == 0) {
673         this->usage();
674         rval = TRUE;
675
676     }else{
677       rval = runTestLoop( name, par, baseName );
678     }
679
680     if (pos)
681         *pos = delim;  // restore original value at pos
682     if(baseNameBuffer!=NULL) {
683       free(baseNameBuffer);
684     }
685     return rval;
686 }
687
688 // call individual tests, to be overriden to call implementations
689 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
690 {
691     // to be overriden by a method like:
692     /*
693     switch (index) {
694         case 0: name = "First Test"; if (exec) FirstTest( par ); break;
695         case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
696         default: name = ""; break;
697     }
698     */
699     this->errln("*** runIndexedTest needs to be overriden! ***");
700 }
701
702
703 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
704 {
705     int32_t    index = 0;
706     const char*   name;
707     UBool  run_this_test;
708     int32_t    lastErrorCount;
709     UBool  rval = FALSE;
710     UBool   lastTestFailed;
711
712     if(baseName == NULL) {
713       printf("ERROR: baseName can't be null.\n");
714       return FALSE;
715     } else {
716       if ((char *)this->basePath != baseName) {
717         strcpy(this->basePath, baseName);
718       }
719     }
720
721     char * saveBaseLoc = baseName+strlen(baseName);
722
723     IntlTest* saveTest = gTest;
724     gTest = this;
725     do {
726         this->runIndexedTest( index, FALSE, name, par );
727         if (strcmp(name,"skip") == 0) {
728             run_this_test = FALSE;
729         } else {
730             if (!name || (name[0] == 0))
731                 break;
732             if (!testname) {
733                 run_this_test = TRUE;
734             }else{
735                 run_this_test = (UBool) (strcmp( name, testname ) == 0);
736             }
737         }
738         if (run_this_test) {
739             lastErrorCount = errorCount;
740             execCount++;
741             char msg[256];
742             sprintf(msg, "%s {", name);
743             LL_message(msg, TRUE);
744             UDate timeStart = uprv_getRawUTCtime();
745             strcpy(saveBaseLoc,name);
746             strcat(saveBaseLoc,"/");
747
748             strcpy(currName, name); // set
749             this->runIndexedTest( index, TRUE, name, par );
750             currName[0]=0; // reset
751
752             UDate timeStop = uprv_getRawUTCtime();
753             rval = TRUE; // at least one test has been called
754             char secs[256];
755             if(!no_time) {
756               sprintf(secs, "%f", (timeStop-timeStart)/1000.0);
757             } else {
758               secs[0]=0;
759             }
760             
761
762             strcpy(saveBaseLoc,name);
763
764
765             ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL);
766             
767
768             saveBaseLoc[0]=0; /* reset path */
769             
770             if (lastErrorCount == errorCount) {
771                 sprintf( msg, "   } OK:   %s ", name );
772                 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
773                 lastTestFailed = FALSE;
774             }else{
775                 sprintf(msg,  "   } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
776                 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
777
778                 for(int i=0;i<LL_indentlevel;i++) {
779                     errorList += " ";
780                 }
781                 errorList += name;
782                 errorList += "\n";
783                 lastTestFailed = TRUE;
784             }
785             LL_indentlevel -= 3;
786             if (lastTestFailed) {
787                 LL_message( "", TRUE);
788             }
789             LL_message( msg, TRUE);
790             if (lastTestFailed) {
791                 LL_message( "", TRUE);
792             }
793             LL_indentlevel += 3;
794         }
795         index++;
796     }while(name);
797
798     *saveBaseLoc = 0;
799
800     gTest = saveTest;
801     return rval;
802 }
803
804
805 /**
806 * Adds given string to the log if we are in verbose mode.
807 */
808 void IntlTest::log( const UnicodeString &message )
809 {
810     if( verbose ) {
811         LL_message( message, FALSE );
812     }
813 }
814
815 /**
816 * Adds given string to the log if we are in verbose mode. Adds a new line to
817 * the given message.
818 */
819 void IntlTest::logln( const UnicodeString &message )
820 {
821     if( verbose ) {
822         LL_message( message, TRUE );
823     }
824 }
825
826 void IntlTest::logln( void )
827 {
828     if( verbose ) {
829         LL_message( "", TRUE );
830     }
831 }
832
833 /**
834 * Unconditionally adds given string to the log.
835 */
836 void IntlTest::info( const UnicodeString &message )
837 {
838   LL_message( message, FALSE );
839 }
840
841 /**
842 * Unconditionally adds given string to the log. Adds a new line to
843 * the given message.
844 */
845 void IntlTest::infoln( const UnicodeString &message )
846 {
847   LL_message( message, TRUE );
848 }
849
850 void IntlTest::infoln( void )
851 {
852   LL_message( "", TRUE );
853 }
854
855 int32_t IntlTest::IncErrorCount( void )
856 {
857     errorCount++;
858     if (caller) caller->IncErrorCount();
859     return errorCount;
860 }
861
862 int32_t IntlTest::IncDataErrorCount( void )
863 {
864     dataErrorCount++;
865     if (caller) caller->IncDataErrorCount();
866     return dataErrorCount;
867 }
868
869 void IntlTest::err()
870 {
871     IncErrorCount();
872 }
873
874 void IntlTest::err( const UnicodeString &message )
875 {
876     IncErrorCount();
877     if (!no_err_msg) LL_message( message, FALSE );
878 }
879
880 void IntlTest::errln( const UnicodeString &message )
881 {
882     IncErrorCount();
883     if (!no_err_msg) LL_message( message, TRUE );
884 }
885
886 void IntlTest::dataerr( const UnicodeString &message )
887 {
888     IncDataErrorCount();
889
890     if (!warn_on_missing_data) {
891         IncErrorCount();
892     }
893
894     if (!no_err_msg) LL_message( message, FALSE );
895 }
896
897 void IntlTest::dataerrln( const UnicodeString &message )
898 {
899     int32_t errCount = IncDataErrorCount();
900     UnicodeString msg;
901     if (!warn_on_missing_data) {
902         IncErrorCount();
903         msg = message;
904     } else {
905         msg = UnicodeString("[DATA] " + message);
906     }
907
908     if (!no_err_msg) {
909       if ( errCount == 1) {
910           LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
911       } else {
912           LL_message( msg , TRUE );
913       }
914     }
915 }
916
917 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
918     if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
919         dataerrln(message);
920     } else {
921         errln(message);
922     }
923 }
924
925 /* convenience functions that include sprintf formatting */
926 void IntlTest::log(const char *fmt, ...)
927 {
928     char buffer[4000];
929     va_list ap;
930
931     va_start(ap, fmt);
932     /* sprintf it just to make sure that the information is valid */
933     vsprintf(buffer, fmt, ap);
934     va_end(ap);
935     if( verbose ) {
936         log(UnicodeString(buffer, ""));
937     }
938 }
939
940 void IntlTest::logln(const char *fmt, ...)
941 {
942     char buffer[4000];
943     va_list ap;
944
945     va_start(ap, fmt);
946     /* sprintf it just to make sure that the information is valid */
947     vsprintf(buffer, fmt, ap);
948     va_end(ap);
949     if( verbose ) {
950         logln(UnicodeString(buffer, ""));
951     }
952 }
953
954 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...)
955 {
956     char buffer[4000];
957     va_list ap;
958
959     va_start(ap, fmt);
960     /* sprintf it just to make sure that the information is valid */
961     vsprintf(buffer, fmt, ap);
962     va_end(ap);
963     return logKnownIssue(ticket, UnicodeString(buffer, ""));
964 }
965
966 UBool IntlTest::logKnownIssue(const char *ticket) {
967   return logKnownIssue(ticket, UnicodeString());
968 }
969
970 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) {
971   if(noKnownIssues) return FALSE;
972
973   char fullpath[2048];
974   strcpy(fullpath, basePath);
975   strcat(fullpath, currName);
976   UnicodeString msg2 =msg;
977   UBool firstForTicket, firstForWhere;
978   knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere);
979
980   if(firstForTicket || firstForWhere) {
981     infoln(UnicodeString("(Known issue #","") + UnicodeString(ticket,"")+ UnicodeString(") \"","") + msg);
982   } else {
983     logln(UnicodeString("(Known issue #","") + UnicodeString(ticket,"")+ UnicodeString(") \"","") + msg);
984   }
985
986   return TRUE;
987 }
988
989 /* convenience functions that include sprintf formatting */
990 void IntlTest::info(const char *fmt, ...)
991 {
992     char buffer[4000];
993     va_list ap;
994
995     va_start(ap, fmt);
996     /* sprintf it just to make sure that the information is valid */
997     vsprintf(buffer, fmt, ap);
998     va_end(ap);
999     info(UnicodeString(buffer, ""));
1000 }
1001
1002 void IntlTest::infoln(const char *fmt, ...)
1003 {
1004     char buffer[4000];
1005     va_list ap;
1006
1007     va_start(ap, fmt);
1008     /* sprintf it just to make sure that the information is valid */
1009     vsprintf(buffer, fmt, ap);
1010     va_end(ap);
1011     infoln(UnicodeString(buffer, ""));
1012 }
1013
1014 void IntlTest::err(const char *fmt, ...)
1015 {
1016     char buffer[4000];
1017     va_list ap;
1018
1019     va_start(ap, fmt);
1020     vsprintf(buffer, fmt, ap);
1021     va_end(ap);
1022     err(UnicodeString(buffer, ""));
1023 }
1024
1025 void IntlTest::errln(const char *fmt, ...)
1026 {
1027     char buffer[4000];
1028     va_list ap;
1029
1030     va_start(ap, fmt);
1031     vsprintf(buffer, fmt, ap);
1032     va_end(ap);
1033     errln(UnicodeString(buffer, ""));
1034 }
1035
1036 void IntlTest::dataerrln(const char *fmt, ...)
1037 {
1038     char buffer[4000];
1039     va_list ap;
1040
1041     va_start(ap, fmt);
1042     vsprintf(buffer, fmt, ap);
1043     va_end(ap);
1044     dataerrln(UnicodeString(buffer, ""));
1045 }
1046
1047 void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...)
1048 {
1049     char buffer[4000];
1050     va_list ap;
1051
1052     va_start(ap, fmt);
1053     vsprintf(buffer, fmt, ap);
1054     va_end(ap);
1055     
1056     if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
1057         dataerrln(UnicodeString(buffer, ""));
1058     } else {
1059         errln(UnicodeString(buffer, ""));
1060     }
1061 }
1062
1063 void IntlTest::printErrors()
1064 {
1065      IntlTest::LL_message(errorList, TRUE);
1066 }
1067
1068 UBool IntlTest::printKnownIssues()
1069 {
1070   if(knownList != NULL) {
1071     udbg_knownIssue_print(knownList);
1072     udbg_knownIssue_close(knownList);
1073     return TRUE;
1074   } else {
1075     return FALSE;
1076   }
1077 }
1078
1079 void IntlTest::LL_message( UnicodeString message, UBool newline )
1080 {
1081     // string that starts with a LineFeed character and continues
1082     // with spaces according to the current indentation
1083     static const UChar indentUChars[] = {
1084         '\n',
1085         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1086         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1087         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1088         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1089         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1090         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1091         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1092         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1093         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1094         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1095     };
1096     UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
1097
1098     char buffer[10000];
1099     int32_t length;
1100
1101     // stream out the indentation string first if necessary
1102     length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
1103     if (length > 0) {
1104         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1105     }
1106
1107     // replace each LineFeed by the indentation string
1108     message.findAndReplace(UnicodeString((UChar)'\n'), indent);
1109
1110     // stream out the message
1111     length = message.extract(0, message.length(), buffer, sizeof(buffer));
1112     if (length > 0) {
1113         length = length > 10000 ? 10000 : length;
1114         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1115     }
1116
1117     if (newline) {
1118         char newLine = '\n';
1119         fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
1120     }
1121
1122     // A newline usually flushes the buffer, but
1123     // flush the message just in case of a core dump.
1124     fflush((FILE *)testoutfp);
1125 }
1126
1127 /**
1128 * Print a usage message for this test class.
1129 */
1130 void IntlTest::usage( void )
1131 {
1132     UBool save_verbose = setVerbose( TRUE );
1133     logln("Test names:");
1134     logln("-----------");
1135
1136     int32_t index = 0;
1137     const char* name = NULL;
1138     do{
1139         this->runIndexedTest( index, FALSE, name );
1140         if (!name) break;
1141         logln(name);
1142         index++;
1143     }while (name && (name[0] != 0));
1144     setVerbose( save_verbose );
1145 }
1146
1147
1148 // memory leak reporting software will be able to take advantage of the testsuite
1149 // being run a second time local to a specific method in order to report only actual leaks
1150 UBool
1151 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1152 {
1153     UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1154     strLeak->append(" for verifying purify filter");
1155     return this->runTest( name, par );
1156 }
1157
1158
1159 #if UCONFIG_NO_LEGACY_CONVERSION
1160 #   define TRY_CNV_1 "iso-8859-1"
1161 #   define TRY_CNV_2 "ibm-1208"
1162 #else
1163 #   define TRY_CNV_1 "iso-8859-7"
1164 #   define TRY_CNV_2 "sjis"
1165 #endif
1166
1167 int
1168 main(int argc, char* argv[])
1169 {
1170     UBool syntax = FALSE;
1171     UBool all = FALSE;
1172     UBool verbose = FALSE;
1173     UBool no_err_msg = FALSE;
1174     UBool no_time = FALSE;
1175     UBool quick = TRUE;
1176     UBool name = FALSE;
1177     UBool leaks = FALSE;
1178     UBool utf8 = FALSE;
1179     const char *summary_file = NULL;
1180     UBool warnOnMissingData = FALSE;
1181     UBool defaultDataFound = FALSE;
1182     int32_t threadCount = 1;
1183     UErrorCode errorCode = U_ZERO_ERROR;
1184     UConverter *cnv = NULL;
1185     const char *warnOrErr = "Failure";
1186     UDate startTime, endTime;
1187     int32_t diffTime;
1188     const char *props[IntlTest::kMaxProps];
1189     int32_t nProps = 0;
1190
1191     U_MAIN_INIT_ARGS(argc, argv);
1192
1193     startTime = uprv_getRawUTCtime();
1194
1195     for (int i = 1; i < argc; ++i) {
1196         if (argv[i][0] == '-') {
1197             const char* str = argv[i] + 1;
1198             if (strcmp("verbose", str) == 0 ||
1199                 strcmp("v", str) == 0)
1200                 verbose = TRUE;
1201             else if (strcmp("noerrormsg", str) == 0 ||
1202                      strcmp("n", str) == 0)
1203                 no_err_msg = TRUE;
1204             else if (strcmp("exhaustive", str) == 0 ||
1205                      strcmp("e", str) == 0)
1206                 quick = FALSE;
1207             else if (strcmp("all", str) == 0 ||
1208                      strcmp("a", str) == 0)
1209                 all = TRUE;
1210             else if (strcmp("utf-8", str) == 0 ||
1211                      strcmp("u", str) == 0)
1212                 utf8 = TRUE;
1213             else if (strcmp("noknownissues", str) == 0 ||
1214                      strcmp("K", str) == 0)
1215                 noKnownIssues = TRUE;
1216             else if (strcmp("leaks", str) == 0 ||
1217                      strcmp("l", str) == 0)
1218                 leaks = TRUE;
1219             else if (strcmp("notime", str) == 0 ||
1220                      strcmp("T", str) == 0)
1221                 no_time = TRUE;
1222             else if (strncmp("E", str, 1) == 0)
1223                 summary_file = str+1;
1224             else if (strcmp("x", str)==0) {
1225               if(++i>=argc) {
1226                 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1227                 syntax = TRUE;
1228               }
1229               if(ctest_xml_setFileName(argv[i])) { /* set the name */
1230                 return 1; /* error */
1231               }
1232             } else if (strcmp("w", str) == 0) {
1233               warnOnMissingData = TRUE;
1234               warnOrErr = "WARNING";
1235             }
1236             else if (strncmp("threads:", str, 8) == 0) {
1237                 threadCount = atoi(str + 8);
1238             }
1239             else if (strncmp("prop:", str, 5) == 0) {
1240                 if (nProps < IntlTest::kMaxProps) {
1241                     props[nProps] = str + 5;
1242                 }
1243                 nProps++;
1244             }
1245             else {
1246                 syntax = TRUE;
1247             }
1248         }else{
1249             name = TRUE;
1250         }
1251     }
1252
1253     if (!all && !name) {
1254         all = TRUE;
1255     } else if (all && name) {
1256         syntax = TRUE;
1257     }
1258
1259     if (syntax) {
1260         fprintf(stdout,
1261                 "### Syntax:\n"
1262                 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1263                 "### \n"
1264                 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1265                 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1266                 "### notime (T), \n"
1267                 "### threads:<threadCount> (Mulithreading must first be \n"
1268                 "###     enabled otherwise this will be ignored. \n"
1269                 "###     The default thread count is 1.),\n"
1270                 "### (Specify either -all (shortcut -a) or a test name). \n"
1271                 "### -all will run all of the tests.\n"
1272                 "### \n"
1273                 "### To get a list of the test names type: intltest LIST \n"
1274                 "### To run just the utility tests type: intltest utility \n"
1275                 "### \n"
1276                 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1277                 "### For example to list the utility tests type: intltest utility/LIST \n"
1278                 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1279                 "### \n"
1280                 "### A parameter can be specified for a test by appending '@' and the value \n"
1281                 "### to the testname. \n\n");
1282         return 1;
1283     }
1284
1285     if (nProps > IntlTest::kMaxProps) {
1286         fprintf(stdout, "### Too many properties.  Exiting.\n");
1287     }
1288
1289     MajorTestLevel major;
1290     major.setVerbose( verbose );
1291     major.setNoErrMsg( no_err_msg );
1292     major.setQuick( quick );
1293     major.setLeaks( leaks );
1294     major.setThreadCount( threadCount );
1295     major.setWarnOnMissingData( warnOnMissingData );
1296     major.setNotime (no_time);
1297     for (int32_t i = 0; i < nProps; i++) {
1298         major.setProperty(props[i]);
1299     }
1300
1301
1302     fprintf(stdout, "-----------------------------------------------\n");
1303     fprintf(stdout, " IntlTest (C++) Test Suite for                 \n");
1304     fprintf(stdout, "   International Components for Unicode %s\n", U_ICU_VERSION);
1305
1306
1307     {
1308         const char *charsetFamily = "Unknown";
1309         int32_t voidSize = (int32_t)sizeof(void*);
1310         int32_t bits = voidSize * 8;
1311         if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1312            charsetFamily="ASCII";
1313         } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1314            charsetFamily="EBCDIC";
1315         }
1316         fprintf(stdout, 
1317                     "   Bits: %d, Byte order: %s, Chars: %s\n",
1318                      bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1319                      charsetFamily);
1320     }
1321     fprintf(stdout, "-----------------------------------------------\n");
1322     fprintf(stdout, " Options:                                       \n");
1323     fprintf(stdout, "   all (a)                  : %s\n", (all?               "On" : "Off"));
1324     fprintf(stdout, "   Verbose (v)              : %s\n", (verbose?           "On" : "Off"));
1325     fprintf(stdout, "   No error messages (n)    : %s\n", (no_err_msg?        "On" : "Off"));
1326     fprintf(stdout, "   Exhaustive (e)           : %s\n", (!quick?            "On" : "Off"));
1327     fprintf(stdout, "   Leaks (l)                : %s\n", (leaks?             "On" : "Off"));
1328     fprintf(stdout, "   utf-8 (u)                : %s\n", (utf8?              "On" : "Off"));
1329     fprintf(stdout, "   notime (T)               : %s\n", (no_time?             "On" : "Off"));
1330     fprintf(stdout, "   noknownissues (K)        : %s\n", (noKnownIssues?      "On" : "Off"));
1331     fprintf(stdout, "   Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1332 #if (ICU_USE_THREADS==0)
1333     fprintf(stdout, "   Threads                  : Disabled\n");
1334 #else
1335     fprintf(stdout, "   Threads                  : %d\n", threadCount);
1336 #endif
1337     for (int32_t i = 0; i < nProps; i++) {
1338         fprintf(stdout, "   Custom property (prop:)  : %s\n", props[i]);
1339     }
1340     fprintf(stdout, "-----------------------------------------------\n");
1341
1342     if(utf8) {
1343       ucnv_setDefaultName("utf-8");
1344     }
1345     /* Check whether ICU will initialize without forcing the build data directory into
1346      *  the ICU_DATA path.  Success here means either the data dll contains data, or that
1347      *  this test program was run with ICU_DATA set externally.  Failure of this check
1348      *  is normal when ICU data is not packaged into a shared library.
1349      *
1350      *  Whether or not this test succeeds, we want to cleanup and reinitialize
1351      *  with a data path so that data loading from individual files can be tested.
1352      */
1353     u_init(&errorCode);
1354     if (U_FAILURE(errorCode)) {
1355         fprintf(stderr,
1356             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
1357         defaultDataFound = FALSE;
1358     }
1359     else {
1360         defaultDataFound = TRUE;
1361     }
1362     u_cleanup();
1363     if(utf8) {
1364       ucnv_setDefaultName("utf-8");
1365     }
1366     errorCode = U_ZERO_ERROR;
1367
1368     /* Initialize ICU */
1369     if (!defaultDataFound) {
1370         IntlTest::setICU_DATA();   // Must set data directory before u_init() is called.
1371     }
1372     u_init(&errorCode);
1373     if (U_FAILURE(errorCode)) {
1374         fprintf(stderr,
1375             "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1376             "*** Check the ICU_DATA environment variable and \n"
1377             "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1378             if(warnOnMissingData == 0) {
1379                 fprintf(stderr, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1380                 u_cleanup();
1381                 return 1;
1382             }
1383     }
1384
1385     // initial check for the default converter
1386     errorCode = U_ZERO_ERROR;
1387     cnv = ucnv_open(0, &errorCode);
1388     if(cnv != 0) {
1389         // ok
1390         ucnv_close(cnv);
1391     } else {
1392         fprintf(stdout,
1393                 "*** %s! The default converter [%s] cannot be opened.\n"
1394                 "*** Check the ICU_DATA environment variable and\n"
1395                 "*** check that the data files are present.\n",
1396                 warnOrErr, ucnv_getDefaultName());
1397         if(!warnOnMissingData) {
1398           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1399           return 1;
1400         }
1401     }
1402
1403     // try more data
1404     cnv = ucnv_open(TRY_CNV_2, &errorCode);
1405     if(cnv != 0) {
1406         // ok
1407         ucnv_close(cnv);
1408     } else {
1409         fprintf(stdout,
1410                 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1411                 "*** Check the ICU_DATA environment variable and \n"
1412                 "*** check that the data files are present.\n", warnOrErr);
1413         if(!warnOnMissingData) {
1414           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1415           return 1;
1416         }
1417     }
1418
1419     UResourceBundle *rb = ures_open(0, "en", &errorCode);
1420     ures_close(rb);
1421     if(U_FAILURE(errorCode)) {
1422         fprintf(stdout,
1423                 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1424                 "*** Check the ICU_DATA environment variable and \n"
1425                 "*** check that the data files are present.\n", warnOrErr);
1426         if(!warnOnMissingData) {
1427           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1428           return 1;
1429         }
1430     }
1431
1432     Locale originalLocale;  // Save the default locale for comparison later on.
1433
1434     if(ctest_xml_init("intltest")) 
1435       return 1;
1436
1437
1438     /* TODO: Add option to call u_cleanup and rerun tests. */
1439     if (all) {
1440         major.runTest();
1441         if (leaks) {
1442             major.run_phase2( NULL, NULL );
1443         }
1444     }else{
1445         for (int i = 1; i < argc; ++i) {
1446             if (argv[i][0] != '-') {
1447                 char* name = argv[i];
1448                 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1449
1450                 char baseName[1024];
1451                 sprintf(baseName, "/%s/", name);
1452
1453                 char* parameter = strchr( name, '@' );
1454                 if (parameter) {
1455                     *parameter = 0;
1456                     parameter += 1;
1457                 }
1458                 execCount = 0;
1459                 UBool res = major.runTest( name, parameter, baseName );
1460                 if (leaks && res) {
1461                     major.run_phase2( name, parameter );
1462                 }
1463                 if (!res || (execCount <= 0)) {
1464                     fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1465                 }
1466             } else if(!strcmp(argv[i],"-x")) {
1467               i++;
1468             }
1469         }
1470     }
1471
1472
1473 #if !UCONFIG_NO_FORMATTING
1474     CalendarTimeZoneTest::cleanup();
1475 #endif
1476
1477     free(_testDataPath);
1478     _testDataPath = 0;
1479
1480     Locale lastDefaultLocale;
1481     if (originalLocale != lastDefaultLocale) {
1482         major.errln("FAILURE: A test changed the default locale without resetting it.");
1483     }
1484
1485     fprintf(stdout, "\n--------------------------------------\n");
1486     if( major.printKnownIssues() ) {
1487       fprintf(stdout, " To run suppressed tests, use the -K option. \n");
1488     }
1489     if (major.getErrors() == 0) {
1490         /* Call it twice to make sure that the defaults were reset. */
1491         /* Call it before the OK message to verify proper cleanup. */
1492         u_cleanup();
1493         u_cleanup();
1494
1495         fprintf(stdout, "OK: All tests passed without error.\n");
1496
1497         if (major.getDataErrors() != 0) {
1498             fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1499         }
1500     }else{
1501         fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1502         major.printErrors();
1503
1504         if(summary_file != NULL) {
1505           FILE *summf = fopen(summary_file, "w");
1506           if( summf != NULL) {
1507             char buf[10000];
1508             int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf));
1509             fwrite(buf, sizeof(*buf), length, (FILE*)summf);
1510             fclose(summf);
1511           }
1512         }
1513
1514
1515         if (major.getDataErrors() != 0) {
1516             fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1517                     "\tstock ICU data (i.e some have been added or removed), consider using\n"
1518                     "\tthe '-w' option to turn these errors into warnings.\n");
1519         }
1520
1521         /* Call afterwards to display errors. */
1522         u_cleanup();
1523     }
1524
1525     fprintf(stdout, "--------------------------------------\n");
1526
1527     if (execCount <= 0) {
1528         fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1529     }
1530     if(!no_time) {
1531       endTime = uprv_getRawUTCtime();
1532       diffTime = (int32_t)(endTime - startTime);
1533       printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1534              (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1535              (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1536              (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1537              (int)(diffTime%U_MILLIS_PER_SECOND));
1538     }
1539
1540     if(ctest_xml_fini())
1541       return 1;
1542
1543     return major.getErrors();
1544 }
1545
1546 const char* IntlTest::loadTestData(UErrorCode& err){
1547     if( _testDataPath == NULL){
1548         const char*      directory=NULL;
1549         UResourceBundle* test =NULL;
1550         char* tdpath=NULL;
1551         const char* tdrelativepath;
1552
1553 #if defined (U_TOPBUILDDIR)
1554         tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1555         directory = U_TOPBUILDDIR;
1556 #else
1557         tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1558         directory = pathToDataDirectory();
1559 #endif
1560
1561         tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1562
1563
1564         /* u_getDataDirectory shoul return \source\data ... set the
1565          * directory to ..\source\data\..\test\testdata\out\testdata
1566          */
1567         strcpy(tdpath, directory);
1568         strcat(tdpath, tdrelativepath);
1569         strcat(tdpath,"testdata");
1570
1571         test=ures_open(tdpath, "testtypes", &err);
1572
1573         if(U_FAILURE(err)){
1574             err = U_FILE_ACCESS_ERROR;
1575             it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1576             return "";
1577         }
1578         ures_close(test);
1579         _testDataPath = tdpath;
1580         return _testDataPath;
1581     }
1582     return _testDataPath;
1583 }
1584
1585 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1586     return loadTestData(err);
1587 }
1588
1589 /* Returns the path to icu/source/test/testdata/ */
1590 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1591     const char *srcDataDir = NULL;
1592 #ifdef U_TOPSRCDIR
1593     srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1594 #else
1595     srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1596     FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r");
1597     if (f) {
1598         /* We're in icu/source/test/intltest/ */
1599         fclose(f);
1600     }
1601     else {
1602         /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1603         srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata"U_FILE_SEP_STRING;
1604     }
1605 #endif
1606     return srcDataDir;
1607 }
1608
1609 const char* IntlTest::fgDataDir = NULL;
1610
1611 /* returns the path to icu/source/data */
1612 const char *  IntlTest::pathToDataDirectory()
1613 {
1614
1615     if(fgDataDir != NULL) {
1616         return fgDataDir;
1617     }
1618
1619     /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1620     //              to point to the top of the build hierarchy, which may or
1621     //              may not be the same as the source directory, depending on
1622     //              the configure options used.  At any rate,
1623     //              set the data path to the built data from this directory.
1624     //              The value is complete with quotes, so it can be used
1625     //              as-is as a string constant.
1626     */
1627 #if defined (U_TOPSRCDIR)
1628     {
1629         fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1630     }
1631 #else
1632
1633     /* On Windows, the file name obtained from __FILE__ includes a full path.
1634      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
1635      *             Change to    "wherever\icu\source\data"
1636      */
1637     {
1638         static char p[sizeof(__FILE__) + 10];
1639         char *pBackSlash;
1640         int i;
1641
1642         strcpy(p, __FILE__);
1643         /* We want to back over three '\' chars.                            */
1644         /*   Only Windows should end up here, so looking for '\' is safe.   */
1645         for (i=1; i<=3; i++) {
1646             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1647             if (pBackSlash != NULL) {
1648                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
1649             }
1650         }
1651
1652         if (pBackSlash != NULL) {
1653             /* We found and truncated three names from the path.
1654             *  Now append "source\data" and set the environment
1655             */
1656             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1657             fgDataDir = p;
1658         }
1659         else {
1660             /* __FILE__ on MSVC7 does not contain the directory */
1661             FILE *file = fopen(".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1662             if (file) {
1663                 fclose(file);
1664                 fgDataDir = ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1665             }
1666             else {
1667                 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1668             }
1669         }
1670     }
1671 #endif
1672
1673     return fgDataDir;
1674
1675 }
1676
1677 /*
1678  * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1679  * It converts an invariant-character string into a UnicodeString, with
1680  * unescaping \u sequences.
1681  */
1682 UnicodeString CharsToUnicodeString(const char* chars){
1683     return UnicodeString(chars, -1, US_INV).unescape();
1684 }
1685
1686 UnicodeString ctou(const char* chars) {
1687     return CharsToUnicodeString(chars);
1688 }
1689
1690 #define RAND_M  (714025)
1691 #define RAND_IA (1366)
1692 #define RAND_IC (150889)
1693
1694 static int32_t RAND_SEED;
1695
1696 /**
1697  * Returns a uniform random value x, with 0.0 <= x < 1.0.  Use
1698  * with care: Does not return all possible values; returns one of
1699  * 714,025 values, uniformly spaced.  However, the period is
1700  * effectively infinite.  See: Numerical Recipes, section 7.1.
1701  *
1702  * @param seedp pointer to seed. Set *seedp to any negative value
1703  * to restart the sequence.
1704  */
1705 float IntlTest::random(int32_t* seedp) {
1706     static int32_t iy, ir[98];
1707     static UBool first=TRUE;
1708     int32_t j;
1709     if (*seedp < 0 || first) {
1710         first = FALSE;
1711         if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1712         for (j=1;j<=97;++j) {
1713             *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1714             ir[j]=(*seedp);
1715         }
1716         *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1717         iy=(*seedp);
1718     }
1719     j=(int32_t)(1 + 97.0*iy/RAND_M);
1720     U_ASSERT(j>=1 && j<=97);
1721     iy=ir[j];
1722     *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1723     ir[j]=(*seedp);
1724     return (float) iy/RAND_M;
1725 }
1726
1727 /**
1728  * Convenience method using a global seed.
1729  */
1730 float IntlTest::random() {
1731     return random(&RAND_SEED);
1732 }
1733
1734 static inline UChar toHex(int32_t i) {
1735     return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1736 }
1737
1738 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1739     for (int32_t i=0; i<s.length(); ++i) {
1740         UChar c = s[i];
1741         if (c <= (UChar)0x7F) {
1742             result += c;
1743         } else {
1744             result += (UChar)0x5c;
1745             result += (UChar)0x75;
1746             result += toHex((c >> 12) & 0xF);
1747             result += toHex((c >>  8) & 0xF);
1748             result += toHex((c >>  4) & 0xF);
1749             result += toHex( c        & 0xF);
1750         }
1751     }
1752     return result;
1753 }
1754
1755 #define VERBOSE_ASSERTIONS
1756
1757 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1758     if (file != NULL) {
1759         if (!condition) {
1760             if (possibleDataError) {
1761                 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1762             } else {
1763                 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1764             }
1765         } else if (!quiet) {
1766             logln("%s:%d: Ok: %s", file, line, message);
1767         }
1768     } else {
1769         if (!condition) {
1770             if (possibleDataError) {
1771                 dataerrln("FAIL: assertTrue() failed: %s", message);
1772             } else {
1773                 errln("FAIL: assertTrue() failed: %s", message);
1774             }
1775         } else if (!quiet) {
1776             logln("Ok: %s", message);
1777         }
1778
1779     }
1780     return condition;
1781 }
1782
1783 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1784     if (condition) {
1785         errln("FAIL: assertFalse() failed: %s", message);
1786     } else if (!quiet) {
1787         logln("Ok: %s", message);
1788     }
1789     return !condition;
1790 }
1791
1792 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1793     if( file==NULL ) {
1794       file = ""; // prevent failure if no file given
1795     }
1796     if (U_FAILURE(ec)) {
1797         if (possibleDataError) {
1798           dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1799         } else {
1800           errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1801         }
1802         return FALSE;
1803     } else {
1804       logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1805     }
1806     return TRUE;
1807 }
1808
1809 UBool IntlTest::assertEquals(const char* message,
1810                              const UnicodeString& expected,
1811                              const UnicodeString& actual,
1812                              UBool possibleDataError) {
1813     if (expected != actual) {
1814         if (possibleDataError) {
1815             dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1816                   prettify(actual) +
1817                   "; expected " + prettify(expected));
1818         } else {
1819             errln((UnicodeString)"FAIL: " + message + "; got " +
1820                   prettify(actual) +
1821                   "; expected " + prettify(expected));
1822         }
1823         return FALSE;
1824     }
1825 #ifdef VERBOSE_ASSERTIONS
1826     else {
1827         logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1828     }
1829 #endif
1830     return TRUE;
1831 }
1832
1833 UBool IntlTest::assertEquals(const char* message,
1834                              const char* expected,
1835                              const char* actual) {
1836     if (uprv_strcmp(expected, actual) != 0) {
1837         errln((UnicodeString)"FAIL: " + message + "; got \"" +
1838               actual +
1839               "\"; expected \"" + expected + "\"");
1840         return FALSE;
1841     }
1842 #ifdef VERBOSE_ASSERTIONS
1843     else {
1844         logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1845     }
1846 #endif
1847     return TRUE;
1848 }
1849
1850 UBool IntlTest::assertEquals(const char* message,
1851                              int32_t expected,
1852                              int32_t actual) {
1853     if (expected != actual) {
1854         errln((UnicodeString)"FAIL: " + message + "; got " +
1855               actual + "=0x" + toHex(actual) +
1856               "; expected " + expected + "=0x" + toHex(expected));
1857         return FALSE;
1858     }
1859 #ifdef VERBOSE_ASSERTIONS
1860     else {
1861         logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual));
1862     }
1863 #endif
1864     return TRUE;
1865 }
1866
1867 UBool IntlTest::assertEquals(const char* message,
1868                              int64_t expected,
1869                              int64_t actual) {
1870     if (expected != actual) {
1871         errln((UnicodeString)"FAIL: " + message + "; got int64 " +
1872               Int64ToUnicodeString(actual) + 
1873               "; expected " + Int64ToUnicodeString(expected) );
1874         return FALSE;
1875     }
1876 #ifdef VERBOSE_ASSERTIONS
1877     else {
1878       logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual));
1879     }
1880 #endif
1881     return TRUE;
1882 }
1883
1884 UBool IntlTest::assertEquals(const char* message,
1885                              UBool expected,
1886                              UBool actual) {
1887     if (expected != actual) {
1888         errln((UnicodeString)"FAIL: " + message + "; got " +
1889               toString(actual) +
1890               "; expected " + toString(expected));
1891         return FALSE;
1892     }
1893 #ifdef VERBOSE_ASSERTIONS
1894     else {
1895       logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1896     }
1897 #endif
1898     return TRUE;
1899 }
1900
1901 #if !UCONFIG_NO_FORMATTING
1902 UBool IntlTest::assertEquals(const char* message,
1903                              const Formattable& expected,
1904                              const Formattable& actual,
1905                              UBool possibleDataError) {
1906     if (expected != actual) {
1907         if (possibleDataError) {
1908             dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1909                   toString(actual) +
1910                   "; expected " + toString(expected));
1911         } else {
1912             errln((UnicodeString)"FAIL: " + message + "; got " +
1913                   toString(actual) +
1914                   "; expected " + toString(expected));
1915         }
1916         return FALSE;
1917     }
1918 #ifdef VERBOSE_ASSERTIONS
1919     else {
1920         logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1921     }
1922 #endif
1923     return TRUE;
1924 }
1925 #endif
1926
1927 static char ASSERT_BUF[256];
1928
1929 static const char* extractToAssertBuf(const UnicodeString& message) {
1930     UnicodeString buf;
1931     escape(message, buf);
1932     buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1933     ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1934     return ASSERT_BUF;
1935 }
1936
1937 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1938     return assertTrue(extractToAssertBuf(message), condition, quiet);
1939 }
1940
1941 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1942     return assertFalse(extractToAssertBuf(message), condition, quiet);
1943 }
1944
1945 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1946     return assertSuccess(extractToAssertBuf(message), ec);
1947 }
1948
1949 UBool IntlTest::assertEquals(const UnicodeString& message,
1950                              const UnicodeString& expected,
1951                              const UnicodeString& actual,
1952                              UBool possibleDataError) {
1953     return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
1954 }
1955
1956 UBool IntlTest::assertEquals(const UnicodeString& message,
1957                              const char* expected,
1958                              const char* actual) {
1959     return assertEquals(extractToAssertBuf(message), expected, actual);
1960 }
1961 UBool IntlTest::assertEquals(const UnicodeString& message,
1962                              UBool expected,
1963                              UBool actual) {
1964     return assertEquals(extractToAssertBuf(message), expected, actual);
1965 }
1966 UBool IntlTest::assertEquals(const UnicodeString& message,
1967                              int32_t expected,
1968                              int32_t actual) {
1969     return assertEquals(extractToAssertBuf(message), expected, actual);
1970 }
1971 UBool IntlTest::assertEquals(const UnicodeString& message,
1972                              int64_t expected,
1973                              int64_t actual) {
1974     return assertEquals(extractToAssertBuf(message), expected, actual);
1975 }
1976
1977 #if !UCONFIG_NO_FORMATTING
1978 UBool IntlTest::assertEquals(const UnicodeString& message,
1979                              const Formattable& expected,
1980                              const Formattable& actual) {
1981     return assertEquals(extractToAssertBuf(message), expected, actual);
1982 }
1983 #endif
1984
1985 void IntlTest::setProperty(const char* propline) {
1986     if (numProps < kMaxProps) {
1987         proplines[numProps] = propline;
1988     }
1989     numProps++;
1990 }
1991
1992 const char* IntlTest::getProperty(const char* prop) {
1993     const char* val = NULL;
1994     for (int32_t i = 0; i < numProps; i++) {
1995         int32_t plen = uprv_strlen(prop);
1996         if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
1997                 && proplines[i][plen] == '='
1998                 && uprv_strncmp(proplines[i], prop, plen) == 0) {
1999             val = &(proplines[i][plen+1]);
2000             break;
2001         }
2002     }
2003     return val;
2004 }
2005
2006 /*
2007  * Hey, Emacs, please set the following:
2008  *
2009  * Local Variables:
2010  * indent-tabs-mode: nil
2011  * End:
2012  *
2013  */