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