• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2015, 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
UCharToUnicodeString(UChar c)62 UCharToUnicodeString(UChar c)
63 { return UnicodeString(c); }
64 
65 // [rtg] Just to get things working
66 UnicodeString
operator +(const UnicodeString & left,long num)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
operator +(const UnicodeString & left,unsigned long num)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
Int64ToUnicodeString(int64_t num)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
operator +(const UnicodeString & left,double num)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  */
_toString(const Formattable & f)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  */
toString(const Formattable & f)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
toString(int32_t n)214 UnicodeString toString(int32_t n) {
215     return UnicodeString() + (long)n;
216 }
217 
218 
219 
toString(UBool b)220 UnicodeString toString(UBool b) {
221   return b ? UnicodeString("TRUE"):UnicodeString("FALSE");
222 }
223 
224 // stephen - cleaned up 05/05/99
operator +(const UnicodeString & left,char num)225 UnicodeString operator+(const UnicodeString& left, char num)
226 { return left + (long)num; }
operator +(const UnicodeString & left,short num)227 UnicodeString operator+(const UnicodeString& left, short num)
228 { return left + (long)num; }
operator +(const UnicodeString & left,int num)229 UnicodeString operator+(const UnicodeString& left, int num)
230 { return left + (long)num; }
operator +(const UnicodeString & left,unsigned char num)231 UnicodeString operator+(const UnicodeString& left, unsigned char num)
232 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned short num)233 UnicodeString operator+(const UnicodeString& left, unsigned short num)
234 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned int num)235 UnicodeString operator+(const UnicodeString& left, unsigned int num)
236 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,float 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&
appendHex(uint32_t number,int32_t digits,UnicodeString & target)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
toHex(uint32_t number,int32_t digits)287 IntlTest::toHex(uint32_t number, int32_t digits) {
288     UnicodeString result;
289     appendHex(number, digits, result);
290     return result;
291 }
292 
isPrintable(UChar32 c)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&
prettify(const UnicodeString & source,UnicodeString & target)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
prettify(const UnicodeString & source,UBool parseBackslash)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  */
setICU_DATA()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 
it_log(UnicodeString message)469 void it_log( UnicodeString message )
470 {
471     if (IntlTest::gTest)
472         IntlTest::gTest->log( message );
473 }
474 
it_logln(UnicodeString message)475 void it_logln( UnicodeString message )
476 {
477     if (IntlTest::gTest)
478         IntlTest::gTest->logln( message );
479 }
480 
it_logln(void)481 void it_logln( void )
482 {
483     if (IntlTest::gTest)
484         IntlTest::gTest->logln();
485 }
486 
it_info(UnicodeString message)487 void it_info( UnicodeString message )
488 {
489     if (IntlTest::gTest)
490         IntlTest::gTest->info( message );
491 }
492 
it_infoln(UnicodeString message)493 void it_infoln( UnicodeString message )
494 {
495     if (IntlTest::gTest)
496         IntlTest::gTest->infoln( message );
497 }
498 
it_infoln(void)499 void it_infoln( void )
500 {
501     if (IntlTest::gTest)
502         IntlTest::gTest->infoln();
503 }
504 
it_err()505 void it_err()
506 {
507     if (IntlTest::gTest)
508         IntlTest::gTest->err();
509 }
510 
it_err(UnicodeString message)511 void it_err( UnicodeString message )
512 {
513     if (IntlTest::gTest)
514         IntlTest::gTest->err( message );
515 }
516 
it_errln(UnicodeString message)517 void it_errln( UnicodeString message )
518 {
519     if (IntlTest::gTest)
520         IntlTest::gTest->errln( message );
521 }
522 
it_dataerr(UnicodeString message)523 void it_dataerr( UnicodeString message )
524 {
525     if (IntlTest::gTest)
526         IntlTest::gTest->dataerr( message );
527 }
528 
it_dataerrln(UnicodeString message)529 void it_dataerrln( UnicodeString message )
530 {
531     if (IntlTest::gTest)
532         IntlTest::gTest->dataerrln( message );
533 }
534 
IntlTest()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 
setCaller(IntlTest * callingTest)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         threadCount = caller->threadCount;
565         testoutfp = caller->testoutfp;
566         LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
567         numProps = caller->numProps;
568         for (int32_t i = 0; i < numProps; i++) {
569             proplines[i] = caller->proplines[i];
570         }
571     }
572 }
573 
callTest(IntlTest & testToBeCalled,char * par)574 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
575 {
576     execCount--; // correct a previously assumed test-exec, as this only calls a subtest
577     testToBeCalled.setCaller( this );
578     strcpy(testToBeCalled.basePath, this->basePath );
579     UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath );
580     strcpy(testToBeCalled.basePath, this->basePath ); // reset it.
581     return result;
582 }
583 
setPath(char * pathVal)584 void IntlTest::setPath( char* pathVal )
585 {
586     this->testPath = pathVal;
587 }
588 
setVerbose(UBool verboseVal)589 UBool IntlTest::setVerbose( UBool verboseVal )
590 {
591     UBool rval = this->verbose;
592     this->verbose = verboseVal;
593     return rval;
594 }
595 
setNotime(UBool no_time)596 UBool IntlTest::setNotime( UBool no_time )
597 {
598     UBool rval = this->no_time;
599     this->no_time = no_time;
600     return rval;
601 }
602 
setWarnOnMissingData(UBool warn_on_missing_dataVal)603 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
604 {
605     UBool rval = this->warn_on_missing_data;
606     this->warn_on_missing_data = warn_on_missing_dataVal;
607     return rval;
608 }
609 
setNoErrMsg(UBool no_err_msgVal)610 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
611 {
612     UBool rval = this->no_err_msg;
613     this->no_err_msg = no_err_msgVal;
614     return rval;
615 }
616 
setQuick(UBool quickVal)617 UBool IntlTest::setQuick( UBool quickVal )
618 {
619     UBool rval = this->quick;
620     this->quick = quickVal;
621     return rval;
622 }
623 
setLeaks(UBool leaksVal)624 UBool IntlTest::setLeaks( UBool leaksVal )
625 {
626     UBool rval = this->leaks;
627     this->leaks = leaksVal;
628     return rval;
629 }
630 
setThreadCount(int32_t count)631 int32_t IntlTest::setThreadCount( int32_t count )
632 {
633     int32_t rval = this->threadCount;
634     this->threadCount = count;
635     return rval;
636 }
637 
getErrors(void)638 int32_t IntlTest::getErrors( void )
639 {
640     return errorCount;
641 }
642 
getDataErrors(void)643 int32_t IntlTest::getDataErrors( void )
644 {
645     return dataErrorCount;
646 }
647 
runTest(char * name,char * par,char * baseName)648 UBool IntlTest::runTest( char* name, char* par, char *baseName )
649 {
650     UBool rval;
651     char* pos = NULL;
652 
653     char* baseNameBuffer = NULL;
654 
655     if(baseName == NULL) {
656       baseNameBuffer = (char*)malloc(1024);
657       baseName=baseNameBuffer;
658       strcpy(baseName, "/");
659     }
660 
661     if (name)
662         pos = strchr( name, delim ); // check if name contains path (by looking for '/')
663     if (pos) {
664         testPath = pos+1;   // store subpath for calling subtest
665         *pos = 0;       // split into two strings
666     }else{
667         testPath = NULL;
668     }
669 
670     if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
671       rval = runTestLoop( NULL, par, baseName );
672 
673     }else if (strcmp( name, "LIST" ) == 0) {
674         this->usage();
675         rval = TRUE;
676 
677     }else{
678       rval = runTestLoop( name, par, baseName );
679     }
680 
681     if (pos)
682         *pos = delim;  // restore original value at pos
683     if(baseNameBuffer!=NULL) {
684       free(baseNameBuffer);
685     }
686     return rval;
687 }
688 
689 // call individual tests, to be overriden to call implementations
runIndexedTest(int32_t,UBool,const char * &,char *)690 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
691 {
692     // to be overriden by a method like:
693     /*
694     switch (index) {
695         case 0: name = "First Test"; if (exec) FirstTest( par ); break;
696         case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
697         default: name = ""; break;
698     }
699     */
700     this->errln("*** runIndexedTest needs to be overriden! ***");
701 }
702 
703 
runTestLoop(char * testname,char * par,char * baseName)704 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
705 {
706     int32_t    index = 0;
707     const char*   name;
708     UBool  run_this_test;
709     int32_t    lastErrorCount;
710     UBool  rval = FALSE;
711     UBool   lastTestFailed;
712 
713     if(baseName == NULL) {
714       printf("ERROR: baseName can't be null.\n");
715       return FALSE;
716     } else {
717       if ((char *)this->basePath != baseName) {
718         strcpy(this->basePath, baseName);
719       }
720     }
721 
722     char * saveBaseLoc = baseName+strlen(baseName);
723 
724     IntlTest* saveTest = gTest;
725     gTest = this;
726     do {
727         this->runIndexedTest( index, FALSE, name, par );
728         if (strcmp(name,"skip") == 0) {
729             run_this_test = FALSE;
730         } else {
731             if (!name || (name[0] == 0))
732                 break;
733             if (!testname) {
734                 run_this_test = TRUE;
735             }else{
736                 run_this_test = (UBool) (strcmp( name, testname ) == 0);
737             }
738         }
739         if (run_this_test) {
740             lastErrorCount = errorCount;
741             execCount++;
742             char msg[256];
743             sprintf(msg, "%s {", name);
744             LL_message(msg, TRUE);
745             UDate timeStart = uprv_getRawUTCtime();
746             strcpy(saveBaseLoc,name);
747             strcat(saveBaseLoc,"/");
748 
749             strcpy(currName, name); // set
750             this->runIndexedTest( index, TRUE, name, par );
751             currName[0]=0; // reset
752 
753             UDate timeStop = uprv_getRawUTCtime();
754             rval = TRUE; // at least one test has been called
755             char secs[256];
756             if(!no_time) {
757               sprintf(secs, "%f", (timeStop-timeStart)/1000.0);
758             } else {
759               secs[0]=0;
760             }
761 
762 
763             strcpy(saveBaseLoc,name);
764 
765 
766             ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL);
767 
768 
769             saveBaseLoc[0]=0; /* reset path */
770 
771             if (lastErrorCount == errorCount) {
772                 sprintf( msg, "   } OK:   %s ", name );
773                 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
774                 lastTestFailed = FALSE;
775             }else{
776                 sprintf(msg,  "   } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
777                 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
778 
779                 for(int i=0;i<LL_indentlevel;i++) {
780                     errorList += " ";
781                 }
782                 errorList += name;
783                 errorList += "\n";
784                 lastTestFailed = TRUE;
785             }
786             LL_indentlevel -= 3;
787             if (lastTestFailed) {
788                 LL_message( "", TRUE);
789             }
790             LL_message( msg, TRUE);
791             if (lastTestFailed) {
792                 LL_message( "", TRUE);
793             }
794             LL_indentlevel += 3;
795         }
796         index++;
797     }while(name);
798 
799     *saveBaseLoc = 0;
800 
801     gTest = saveTest;
802     return rval;
803 }
804 
805 
806 /**
807 * Adds given string to the log if we are in verbose mode.
808 */
log(const UnicodeString & message)809 void IntlTest::log( const UnicodeString &message )
810 {
811     if( verbose ) {
812         LL_message( message, FALSE );
813     }
814 }
815 
816 /**
817 * Adds given string to the log if we are in verbose mode. Adds a new line to
818 * the given message.
819 */
logln(const UnicodeString & message)820 void IntlTest::logln( const UnicodeString &message )
821 {
822     if( verbose ) {
823         LL_message( message, TRUE );
824     }
825 }
826 
logln(void)827 void IntlTest::logln( void )
828 {
829     if( verbose ) {
830         LL_message( "", TRUE );
831     }
832 }
833 
834 /**
835 * Unconditionally adds given string to the log.
836 */
info(const UnicodeString & message)837 void IntlTest::info( const UnicodeString &message )
838 {
839   LL_message( message, FALSE );
840 }
841 
842 /**
843 * Unconditionally adds given string to the log. Adds a new line to
844 * the given message.
845 */
infoln(const UnicodeString & message)846 void IntlTest::infoln( const UnicodeString &message )
847 {
848   LL_message( message, TRUE );
849 }
850 
infoln(void)851 void IntlTest::infoln( void )
852 {
853   LL_message( "", TRUE );
854 }
855 
IncErrorCount(void)856 int32_t IntlTest::IncErrorCount( void )
857 {
858     errorCount++;
859     if (caller) caller->IncErrorCount();
860     return errorCount;
861 }
862 
IncDataErrorCount(void)863 int32_t IntlTest::IncDataErrorCount( void )
864 {
865     dataErrorCount++;
866     if (caller) caller->IncDataErrorCount();
867     return dataErrorCount;
868 }
869 
err()870 void IntlTest::err()
871 {
872     IncErrorCount();
873 }
874 
err(const UnicodeString & message)875 void IntlTest::err( const UnicodeString &message )
876 {
877     IncErrorCount();
878     if (!no_err_msg) LL_message( message, FALSE );
879 }
880 
errln(const UnicodeString & message)881 void IntlTest::errln( const UnicodeString &message )
882 {
883     IncErrorCount();
884     if (!no_err_msg) LL_message( message, TRUE );
885 }
886 
dataerr(const UnicodeString & message)887 void IntlTest::dataerr( const UnicodeString &message )
888 {
889     IncDataErrorCount();
890 
891     if (!warn_on_missing_data) {
892         IncErrorCount();
893     }
894 
895     if (!no_err_msg) LL_message( message, FALSE );
896 }
897 
dataerrln(const UnicodeString & message)898 void IntlTest::dataerrln( const UnicodeString &message )
899 {
900     int32_t errCount = IncDataErrorCount();
901     UnicodeString msg;
902     if (!warn_on_missing_data) {
903         IncErrorCount();
904         msg = message;
905     } else {
906         msg = UnicodeString("[DATA] " + message);
907     }
908 
909     if (!no_err_msg) {
910       if ( errCount == 1) {
911           LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
912       } else {
913           LL_message( msg , TRUE );
914       }
915     }
916 }
917 
errcheckln(UErrorCode status,const UnicodeString & message)918 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
919     if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
920         dataerrln(message);
921     } else {
922         errln(message);
923     }
924 }
925 
926 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)927 void IntlTest::log(const char *fmt, ...)
928 {
929     char buffer[4000];
930     va_list ap;
931 
932     va_start(ap, fmt);
933     /* sprintf it just to make sure that the information is valid */
934     vsprintf(buffer, fmt, ap);
935     va_end(ap);
936     if( verbose ) {
937         log(UnicodeString(buffer, ""));
938     }
939 }
940 
logln(const char * fmt,...)941 void IntlTest::logln(const char *fmt, ...)
942 {
943     char buffer[4000];
944     va_list ap;
945 
946     va_start(ap, fmt);
947     /* sprintf it just to make sure that the information is valid */
948     vsprintf(buffer, fmt, ap);
949     va_end(ap);
950     if( verbose ) {
951         logln(UnicodeString(buffer, ""));
952     }
953 }
954 
logKnownIssue(const char * ticket,const char * fmt,...)955 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...)
956 {
957     char buffer[4000];
958     va_list ap;
959 
960     va_start(ap, fmt);
961     /* sprintf it just to make sure that the information is valid */
962     vsprintf(buffer, fmt, ap);
963     va_end(ap);
964     return logKnownIssue(ticket, UnicodeString(buffer, ""));
965 }
966 
logKnownIssue(const char * ticket)967 UBool IntlTest::logKnownIssue(const char *ticket) {
968   return logKnownIssue(ticket, UnicodeString());
969 }
970 
logKnownIssue(const char * ticket,const UnicodeString & msg)971 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) {
972   if(noKnownIssues) return FALSE;
973 
974   char fullpath[2048];
975   strcpy(fullpath, basePath);
976   strcat(fullpath, currName);
977   UnicodeString msg2 = msg;
978   UBool firstForTicket = TRUE, firstForWhere = TRUE;
979   knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere);
980 
981   msg2 = UNICODE_STRING_SIMPLE("(Known issue #") +
982       UnicodeString(ticket, -1, US_INV) + UNICODE_STRING_SIMPLE(") ") + msg;
983   if(firstForTicket || firstForWhere) {
984     infoln(msg2);
985   } else {
986     logln(msg2);
987   }
988 
989   return TRUE;
990 }
991 
992 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)993 void IntlTest::info(const char *fmt, ...)
994 {
995     char buffer[4000];
996     va_list ap;
997 
998     va_start(ap, fmt);
999     /* sprintf it just to make sure that the information is valid */
1000     vsprintf(buffer, fmt, ap);
1001     va_end(ap);
1002     info(UnicodeString(buffer, ""));
1003 }
1004 
infoln(const char * fmt,...)1005 void IntlTest::infoln(const char *fmt, ...)
1006 {
1007     char buffer[4000];
1008     va_list ap;
1009 
1010     va_start(ap, fmt);
1011     /* sprintf it just to make sure that the information is valid */
1012     vsprintf(buffer, fmt, ap);
1013     va_end(ap);
1014     infoln(UnicodeString(buffer, ""));
1015 }
1016 
err(const char * fmt,...)1017 void IntlTest::err(const char *fmt, ...)
1018 {
1019     char buffer[4000];
1020     va_list ap;
1021 
1022     va_start(ap, fmt);
1023     vsprintf(buffer, fmt, ap);
1024     va_end(ap);
1025     err(UnicodeString(buffer, ""));
1026 }
1027 
errln(const char * fmt,...)1028 void IntlTest::errln(const char *fmt, ...)
1029 {
1030     char buffer[4000];
1031     va_list ap;
1032 
1033     va_start(ap, fmt);
1034     vsprintf(buffer, fmt, ap);
1035     va_end(ap);
1036     errln(UnicodeString(buffer, ""));
1037 }
1038 
dataerrln(const char * fmt,...)1039 void IntlTest::dataerrln(const char *fmt, ...)
1040 {
1041     char buffer[4000];
1042     va_list ap;
1043 
1044     va_start(ap, fmt);
1045     vsprintf(buffer, fmt, ap);
1046     va_end(ap);
1047     dataerrln(UnicodeString(buffer, ""));
1048 }
1049 
errcheckln(UErrorCode status,const char * fmt,...)1050 void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...)
1051 {
1052     char buffer[4000];
1053     va_list ap;
1054 
1055     va_start(ap, fmt);
1056     vsprintf(buffer, fmt, ap);
1057     va_end(ap);
1058 
1059     if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
1060         dataerrln(UnicodeString(buffer, ""));
1061     } else {
1062         errln(UnicodeString(buffer, ""));
1063     }
1064 }
1065 
printErrors()1066 void IntlTest::printErrors()
1067 {
1068      IntlTest::LL_message(errorList, TRUE);
1069 }
1070 
printKnownIssues()1071 UBool IntlTest::printKnownIssues()
1072 {
1073   if(knownList != NULL) {
1074     udbg_knownIssue_print(knownList);
1075     udbg_knownIssue_close(knownList);
1076     return TRUE;
1077   } else {
1078     return FALSE;
1079   }
1080 }
1081 
LL_message(UnicodeString message,UBool newline)1082 void IntlTest::LL_message( UnicodeString message, UBool newline )
1083 {
1084     // string that starts with a LineFeed character and continues
1085     // with spaces according to the current indentation
1086     static const UChar indentUChars[] = {
1087         '\n',
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         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1096         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1097         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1098     };
1099     UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
1100 
1101     char buffer[30000];
1102     int32_t length;
1103 
1104     // stream out the indentation string first if necessary
1105     length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
1106     if (length > 0) {
1107         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1108     }
1109 
1110     // replace each LineFeed by the indentation string
1111     message.findAndReplace(UnicodeString((UChar)'\n'), indent);
1112 
1113     // stream out the message
1114     length = message.extract(0, message.length(), buffer, sizeof(buffer));
1115     if (length > 0) {
1116         length = length > 30000 ? 30000 : length;
1117         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1118     }
1119 
1120     if (newline) {
1121         char newLine = '\n';
1122         fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
1123     }
1124 
1125     // A newline usually flushes the buffer, but
1126     // flush the message just in case of a core dump.
1127     fflush((FILE *)testoutfp);
1128 }
1129 
1130 /**
1131 * Print a usage message for this test class.
1132 */
usage(void)1133 void IntlTest::usage( void )
1134 {
1135     UBool save_verbose = setVerbose( TRUE );
1136     logln("Test names:");
1137     logln("-----------");
1138 
1139     int32_t index = 0;
1140     const char* name = NULL;
1141     do{
1142         this->runIndexedTest( index, FALSE, name );
1143         if (!name) break;
1144         logln(name);
1145         index++;
1146     }while (name && (name[0] != 0));
1147     setVerbose( save_verbose );
1148 }
1149 
1150 
1151 // memory leak reporting software will be able to take advantage of the testsuite
1152 // being run a second time local to a specific method in order to report only actual leaks
1153 UBool
run_phase2(char * name,char * par)1154 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1155 {
1156     UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1157     strLeak->append(" for verifying purify filter");
1158     return this->runTest( name, par );
1159 }
1160 
1161 
1162 #if UCONFIG_NO_LEGACY_CONVERSION
1163 #   define TRY_CNV_1 "iso-8859-1"
1164 #   define TRY_CNV_2 "ibm-1208"
1165 #else
1166 #   define TRY_CNV_1 "iso-8859-7"
1167 #   define TRY_CNV_2 "sjis"
1168 #endif
1169 
1170 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1171 U_CAPI void unistr_printLengths();
1172 #endif
1173 
1174 int
main(int argc,char * argv[])1175 main(int argc, char* argv[])
1176 {
1177     UBool syntax = FALSE;
1178     UBool all = FALSE;
1179     UBool verbose = FALSE;
1180     UBool no_err_msg = FALSE;
1181     UBool no_time = FALSE;
1182     UBool quick = TRUE;
1183     UBool name = FALSE;
1184     UBool leaks = FALSE;
1185     UBool utf8 = FALSE;
1186     const char *summary_file = NULL;
1187     UBool warnOnMissingData = FALSE;
1188     UBool defaultDataFound = FALSE;
1189     int32_t threadCount = 1;
1190     UErrorCode errorCode = U_ZERO_ERROR;
1191     UConverter *cnv = NULL;
1192     const char *warnOrErr = "Failure";
1193     UDate startTime, endTime;
1194     int32_t diffTime;
1195     const char *props[IntlTest::kMaxProps];
1196     int32_t nProps = 0;
1197 
1198     U_MAIN_INIT_ARGS(argc, argv);
1199 
1200     startTime = uprv_getRawUTCtime();
1201 
1202     for (int i = 1; i < argc; ++i) {
1203         if (argv[i][0] == '-') {
1204             const char* str = argv[i] + 1;
1205             if (strcmp("verbose", str) == 0 ||
1206                 strcmp("v", str) == 0)
1207                 verbose = TRUE;
1208             else if (strcmp("noerrormsg", str) == 0 ||
1209                      strcmp("n", str) == 0)
1210                 no_err_msg = TRUE;
1211             else if (strcmp("exhaustive", str) == 0 ||
1212                      strcmp("e", str) == 0)
1213                 quick = FALSE;
1214             else if (strcmp("all", str) == 0 ||
1215                      strcmp("a", str) == 0)
1216                 all = TRUE;
1217             else if (strcmp("utf-8", str) == 0 ||
1218                      strcmp("u", str) == 0)
1219                 utf8 = TRUE;
1220             else if (strcmp("noknownissues", str) == 0 ||
1221                      strcmp("K", str) == 0)
1222                 noKnownIssues = TRUE;
1223             else if (strcmp("leaks", str) == 0 ||
1224                      strcmp("l", str) == 0)
1225                 leaks = TRUE;
1226             else if (strcmp("notime", str) == 0 ||
1227                      strcmp("T", str) == 0)
1228                 no_time = TRUE;
1229             else if (strncmp("E", str, 1) == 0)
1230                 summary_file = str+1;
1231             else if (strcmp("x", str)==0) {
1232               if(++i>=argc) {
1233                 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1234                 syntax = TRUE;
1235               }
1236               if(ctest_xml_setFileName(argv[i])) { /* set the name */
1237                 return 1; /* error */
1238               }
1239             } else if (strcmp("w", str) == 0) {
1240               warnOnMissingData = TRUE;
1241               warnOrErr = "WARNING";
1242             }
1243             else if (strncmp("threads:", str, 8) == 0) {
1244                 threadCount = atoi(str + 8);
1245             }
1246             else if (strncmp("prop:", str, 5) == 0) {
1247                 if (nProps < IntlTest::kMaxProps) {
1248                     props[nProps] = str + 5;
1249                 }
1250                 nProps++;
1251             }
1252             else {
1253                 syntax = TRUE;
1254             }
1255         }else{
1256             name = TRUE;
1257         }
1258     }
1259 
1260     if (!all && !name) {
1261         all = TRUE;
1262     } else if (all && name) {
1263         syntax = TRUE;
1264     }
1265 
1266     if (syntax) {
1267         fprintf(stdout,
1268                 "### Syntax:\n"
1269                 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1270                 "### \n"
1271                 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1272                 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1273                 "### notime (T), \n"
1274                 "### threads:<threadCount> (Mulithreading must first be \n"
1275                 "###     enabled otherwise this will be ignored. \n"
1276                 "###     The default thread count is 1.),\n"
1277                 "### (Specify either -all (shortcut -a) or a test name). \n"
1278                 "### -all will run all of the tests.\n"
1279                 "### \n"
1280                 "### To get a list of the test names type: intltest LIST \n"
1281                 "### To run just the utility tests type: intltest utility \n"
1282                 "### \n"
1283                 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1284                 "### For example to list the utility tests type: intltest utility/LIST \n"
1285                 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1286                 "### \n"
1287                 "### A parameter can be specified for a test by appending '@' and the value \n"
1288                 "### to the testname. \n\n");
1289         return 1;
1290     }
1291 
1292     if (nProps > IntlTest::kMaxProps) {
1293         fprintf(stdout, "### Too many properties.  Exiting.\n");
1294     }
1295 
1296     MajorTestLevel major;
1297     major.setVerbose( verbose );
1298     major.setNoErrMsg( no_err_msg );
1299     major.setQuick( quick );
1300     major.setLeaks( leaks );
1301     major.setThreadCount( threadCount );
1302     major.setWarnOnMissingData( warnOnMissingData );
1303     major.setNotime (no_time);
1304     for (int32_t i = 0; i < nProps; i++) {
1305         major.setProperty(props[i]);
1306     }
1307 
1308 
1309     fprintf(stdout, "-----------------------------------------------\n");
1310     fprintf(stdout, " IntlTest (C++) Test Suite for                 \n");
1311     fprintf(stdout, "   International Components for Unicode %s\n", U_ICU_VERSION);
1312 
1313 
1314     {
1315 	const char *charsetFamily = "Unknown";
1316         int32_t voidSize = (int32_t)sizeof(void*);
1317         int32_t bits = voidSize * 8;
1318         if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1319            charsetFamily="ASCII";
1320         } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1321            charsetFamily="EBCDIC";
1322         }
1323         fprintf(stdout,
1324                     "   Bits: %d, Byte order: %s, Chars: %s\n",
1325                      bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1326                      charsetFamily);
1327     }
1328     fprintf(stdout, "-----------------------------------------------\n");
1329     fprintf(stdout, " Options:                                       \n");
1330     fprintf(stdout, "   all (a)                  : %s\n", (all?               "On" : "Off"));
1331     fprintf(stdout, "   Verbose (v)              : %s\n", (verbose?           "On" : "Off"));
1332     fprintf(stdout, "   No error messages (n)    : %s\n", (no_err_msg?        "On" : "Off"));
1333     fprintf(stdout, "   Exhaustive (e)           : %s\n", (!quick?            "On" : "Off"));
1334     fprintf(stdout, "   Leaks (l)                : %s\n", (leaks?             "On" : "Off"));
1335     fprintf(stdout, "   utf-8 (u)                : %s\n", (utf8?              "On" : "Off"));
1336     fprintf(stdout, "   notime (T)               : %s\n", (no_time?             "On" : "Off"));
1337     fprintf(stdout, "   noknownissues (K)        : %s\n", (noKnownIssues?      "On" : "Off"));
1338     fprintf(stdout, "   Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1339     fprintf(stdout, "   Threads                  : %d\n", threadCount);
1340     for (int32_t i = 0; i < nProps; i++) {
1341         fprintf(stdout, "   Custom property (prop:)  : %s\n", props[i]);
1342     }
1343     fprintf(stdout, "-----------------------------------------------\n");
1344 
1345     if(utf8) {
1346       ucnv_setDefaultName("utf-8");
1347     }
1348     /* Check whether ICU will initialize without forcing the build data directory into
1349      *  the ICU_DATA path.  Success here means either the data dll contains data, or that
1350      *  this test program was run with ICU_DATA set externally.  Failure of this check
1351      *  is normal when ICU data is not packaged into a shared library.
1352      *
1353      *  Whether or not this test succeeds, we want to cleanup and reinitialize
1354      *  with a data path so that data loading from individual files can be tested.
1355      */
1356     u_init(&errorCode);
1357     if (U_FAILURE(errorCode)) {
1358         fprintf(stderr,
1359             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
1360         defaultDataFound = FALSE;
1361     }
1362     else {
1363         defaultDataFound = TRUE;
1364     }
1365     u_cleanup();
1366     if(utf8) {
1367       ucnv_setDefaultName("utf-8");
1368     }
1369     errorCode = U_ZERO_ERROR;
1370 
1371     /* Initialize ICU */
1372     if (!defaultDataFound) {
1373         IntlTest::setICU_DATA();   // Must set data directory before u_init() is called.
1374     }
1375     u_init(&errorCode);
1376     if (U_FAILURE(errorCode)) {
1377         fprintf(stderr,
1378             "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1379             "*** Check the ICU_DATA environment variable and \n"
1380             "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1381             if(warnOnMissingData == 0) {
1382                 fprintf(stderr, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1383                 u_cleanup();
1384                 return 1;
1385             }
1386     }
1387 
1388     // initial check for the default converter
1389     errorCode = U_ZERO_ERROR;
1390     cnv = ucnv_open(0, &errorCode);
1391     if(cnv != 0) {
1392         // ok
1393         ucnv_close(cnv);
1394     } else {
1395         fprintf(stdout,
1396                 "*** %s! The default converter [%s] cannot be opened.\n"
1397                 "*** Check the ICU_DATA environment variable and\n"
1398                 "*** check that the data files are present.\n",
1399                 warnOrErr, ucnv_getDefaultName());
1400         if(!warnOnMissingData) {
1401           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1402           return 1;
1403         }
1404     }
1405 
1406     // try more data
1407     cnv = ucnv_open(TRY_CNV_2, &errorCode);
1408     if(cnv != 0) {
1409         // ok
1410         ucnv_close(cnv);
1411     } else {
1412         fprintf(stdout,
1413                 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1414                 "*** Check the ICU_DATA environment variable and \n"
1415                 "*** check that the data files are present.\n", warnOrErr);
1416         if(!warnOnMissingData) {
1417           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1418           return 1;
1419         }
1420     }
1421 
1422     UResourceBundle *rb = ures_open(0, "en", &errorCode);
1423     ures_close(rb);
1424     if(U_FAILURE(errorCode)) {
1425         fprintf(stdout,
1426                 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1427                 "*** Check the ICU_DATA environment variable and \n"
1428                 "*** check that the data files are present.\n", warnOrErr);
1429         if(!warnOnMissingData) {
1430           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1431           return 1;
1432         }
1433     }
1434 
1435     Locale originalLocale;  // Save the default locale for comparison later on.
1436 
1437     if(ctest_xml_init("intltest"))
1438       return 1;
1439 
1440 
1441     /* TODO: Add option to call u_cleanup and rerun tests. */
1442     if (all) {
1443         major.runTest();
1444         if (leaks) {
1445             major.run_phase2( NULL, NULL );
1446         }
1447     }else{
1448         for (int i = 1; i < argc; ++i) {
1449             if (argv[i][0] != '-') {
1450                 char* name = argv[i];
1451                 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1452 
1453                 char baseName[1024];
1454                 sprintf(baseName, "/%s/", name);
1455 
1456                 char* parameter = strchr( name, '@' );
1457                 if (parameter) {
1458                     *parameter = 0;
1459                     parameter += 1;
1460                 }
1461                 execCount = 0;
1462                 UBool res = major.runTest( name, parameter, baseName );
1463                 if (leaks && res) {
1464                     major.run_phase2( name, parameter );
1465                 }
1466                 if (!res || (execCount <= 0)) {
1467                     fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1468                 }
1469             } else if(!strcmp(argv[i],"-x")) {
1470               i++;
1471             }
1472         }
1473     }
1474 
1475 
1476 #if !UCONFIG_NO_FORMATTING
1477     CalendarTimeZoneTest::cleanup();
1478 #endif
1479 
1480     free(_testDataPath);
1481     _testDataPath = 0;
1482 
1483     Locale lastDefaultLocale;
1484     if (originalLocale != lastDefaultLocale) {
1485         major.errln("FAILURE: A test changed the default locale without resetting it.");
1486     }
1487 
1488     fprintf(stdout, "\n--------------------------------------\n");
1489     if( major.printKnownIssues() ) {
1490       fprintf(stdout, " To run suppressed tests, use the -K option. \n");
1491     }
1492     if (major.getErrors() == 0) {
1493         /* Call it twice to make sure that the defaults were reset. */
1494         /* Call it before the OK message to verify proper cleanup. */
1495         u_cleanup();
1496         u_cleanup();
1497 
1498         fprintf(stdout, "OK: All tests passed without error.\n");
1499 
1500         if (major.getDataErrors() != 0) {
1501             fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1502         }
1503     }else{
1504         fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1505         major.printErrors();
1506 
1507         if(summary_file != NULL) {
1508           FILE *summf = fopen(summary_file, "w");
1509           if( summf != NULL) {
1510             char buf[10000];
1511             int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf));
1512             fwrite(buf, sizeof(*buf), length, (FILE*)summf);
1513             fclose(summf);
1514           }
1515         }
1516 
1517 
1518         if (major.getDataErrors() != 0) {
1519             fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1520                     "\tstock ICU data (i.e some have been added or removed), consider using\n"
1521                     "\tthe '-w' option to turn these errors into warnings.\n");
1522         }
1523 
1524         /* Call afterwards to display errors. */
1525         u_cleanup();
1526     }
1527 
1528 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1529     unistr_printLengths();
1530 #endif
1531 
1532     fprintf(stdout, "--------------------------------------\n");
1533 
1534     if (execCount <= 0) {
1535         fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1536     }
1537     if(!no_time) {
1538       endTime = uprv_getRawUTCtime();
1539       diffTime = (int32_t)(endTime - startTime);
1540       printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1541              (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1542              (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1543              (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1544              (int)(diffTime%U_MILLIS_PER_SECOND));
1545     }
1546 
1547     if(ctest_xml_fini())
1548       return 1;
1549 
1550     return major.getErrors();
1551 }
1552 
loadTestData(UErrorCode & err)1553 const char* IntlTest::loadTestData(UErrorCode& err){
1554     if( _testDataPath == NULL){
1555         const char*      directory=NULL;
1556         UResourceBundle* test =NULL;
1557         char* tdpath=NULL;
1558         const char* tdrelativepath;
1559 
1560 #if defined (U_TOPBUILDDIR)
1561         tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1562         directory = U_TOPBUILDDIR;
1563 #else
1564         tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1565         directory = pathToDataDirectory();
1566 #endif
1567 
1568         tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1569 
1570 
1571         /* u_getDataDirectory shoul return \source\data ... set the
1572          * directory to ..\source\data\..\test\testdata\out\testdata
1573          */
1574         strcpy(tdpath, directory);
1575         strcat(tdpath, tdrelativepath);
1576         strcat(tdpath,"testdata");
1577 
1578         test=ures_open(tdpath, "testtypes", &err);
1579 
1580         if(U_FAILURE(err)){
1581             err = U_FILE_ACCESS_ERROR;
1582             it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1583             return "";
1584         }
1585         ures_close(test);
1586         _testDataPath = tdpath;
1587         return _testDataPath;
1588     }
1589     return _testDataPath;
1590 }
1591 
getTestDataPath(UErrorCode & err)1592 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1593     return loadTestData(err);
1594 }
1595 
1596 /* Returns the path to icu/source/test/testdata/ */
getSourceTestData(UErrorCode &)1597 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1598     const char *srcDataDir = NULL;
1599 #ifdef U_TOPSRCDIR
1600     srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1601 #else
1602     srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1603     FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r");
1604     if (f) {
1605         /* We're in icu/source/test/intltest/ */
1606         fclose(f);
1607     }
1608     else {
1609         /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1610         srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1611                      "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1612     }
1613 #endif
1614     return srcDataDir;
1615 }
1616 
getUnidataPath(char path[])1617 char *IntlTest::getUnidataPath(char path[]) {
1618     const int kUnicodeDataTxtLength = 15;  // strlen("UnicodeData.txt")
1619 
1620     // Look inside ICU_DATA first.
1621     strcpy(path, pathToDataDirectory());
1622     strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1623     FILE *f = fopen(path, "r");
1624     if(f != NULL) {
1625         fclose(f);
1626         *(strchr(path, 0) - kUnicodeDataTxtLength) = 0;  // Remove the basename.
1627         return path;
1628     }
1629 
1630     // As a fallback, try to guess where the source data was located
1631     // at the time ICU was built, and look there.
1632 #   ifdef U_TOPSRCDIR
1633         strcpy(path, U_TOPSRCDIR  U_FILE_SEP_STRING "data");
1634 #   else
1635         UErrorCode errorCode = U_ZERO_ERROR;
1636         const char *testDataPath = loadTestData(errorCode);
1637         if(U_FAILURE(errorCode)) {
1638             it_errln(UnicodeString(
1639                         "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1640                     u_errorName(errorCode));
1641             return NULL;
1642         }
1643         strcpy(path, testDataPath);
1644         strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1645                      U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1646                      U_FILE_SEP_STRING "data");
1647 #   endif
1648     strcat(path, U_FILE_SEP_STRING);
1649     strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1650     f = fopen(path, "r");
1651     if(f != NULL) {
1652         fclose(f);
1653         *(strchr(path, 0) - kUnicodeDataTxtLength) = 0;  // Remove the basename.
1654         return path;
1655     }
1656     return NULL;
1657 }
1658 
1659 const char* IntlTest::fgDataDir = NULL;
1660 
1661 /* returns the path to icu/source/data */
pathToDataDirectory()1662 const char *  IntlTest::pathToDataDirectory()
1663 {
1664 
1665     if(fgDataDir != NULL) {
1666         return fgDataDir;
1667     }
1668 
1669     /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1670     //              to point to the top of the build hierarchy, which may or
1671     //              may not be the same as the source directory, depending on
1672     //              the configure options used.  At any rate,
1673     //              set the data path to the built data from this directory.
1674     //              The value is complete with quotes, so it can be used
1675     //              as-is as a string constant.
1676     */
1677 #if defined (U_TOPSRCDIR)
1678     {
1679         fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1680     }
1681 #else
1682 
1683     /* On Windows, the file name obtained from __FILE__ includes a full path.
1684      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
1685      *             Change to    "wherever\icu\source\data"
1686      */
1687     {
1688         static char p[sizeof(__FILE__) + 10];
1689         char *pBackSlash;
1690         int i;
1691 
1692         strcpy(p, __FILE__);
1693         /* We want to back over three '\' chars.                            */
1694         /*   Only Windows should end up here, so looking for '\' is safe.   */
1695         for (i=1; i<=3; i++) {
1696             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1697             if (pBackSlash != NULL) {
1698                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
1699             }
1700         }
1701 
1702         if (pBackSlash != NULL) {
1703             /* We found and truncated three names from the path.
1704             *  Now append "source\data" and set the environment
1705             */
1706             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1707             fgDataDir = p;
1708         }
1709         else {
1710             /* __FILE__ on MSVC7 does not contain the directory */
1711             FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1712             if (file) {
1713                 fclose(file);
1714                 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1715             }
1716             else {
1717                 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1718             }
1719         }
1720     }
1721 #endif
1722 
1723     return fgDataDir;
1724 
1725 }
1726 
1727 /*
1728  * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1729  * It converts an invariant-character string into a UnicodeString, with
1730  * unescaping \u sequences.
1731  */
CharsToUnicodeString(const char * chars)1732 UnicodeString CharsToUnicodeString(const char* chars){
1733     return UnicodeString(chars, -1, US_INV).unescape();
1734 }
1735 
ctou(const char * chars)1736 UnicodeString ctou(const char* chars) {
1737     return CharsToUnicodeString(chars);
1738 }
1739 
1740 #define RAND_M  (714025)
1741 #define RAND_IA (1366)
1742 #define RAND_IC (150889)
1743 
1744 static int32_t RAND_SEED;
1745 
1746 /**
1747  * Returns a uniform random value x, with 0.0 <= x < 1.0.  Use
1748  * with care: Does not return all possible values; returns one of
1749  * 714,025 values, uniformly spaced.  However, the period is
1750  * effectively infinite.  See: Numerical Recipes, section 7.1.
1751  *
1752  * @param seedp pointer to seed. Set *seedp to any negative value
1753  * to restart the sequence.
1754  */
random(int32_t * seedp)1755 float IntlTest::random(int32_t* seedp) {
1756     static int32_t iy, ir[98];
1757     static UBool first=TRUE;
1758     int32_t j;
1759     if (*seedp < 0 || first) {
1760         first = FALSE;
1761         if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1762         for (j=1;j<=97;++j) {
1763             *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1764             ir[j]=(*seedp);
1765         }
1766         *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1767         iy=(*seedp);
1768     }
1769     j=(int32_t)(1 + 97.0*iy/RAND_M);
1770     U_ASSERT(j>=1 && j<=97);
1771     iy=ir[j];
1772     *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1773     ir[j]=(*seedp);
1774     return (float) iy/RAND_M;
1775 }
1776 
1777 /**
1778  * Convenience method using a global seed.
1779  */
random()1780 float IntlTest::random() {
1781     return random(&RAND_SEED);
1782 }
1783 
toHex(int32_t i)1784 static inline UChar toHex(int32_t i) {
1785     return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1786 }
1787 
escape(const UnicodeString & s,UnicodeString & result)1788 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1789     for (int32_t i=0; i<s.length(); ++i) {
1790         UChar c = s[i];
1791         if (c <= (UChar)0x7F) {
1792             result += c;
1793         } else {
1794             result += (UChar)0x5c;
1795             result += (UChar)0x75;
1796             result += toHex((c >> 12) & 0xF);
1797             result += toHex((c >>  8) & 0xF);
1798             result += toHex((c >>  4) & 0xF);
1799             result += toHex( c        & 0xF);
1800         }
1801     }
1802     return result;
1803 }
1804 
1805 #define VERBOSE_ASSERTIONS
1806 
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1807 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1808     if (file != NULL) {
1809         if (!condition) {
1810             if (possibleDataError) {
1811                 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1812             } else {
1813                 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1814             }
1815         } else if (!quiet) {
1816             logln("%s:%d: Ok: %s", file, line, message);
1817         }
1818     } else {
1819         if (!condition) {
1820             if (possibleDataError) {
1821                 dataerrln("FAIL: assertTrue() failed: %s", message);
1822             } else {
1823                 errln("FAIL: assertTrue() failed: %s", message);
1824             }
1825         } else if (!quiet) {
1826             logln("Ok: %s", message);
1827         }
1828 
1829     }
1830     return condition;
1831 }
1832 
assertFalse(const char * message,UBool condition,UBool quiet)1833 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1834     if (condition) {
1835         errln("FAIL: assertFalse() failed: %s", message);
1836     } else if (!quiet) {
1837         logln("Ok: %s", message);
1838     }
1839     return !condition;
1840 }
1841 
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1842 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1843     if( file==NULL ) {
1844       file = ""; // prevent failure if no file given
1845     }
1846     if (U_FAILURE(ec)) {
1847         if (possibleDataError) {
1848           dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1849         } else {
1850           errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1851         }
1852         return FALSE;
1853     } else {
1854       logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1855     }
1856     return TRUE;
1857 }
1858 
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1859 UBool IntlTest::assertEquals(const char* message,
1860                              const UnicodeString& expected,
1861                              const UnicodeString& actual,
1862                              UBool possibleDataError) {
1863     if (expected != actual) {
1864         if (possibleDataError) {
1865             dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1866                   prettify(actual) +
1867                   "; expected " + prettify(expected));
1868         } else {
1869             errln((UnicodeString)"FAIL: " + message + "; got " +
1870                   prettify(actual) +
1871                   "; expected " + prettify(expected));
1872         }
1873         return FALSE;
1874     }
1875 #ifdef VERBOSE_ASSERTIONS
1876     else {
1877         logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1878     }
1879 #endif
1880     return TRUE;
1881 }
1882 
assertEquals(const char * message,const char * expected,const char * actual)1883 UBool IntlTest::assertEquals(const char* message,
1884                              const char* expected,
1885                              const char* actual) {
1886     if (uprv_strcmp(expected, actual) != 0) {
1887         errln((UnicodeString)"FAIL: " + message + "; got \"" +
1888               actual +
1889               "\"; expected \"" + expected + "\"");
1890         return FALSE;
1891     }
1892 #ifdef VERBOSE_ASSERTIONS
1893     else {
1894         logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1895     }
1896 #endif
1897     return TRUE;
1898 }
1899 
assertEquals(const char * message,int32_t expected,int32_t actual)1900 UBool IntlTest::assertEquals(const char* message,
1901                              int32_t expected,
1902                              int32_t actual) {
1903     if (expected != actual) {
1904         errln((UnicodeString)"FAIL: " + message + "; got " +
1905               actual + "=0x" + toHex(actual) +
1906               "; expected " + expected + "=0x" + toHex(expected));
1907         return FALSE;
1908     }
1909 #ifdef VERBOSE_ASSERTIONS
1910     else {
1911         logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual));
1912     }
1913 #endif
1914     return TRUE;
1915 }
1916 
assertEquals(const char * message,int64_t expected,int64_t actual)1917 UBool IntlTest::assertEquals(const char* message,
1918                              int64_t expected,
1919                              int64_t actual) {
1920     if (expected != actual) {
1921         errln((UnicodeString)"FAIL: " + message + "; got int64 " +
1922               Int64ToUnicodeString(actual) +
1923               "; expected " + Int64ToUnicodeString(expected) );
1924         return FALSE;
1925     }
1926 #ifdef VERBOSE_ASSERTIONS
1927     else {
1928       logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual));
1929     }
1930 #endif
1931     return TRUE;
1932 }
1933 
assertEquals(const char * message,double expected,double actual)1934 UBool IntlTest::assertEquals(const char* message,
1935                              double expected,
1936                              double actual) {
1937     if (expected != actual) {
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 
1951 
assertEquals(const char * message,UBool expected,UBool actual)1952 UBool IntlTest::assertEquals(const char* message,
1953                              UBool expected,
1954                              UBool actual) {
1955     if (expected != actual) {
1956         errln((UnicodeString)"FAIL: " + message + "; got " +
1957               toString(actual) +
1958               "; expected " + toString(expected));
1959         return FALSE;
1960     }
1961 #ifdef VERBOSE_ASSERTIONS
1962     else {
1963       logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1964     }
1965 #endif
1966     return TRUE;
1967 }
1968 
1969 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)1970 UBool IntlTest::assertEquals(const char* message,
1971                              const Formattable& expected,
1972                              const Formattable& actual,
1973                              UBool possibleDataError) {
1974     if (expected != actual) {
1975         if (possibleDataError) {
1976             dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1977                   toString(actual) +
1978                   "; expected " + toString(expected));
1979         } else {
1980             errln((UnicodeString)"FAIL: " + message + "; got " +
1981                   toString(actual) +
1982                   "; expected " + toString(expected));
1983         }
1984         return FALSE;
1985     }
1986 #ifdef VERBOSE_ASSERTIONS
1987     else {
1988         logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1989     }
1990 #endif
1991     return TRUE;
1992 }
1993 #endif
1994 
1995 static char ASSERT_BUF[256];
1996 
extractToAssertBuf(const UnicodeString & message)1997 static const char* extractToAssertBuf(const UnicodeString& message) {
1998     UnicodeString buf;
1999     escape(message, buf);
2000     buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
2001     ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
2002     return ASSERT_BUF;
2003 }
2004 
assertTrue(const UnicodeString & message,UBool condition,UBool quiet)2005 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
2006     return assertTrue(extractToAssertBuf(message), condition, quiet);
2007 }
2008 
assertFalse(const UnicodeString & message,UBool condition,UBool quiet)2009 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
2010     return assertFalse(extractToAssertBuf(message), condition, quiet);
2011 }
2012 
assertSuccess(const UnicodeString & message,UErrorCode ec)2013 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
2014     return assertSuccess(extractToAssertBuf(message), ec);
2015 }
2016 
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)2017 UBool IntlTest::assertEquals(const UnicodeString& message,
2018                              const UnicodeString& expected,
2019                              const UnicodeString& actual,
2020                              UBool possibleDataError) {
2021     return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
2022 }
2023 
assertEquals(const UnicodeString & message,const char * expected,const char * actual)2024 UBool IntlTest::assertEquals(const UnicodeString& message,
2025                              const char* expected,
2026                              const char* actual) {
2027     return assertEquals(extractToAssertBuf(message), expected, actual);
2028 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)2029 UBool IntlTest::assertEquals(const UnicodeString& message,
2030                              UBool expected,
2031                              UBool actual) {
2032     return assertEquals(extractToAssertBuf(message), expected, actual);
2033 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)2034 UBool IntlTest::assertEquals(const UnicodeString& message,
2035                              int32_t expected,
2036                              int32_t actual) {
2037     return assertEquals(extractToAssertBuf(message), expected, actual);
2038 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)2039 UBool IntlTest::assertEquals(const UnicodeString& message,
2040                              int64_t expected,
2041                              int64_t actual) {
2042     return assertEquals(extractToAssertBuf(message), expected, actual);
2043 }
2044 
2045 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)2046 UBool IntlTest::assertEquals(const UnicodeString& message,
2047                              const Formattable& expected,
2048                              const Formattable& actual) {
2049     return assertEquals(extractToAssertBuf(message), expected, actual);
2050 }
2051 #endif
2052 
setProperty(const char * propline)2053 void IntlTest::setProperty(const char* propline) {
2054     if (numProps < kMaxProps) {
2055         proplines[numProps] = propline;
2056     }
2057     numProps++;
2058 }
2059 
getProperty(const char * prop)2060 const char* IntlTest::getProperty(const char* prop) {
2061     const char* val = NULL;
2062     for (int32_t i = 0; i < numProps; i++) {
2063         int32_t plen = uprv_strlen(prop);
2064         if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
2065                 && proplines[i][plen] == '='
2066                 && uprv_strncmp(proplines[i], prop, plen) == 0) {
2067             val = &(proplines[i][plen+1]);
2068             break;
2069         }
2070     }
2071     return val;
2072 }
2073 
2074 /*
2075  * Hey, Emacs, please set the following:
2076  *
2077  * Local Variables:
2078  * indent-tabs-mode: nil
2079  * End:
2080  *
2081  */
2082