• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2007, 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_getUTCtime()
39 #include "unicode/locid.h"
40 
41 
42 #ifdef XP_MAC_CONSOLE
43 #include <console.h>
44 #include "Files.h"
45 #endif
46 
47 
48 static char* _testDataPath=NULL;
49 
50 // Static list of errors found
51 static UnicodeString errorList;
52 
53 //-----------------------------------------------------------------------------
54 //convenience classes to ease porting code that uses the Java
55 //string-concatenation operator (moved from findword test by rtg)
56 
57 // [LIU] Just to get things working
58 UnicodeString
UCharToUnicodeString(UChar c)59 UCharToUnicodeString(UChar c)
60 { return UnicodeString(c); }
61 
62 // [rtg] Just to get things working
63 UnicodeString
operator +(const UnicodeString & left,long num)64 operator+(const UnicodeString& left,
65       long num)
66 {
67     char buffer[64];    // nos changed from 10 to 64
68     char danger = 'p';  // guard against overrunning the buffer (rtg)
69 
70     sprintf(buffer, "%ld", num);
71     assert(danger == 'p');
72 
73     return left + buffer;
74 }
75 
76 UnicodeString
operator +(const UnicodeString & left,unsigned long num)77 operator+(const UnicodeString& left,
78       unsigned long num)
79 {
80     char buffer[64];    // nos changed from 10 to 64
81     char danger = 'p';  // guard against overrunning the buffer (rtg)
82 
83     sprintf(buffer, "%lu", num);
84     assert(danger == 'p');
85 
86     return left + buffer;
87 }
88 
89 UnicodeString
Int64ToUnicodeString(int64_t num)90 Int64ToUnicodeString(int64_t num)
91 {
92     char buffer[64];    // nos changed from 10 to 64
93     char danger = 'p';  // guard against overrunning the buffer (rtg)
94 
95 #ifdef U_WINDOWS
96     sprintf(buffer, "%I64d", num);
97 #else
98     sprintf(buffer, "%lld", (long long)num);
99 #endif
100     assert(danger == 'p');
101 
102     return buffer;
103 }
104 
105 // [LIU] Just to get things working
106 UnicodeString
operator +(const UnicodeString & left,double num)107 operator+(const UnicodeString& left,
108       double num)
109 {
110     char buffer[64];   // was 32, made it arbitrarily bigger (rtg)
111     char danger = 'p'; // guard against overrunning the buffer (rtg)
112 
113     // IEEE floating point has 52 bits of mantissa, plus one assumed bit
114     //  53*log(2)/log(10) = 15.95
115     // so there is no need to show more than 16 digits. [alan]
116 
117     sprintf(buffer, "%.17g", num);
118     assert(danger == 'p');
119 
120     return left + buffer;
121 }
122 
123 #if !UCONFIG_NO_FORMATTING
124 
125 /**
126  * Return a string display for for this, without surrounding braces.
127  */
_toString(const Formattable & f)128 UnicodeString _toString(const Formattable& f) {
129     UnicodeString s;
130     switch (f.getType()) {
131     case Formattable::kDate:
132         {
133             UErrorCode status = U_ZERO_ERROR;
134             SimpleDateFormat fmt(status);
135             if (U_SUCCESS(status)) {
136                 FieldPosition pos;
137                 fmt.format(f.getDate(), s, pos);
138                 s.insert(0, "Date:");
139             } else {
140                 s = UnicodeString("Error creating date format]");
141             }
142         }
143         break;
144     case Formattable::kDouble:
145         s = UnicodeString("double:") + f.getDouble();
146         break;
147     case Formattable::kLong:
148         s = UnicodeString("long:") + f.getLong();
149         break;
150 
151     case Formattable::kInt64:
152         s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64());
153         break;
154 
155     case Formattable::kString:
156         f.getString(s);
157         s.insert(0, "String:");
158         break;
159     case Formattable::kArray:
160         {
161             int32_t i, n;
162             const Formattable* array = f.getArray(n);
163             s.insert(0, UnicodeString("Array:"));
164             UnicodeString delim(", ");
165             for (i=0; i<n; ++i) {
166                 if (i > 0) {
167                     s.append(delim);
168                 }
169                 s = s + _toString(array[i]);
170             }
171         }
172         break;
173     case Formattable::kObject:
174         if (f.getObject()->getDynamicClassID() ==
175             CurrencyAmount::getStaticClassID()) {
176             const CurrencyAmount& c = (const CurrencyAmount&) *f.getObject();
177             s = _toString(c.getNumber()) + " " + UnicodeString(c.getISOCurrency());
178         } else {
179             s = UnicodeString("Unknown UObject");
180         }
181         break;
182     default:
183         s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType();
184         break;
185     }
186     return s;
187 }
188 
189 /**
190  * Originally coded this as operator+, but that makes the expression
191  * + char* ambiguous. - liu
192  */
toString(const Formattable & f)193 UnicodeString toString(const Formattable& f) {
194     UnicodeString s((UChar)91/*[*/);
195     s.append(_toString(f));
196     s.append((UChar)0x5d/*]*/);
197     return s;
198 }
199 
200 #endif
201 
202 // useful when operator+ won't cooperate
toString(int32_t n)203 UnicodeString toString(int32_t n) {
204     return UnicodeString() + (long)n;
205 }
206 
207 // stephen - cleaned up 05/05/99
operator +(const UnicodeString & left,char num)208 UnicodeString operator+(const UnicodeString& left, char num)
209 { return left + (long)num; }
operator +(const UnicodeString & left,short num)210 UnicodeString operator+(const UnicodeString& left, short num)
211 { return left + (long)num; }
operator +(const UnicodeString & left,int num)212 UnicodeString operator+(const UnicodeString& left, int num)
213 { return left + (long)num; }
operator +(const UnicodeString & left,unsigned char num)214 UnicodeString operator+(const UnicodeString& left, unsigned char num)
215 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned short num)216 UnicodeString operator+(const UnicodeString& left, unsigned short num)
217 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned int num)218 UnicodeString operator+(const UnicodeString& left, unsigned int num)
219 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,float num)220 UnicodeString operator+(const UnicodeString& left, float num)
221 { return left + (double)num; }
222 
223 //------------------
224 
225 // Append a hex string to the target
226 UnicodeString&
appendHex(uint32_t number,int32_t digits,UnicodeString & target)227 IntlTest::appendHex(uint32_t number,
228             int32_t digits,
229             UnicodeString& target)
230 {
231     static const UChar digitString[] = {
232         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
233         0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
234     }; /* "0123456789ABCDEF" */
235 
236     switch (digits)
237     {
238     case 8:
239         target += digitString[(number >> 28) & 0xF];
240     case 7:
241         target += digitString[(number >> 24) & 0xF];
242     case 6:
243         target += digitString[(number >> 20) & 0xF];
244     case 5:
245         target += digitString[(number >> 16) & 0xF];
246     case 4:
247         target += digitString[(number >> 12) & 0xF];
248     case 3:
249         target += digitString[(number >>  8) & 0xF];
250     case 2:
251         target += digitString[(number >>  4) & 0xF];
252     case 1:
253         target += digitString[(number >>  0) & 0xF];
254         break;
255     default:
256         target += "**";
257     }
258     return target;
259 }
260 
261 // Replace nonprintable characters with unicode escapes
262 UnicodeString&
prettify(const UnicodeString & source,UnicodeString & target)263 IntlTest::prettify(const UnicodeString &source,
264            UnicodeString &target)
265 {
266     int32_t i;
267 
268     target.remove();
269     target += "\"";
270 
271     for (i = 0; i < source.length(); )
272     {
273         UChar32 ch = source.char32At(i);
274         i += UTF_CHAR_LENGTH(ch);
275 
276         if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
277         {
278             if (ch <= 0xFFFF) {
279                 target += "\\u";
280                 appendHex(ch, 4, target);
281             } else {
282                 target += "\\U";
283                 appendHex(ch, 8, target);
284             }
285         }
286         else
287         {
288             target += ch;
289         }
290     }
291 
292     target += "\"";
293 
294     return target;
295 }
296 
297 // Replace nonprintable characters with unicode escapes
298 UnicodeString
prettify(const UnicodeString & source,UBool parseBackslash)299 IntlTest::prettify(const UnicodeString &source, UBool parseBackslash)
300 {
301     int32_t i;
302     UnicodeString target;
303     target.remove();
304     target += "\"";
305 
306     for (i = 0; i < source.length();)
307     {
308         UChar32 ch = source.char32At(i);
309         i += UTF_CHAR_LENGTH(ch);
310 
311         if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
312         {
313             if (parseBackslash) {
314                 // If we are preceded by an odd number of backslashes,
315                 // then this character has already been backslash escaped.
316                 // Delete a backslash.
317                 int32_t backslashCount = 0;
318                 for (int32_t j=target.length()-1; j>=0; --j) {
319                     if (target.charAt(j) == (UChar)92) {
320                         ++backslashCount;
321                     } else {
322                         break;
323                     }
324                 }
325                 if ((backslashCount % 2) == 1) {
326                     target.truncate(target.length() - 1);
327                 }
328             }
329             if (ch <= 0xFFFF) {
330                 target += "\\u";
331                 appendHex(ch, 4, target);
332             } else {
333                 target += "\\U";
334                 appendHex(ch, 8, target);
335             }
336         }
337         else
338         {
339             target += ch;
340         }
341     }
342 
343     target += "\"";
344 
345     return target;
346 }
347 
348 /*  IntlTest::setICU_DATA  - if the ICU_DATA environment variable is not already
349  *                       set, try to deduce the directory in which ICU was built,
350  *                       and set ICU_DATA to "icu/source/data" in that location.
351  *                       The intent is to allow the tests to have a good chance
352  *                       of running without requiring that the user manually set
353  *                       ICU_DATA.  Common data isn't a problem, since it is
354  *                       picked up via a static (build time) reference, but the
355  *                       tests dynamically load some data.
356  */
setICU_DATA()357 void IntlTest::setICU_DATA() {
358     const char *original_ICU_DATA = getenv("ICU_DATA");
359 
360     if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) {
361         /*  If the user set ICU_DATA, don't second-guess the person. */
362         return;
363     }
364 
365     // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
366     //              to point to the top of the build hierarchy, which may or
367     //              may not be the same as the source directory, depending on
368     //              the configure options used.  At any rate,
369     //              set the data path to the built data from this directory.
370     //              The value is complete with quotes, so it can be used
371     //              as-is as a string constant.
372 
373 #if defined (U_TOPBUILDDIR)
374     {
375         static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
376         u_setDataDirectory(env_string);
377         return;
378     }
379 
380 #else
381     // Use #else so we don't get compiler warnings due to the return above.
382 
383     /* On Windows, the file name obtained from __FILE__ includes a full path.
384      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
385      *             Change to    "wherever\icu\source\data"
386      */
387     {
388         char p[sizeof(__FILE__) + 10];
389         char *pBackSlash;
390         int i;
391 
392         strcpy(p, __FILE__);
393         /* We want to back over three '\' chars.                            */
394         /*   Only Windows should end up here, so looking for '\' is safe.   */
395         for (i=1; i<=3; i++) {
396             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
397             if (pBackSlash != NULL) {
398                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
399             }
400         }
401 
402         if (pBackSlash != NULL) {
403             /* We found and truncated three names from the path.
404              *  Now append "source\data" and set the environment
405              */
406             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
407             u_setDataDirectory(p);     /*  p is "ICU_DATA=wherever\icu\source\data"    */
408             return;
409         }
410         else {
411             /* __FILE__ on MSVC7 does not contain the directory */
412             u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
413             return;
414         }
415     }
416 #endif
417 
418     /* No location for the data dir was identifiable.
419      *   Add other fallbacks for the test data location here if the need arises
420      */
421 }
422 
423 
424 //--------------------------------------------------------------------------------------
425 
426 static const int32_t indentLevel_offset = 3;
427 static const char delim = '/';
428 
429 IntlTest* IntlTest::gTest = NULL;
430 
431 static int32_t execCount = 0;
432 
it_log(UnicodeString message)433 void it_log( UnicodeString message )
434 {
435     if (IntlTest::gTest)
436         IntlTest::gTest->log( message );
437 }
438 
it_logln(UnicodeString message)439 void it_logln( UnicodeString message )
440 {
441     if (IntlTest::gTest)
442         IntlTest::gTest->logln( message );
443 }
444 
it_logln(void)445 void it_logln( void )
446 {
447     if (IntlTest::gTest)
448         IntlTest::gTest->logln();
449 }
450 
it_info(UnicodeString message)451 void it_info( UnicodeString message )
452 {
453     if (IntlTest::gTest)
454         IntlTest::gTest->info( message );
455 }
456 
it_infoln(UnicodeString message)457 void it_infoln( UnicodeString message )
458 {
459     if (IntlTest::gTest)
460         IntlTest::gTest->infoln( message );
461 }
462 
it_infoln(void)463 void it_infoln( void )
464 {
465     if (IntlTest::gTest)
466         IntlTest::gTest->infoln();
467 }
468 
it_err()469 void it_err()
470 {
471     if (IntlTest::gTest)
472         IntlTest::gTest->err();
473 }
474 
it_err(UnicodeString message)475 void it_err( UnicodeString message )
476 {
477     if (IntlTest::gTest)
478         IntlTest::gTest->err( message );
479 }
480 
it_errln(UnicodeString message)481 void it_errln( UnicodeString message )
482 {
483     if (IntlTest::gTest)
484         IntlTest::gTest->errln( message );
485 }
486 
it_dataerr(UnicodeString message)487 void it_dataerr( UnicodeString message )
488 {
489     if (IntlTest::gTest)
490         IntlTest::gTest->dataerr( message );
491 }
492 
it_dataerrln(UnicodeString message)493 void it_dataerrln( UnicodeString message )
494 {
495     if (IntlTest::gTest)
496         IntlTest::gTest->dataerrln( message );
497 }
498 
IntlTest()499 IntlTest::IntlTest()
500 {
501     caller = NULL;
502     testPath = NULL;
503     LL_linestart = TRUE;
504     errorCount = 0;
505     dataErrorCount = 0;
506     verbose = FALSE;
507     no_err_msg = FALSE;
508     warn_on_missing_data = FALSE;
509     quick = FALSE;
510     leaks = FALSE;
511     testoutfp = stdout;
512     LL_indentlevel = indentLevel_offset;
513 }
514 
setCaller(IntlTest * callingTest)515 void IntlTest::setCaller( IntlTest* callingTest )
516 {
517     caller = callingTest;
518     if (caller) {
519         verbose = caller->verbose;
520         no_err_msg = caller->no_err_msg;
521         quick = caller->quick;
522         testoutfp = caller->testoutfp;
523         LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
524     }
525 }
526 
callTest(IntlTest & testToBeCalled,char * par)527 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
528 {
529     execCount--; // correct a previously assumed test-exec, as this only calls a subtest
530     testToBeCalled.setCaller( this );
531     return testToBeCalled.runTest( testPath, par );
532 }
533 
setPath(char * pathVal)534 void IntlTest::setPath( char* pathVal )
535 {
536     this->testPath = pathVal;
537 }
538 
setVerbose(UBool verboseVal)539 UBool IntlTest::setVerbose( UBool verboseVal )
540 {
541     UBool rval = this->verbose;
542     this->verbose = verboseVal;
543     return rval;
544 }
545 
setWarnOnMissingData(UBool warn_on_missing_dataVal)546 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
547 {
548     UBool rval = this->warn_on_missing_data;
549     this->warn_on_missing_data = warn_on_missing_dataVal;
550     return rval;
551 }
552 
setNoErrMsg(UBool no_err_msgVal)553 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
554 {
555     UBool rval = this->no_err_msg;
556     this->no_err_msg = no_err_msgVal;
557     return rval;
558 }
559 
setQuick(UBool quickVal)560 UBool IntlTest::setQuick( UBool quickVal )
561 {
562     UBool rval = this->quick;
563     this->quick = quickVal;
564     return rval;
565 }
566 
setLeaks(UBool leaksVal)567 UBool IntlTest::setLeaks( UBool leaksVal )
568 {
569     UBool rval = this->leaks;
570     this->leaks = leaksVal;
571     return rval;
572 }
573 
getErrors(void)574 int32_t IntlTest::getErrors( void )
575 {
576     return errorCount;
577 }
578 
getDataErrors(void)579 int32_t IntlTest::getDataErrors( void )
580 {
581     return dataErrorCount;
582 }
583 
runTest(char * name,char * par)584 UBool IntlTest::runTest( char* name, char* par )
585 {
586     UBool rval;
587     char* pos = NULL;
588 
589     if (name)
590         pos = strchr( name, delim ); // check if name contains path (by looking for '/')
591     if (pos) {
592         testPath = pos+1;   // store subpath for calling subtest
593         *pos = 0;       // split into two strings
594     }else{
595         testPath = NULL;
596     }
597 
598     if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
599         rval = runTestLoop( NULL, par );
600 
601     }else if (strcmp( name, "LIST" ) == 0) {
602         this->usage();
603         rval = TRUE;
604 
605     }else{
606         rval = runTestLoop( name, par );
607     }
608 
609     if (pos)
610         *pos = delim;  // restore original value at pos
611     return rval;
612 }
613 
614 // call individual tests, to be overriden to call implementations
runIndexedTest(int32_t index,UBool exec,const char * & name,char * par)615 void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
616 {
617     // to be overriden by a method like:
618     /*
619     switch (index) {
620         case 0: name = "First Test"; if (exec) FirstTest( par ); break;
621         case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
622         default: name = ""; break;
623     }
624     */
625     this->errln("*** runIndexedTest needs to be overriden! ***");
626     name = ""; exec = exec; index = index; par = par;
627 }
628 
629 
runTestLoop(char * testname,char * par)630 UBool IntlTest::runTestLoop( char* testname, char* par )
631 {
632     int32_t    index = 0;
633     const char*   name;
634     UBool  run_this_test;
635     int32_t    lastErrorCount;
636     UBool  rval = FALSE;
637     UBool   lastTestFailed;
638 
639     IntlTest* saveTest = gTest;
640     gTest = this;
641     do {
642         this->runIndexedTest( index, FALSE, name, par );
643         if (!name || (name[0] == 0))
644             break;
645         if (!testname) {
646             run_this_test = TRUE;
647         }else{
648             run_this_test = (UBool) (strcmp( name, testname ) == 0);
649         }
650         if (run_this_test) {
651             lastErrorCount = errorCount;
652             execCount++;
653             this->runIndexedTest( index, TRUE, name, par );
654             rval = TRUE; // at least one test has been called
655             char msg[256];
656             if (lastErrorCount == errorCount) {
657                 sprintf( msg, "---OK:   %s", name );
658                 lastTestFailed = FALSE;
659             }else{
660                 sprintf(msg, "---ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
661 
662                 for(int i=0;i<LL_indentlevel;i++) {
663                     errorList += " ";
664                 }
665                 errorList += name;
666                 errorList += "\n";
667                 lastTestFailed = TRUE;
668             }
669             LL_indentlevel -= 3;
670             if (lastTestFailed) {
671                 LL_message( "", TRUE);
672             }
673             LL_message( msg, TRUE);
674             if (lastTestFailed) {
675                 LL_message( "", TRUE);
676             }
677             LL_indentlevel += 3;
678         }
679         index++;
680     }while(name);
681 
682     gTest = saveTest;
683     return rval;
684 }
685 
686 
687 /**
688 * Adds given string to the log if we are in verbose mode.
689 */
log(const UnicodeString & message)690 void IntlTest::log( const UnicodeString &message )
691 {
692     if( verbose ) {
693         LL_message( message, FALSE );
694     }
695 }
696 
697 /**
698 * Adds given string to the log if we are in verbose mode. Adds a new line to
699 * the given message.
700 */
logln(const UnicodeString & message)701 void IntlTest::logln( const UnicodeString &message )
702 {
703     if( verbose ) {
704         LL_message( message, TRUE );
705     }
706 }
707 
logln(void)708 void IntlTest::logln( void )
709 {
710     if( verbose ) {
711         LL_message( "", TRUE );
712     }
713 }
714 
715 /**
716 * Unconditionally adds given string to the log.
717 */
info(const UnicodeString & message)718 void IntlTest::info( const UnicodeString &message )
719 {
720   LL_message( message, FALSE );
721 }
722 
723 /**
724 * Unconditionally adds given string to the log. Adds a new line to
725 * the given message.
726 */
infoln(const UnicodeString & message)727 void IntlTest::infoln( const UnicodeString &message )
728 {
729   LL_message( message, TRUE );
730 }
731 
infoln(void)732 void IntlTest::infoln( void )
733 {
734   LL_message( "", TRUE );
735 }
736 
IncErrorCount(void)737 int32_t IntlTest::IncErrorCount( void )
738 {
739     errorCount++;
740     if (caller) caller->IncErrorCount();
741     return errorCount;
742 }
743 
IncDataErrorCount(void)744 int32_t IntlTest::IncDataErrorCount( void )
745 {
746     dataErrorCount++;
747     if (caller) caller->IncDataErrorCount();
748     return dataErrorCount;
749 }
750 
err()751 void IntlTest::err()
752 {
753     IncErrorCount();
754 }
755 
err(const UnicodeString & message)756 void IntlTest::err( const UnicodeString &message )
757 {
758     IncErrorCount();
759     if (!no_err_msg) LL_message( message, FALSE );
760 }
761 
errln(const UnicodeString & message)762 void IntlTest::errln( const UnicodeString &message )
763 {
764     IncErrorCount();
765     if (!no_err_msg) LL_message( message, TRUE );
766 }
767 
dataerr(const UnicodeString & message)768 void IntlTest::dataerr( const UnicodeString &message )
769 {
770     IncDataErrorCount();
771 
772     if (!warn_on_missing_data) {
773         IncErrorCount();
774     }
775 
776     if (!no_err_msg) LL_message( message, FALSE );
777 }
778 
dataerrln(const UnicodeString & message)779 void IntlTest::dataerrln( const UnicodeString &message )
780 {
781     IncDataErrorCount();
782 
783     if (!warn_on_missing_data) {
784         IncErrorCount();
785     }
786 
787     if (!no_err_msg) LL_message( message, TRUE );
788 }
789 
790 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)791 void IntlTest::log(const char *fmt, ...)
792 {
793     char buffer[4000];
794     va_list ap;
795 
796     va_start(ap, fmt);
797     /* sprintf it just to make sure that the information is valid */
798     vsprintf(buffer, fmt, ap);
799     va_end(ap);
800     if( verbose ) {
801         log(UnicodeString(buffer, ""));
802     }
803 }
804 
logln(const char * fmt,...)805 void IntlTest::logln(const char *fmt, ...)
806 {
807     char buffer[4000];
808     va_list ap;
809 
810     va_start(ap, fmt);
811     /* sprintf it just to make sure that the information is valid */
812     vsprintf(buffer, fmt, ap);
813     va_end(ap);
814     if( verbose ) {
815         logln(UnicodeString(buffer, ""));
816     }
817 }
818 
819 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)820 void IntlTest::info(const char *fmt, ...)
821 {
822     char buffer[4000];
823     va_list ap;
824 
825     va_start(ap, fmt);
826     /* sprintf it just to make sure that the information is valid */
827     vsprintf(buffer, fmt, ap);
828     va_end(ap);
829     info(UnicodeString(buffer, ""));
830 }
831 
infoln(const char * fmt,...)832 void IntlTest::infoln(const char *fmt, ...)
833 {
834     char buffer[4000];
835     va_list ap;
836 
837     va_start(ap, fmt);
838     /* sprintf it just to make sure that the information is valid */
839     vsprintf(buffer, fmt, ap);
840     va_end(ap);
841     infoln(UnicodeString(buffer, ""));
842 }
843 
err(const char * fmt,...)844 void IntlTest::err(const char *fmt, ...)
845 {
846     char buffer[4000];
847     va_list ap;
848 
849     va_start(ap, fmt);
850     vsprintf(buffer, fmt, ap);
851     va_end(ap);
852     err(UnicodeString(buffer, ""));
853 }
854 
errln(const char * fmt,...)855 void IntlTest::errln(const char *fmt, ...)
856 {
857     char buffer[4000];
858     va_list ap;
859 
860     va_start(ap, fmt);
861     vsprintf(buffer, fmt, ap);
862     va_end(ap);
863     errln(UnicodeString(buffer, ""));
864 }
865 
dataerrln(const char * fmt,...)866 void IntlTest::dataerrln(const char *fmt, ...)
867 {
868     char buffer[4000];
869     va_list ap;
870 
871     va_start(ap, fmt);
872     vsprintf(buffer, fmt, ap);
873     va_end(ap);
874     dataerrln(UnicodeString(buffer, ""));
875 }
876 
printErrors()877 void IntlTest::printErrors()
878 {
879      IntlTest::LL_message(errorList, TRUE);
880 }
881 
LL_message(UnicodeString message,UBool newline)882 void IntlTest::LL_message( UnicodeString message, UBool newline )
883 {
884     // string that starts with a LineFeed character and continues
885     // with spaces according to the current indentation
886     static const UChar indentUChars[] = {
887         '\n',
888         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
889         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
890         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
891         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
892         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
893         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
894         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
895         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
896         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
897         32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
898     };
899     UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
900 
901     char buffer[10000];
902     int32_t length;
903 
904     // stream out the indentation string first if necessary
905     length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
906     if (length > 0) {
907         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
908     }
909 
910     // replace each LineFeed by the indentation string
911     message.findAndReplace(UnicodeString((UChar)'\n'), indent);
912 
913     // stream out the message
914     length = message.extract(0, message.length(), buffer, sizeof(buffer));
915     if (length > 0) {
916         length = length > 10000 ? 10000 : length;
917         fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
918     }
919 
920     if (newline) {
921         char newLine = '\n';
922         fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
923     }
924 
925     // A newline usually flushes the buffer, but
926     // flush the message just in case of a core dump.
927     fflush((FILE *)testoutfp);
928 }
929 
930 /**
931 * Print a usage message for this test class.
932 */
usage(void)933 void IntlTest::usage( void )
934 {
935     UBool save_verbose = setVerbose( TRUE );
936     logln("Test names:");
937     logln("-----------");
938 
939     int32_t index = 0;
940     const char* name = NULL;
941     do{
942         this->runIndexedTest( index, FALSE, name );
943         if (!name) break;
944         logln(name);
945         index++;
946     }while (name && (name[0] != 0));
947     setVerbose( save_verbose );
948 }
949 
950 
951 // memory leak reporting software will be able to take advantage of the testsuite
952 // being run a second time local to a specific method in order to report only actual leaks
953 UBool
run_phase2(char * name,char * par)954 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
955 {
956     UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
957     strLeak->append(" for verifying purify filter");
958     return this->runTest( name, par );
959 }
960 
961 
962 #if UCONFIG_NO_LEGACY_CONVERSION
963 #   define TRY_CNV_1 "iso-8859-1"
964 #   define TRY_CNV_2 "ibm-1208"
965 #else
966 #   define TRY_CNV_1 "iso-8859-7"
967 #   define TRY_CNV_2 "sjis"
968 #endif
969 
970 int
main(int argc,char * argv[])971 main(int argc, char* argv[])
972 {
973     UBool syntax = FALSE;
974     UBool all = FALSE;
975     UBool verbose = FALSE;
976     UBool no_err_msg = FALSE;
977     UBool quick = TRUE;
978     UBool name = FALSE;
979     UBool leaks = FALSE;
980     UBool warnOnMissingData = FALSE;
981     UBool defaultDataFound = FALSE;
982     UErrorCode errorCode = U_ZERO_ERROR;
983     UConverter *cnv = NULL;
984     const char *warnOrErr = "Failure";
985     UDate startTime, endTime;
986     int32_t diffTime;
987 
988     U_MAIN_INIT_ARGS(argc, argv);
989 
990     startTime = uprv_getUTCtime();
991 
992     for (int i = 1; i < argc; ++i) {
993         if (argv[i][0] == '-') {
994             const char* str = argv[i] + 1;
995             if (strcmp("verbose", str) == 0 ||
996                 strcmp("v", str) == 0)
997                 verbose = TRUE;
998             else if (strcmp("noerrormsg", str) == 0 ||
999                      strcmp("n", str) == 0)
1000                 no_err_msg = TRUE;
1001             else if (strcmp("exhaustive", str) == 0 ||
1002                      strcmp("e", str) == 0)
1003                 quick = FALSE;
1004             else if (strcmp("all", str) == 0 ||
1005                      strcmp("a", str) == 0)
1006                 all = TRUE;
1007             else if (strcmp("leaks", str) == 0 ||
1008                      strcmp("l", str) == 0)
1009                 leaks = TRUE;
1010             else if (strcmp("w", str) == 0) {
1011               warnOnMissingData = TRUE;
1012               warnOrErr = "WARNING";
1013             }
1014             else {
1015                 syntax = TRUE;
1016             }
1017         }else{
1018             name = TRUE;
1019         }
1020     }
1021 
1022     if (!all && !name) {
1023         all = TRUE;
1024     } else if (all && name) {
1025         syntax = TRUE;
1026     }
1027 
1028     if (syntax) {
1029         fprintf(stdout,
1030                 "### Syntax:\n"
1031                 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1032                 "### where options are: verbose (v), all (a), noerrormsg (n), \n"
1033                 "### exhaustive (e), leaks (l)"
1034                 "### (Specify either -all (shortcut -a) or a test name). \n"
1035                 "### -all will run all of the tests.\n"
1036                 "### \n"
1037                 "### To get a list of the test names type: intltest LIST \n"
1038                 "### To run just the utility tests type: intltest utility \n"
1039                 "### \n"
1040                 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1041                 "### For example to list the utility tests type: intltest utility/LIST \n"
1042                 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1043                 "### \n"
1044                 "### A parameter can be specified for a test by appending '@' and the value \n"
1045                 "### to the testname. \n\n");
1046         return 1;
1047     }
1048 
1049     UBool all_tests_exist = TRUE;
1050     MajorTestLevel major;
1051     major.setVerbose( verbose );
1052     major.setNoErrMsg( no_err_msg );
1053     major.setQuick( quick );
1054     major.setLeaks( leaks );
1055     major.setWarnOnMissingData( warnOnMissingData );
1056     fprintf(stdout, "-----------------------------------------------\n");
1057     fprintf(stdout, " IntlTest (C++) Test Suite for                 \n");
1058     fprintf(stdout, "   International Components for Unicode %s\n", U_ICU_VERSION);
1059     fprintf(stdout, "-----------------------------------------------\n");
1060     fprintf(stdout, " Options:                                       \n");
1061     fprintf(stdout, "   all (a)                  : %s\n", (all?               "On" : "Off"));
1062     fprintf(stdout, "   Verbose (v)              : %s\n", (verbose?           "On" : "Off"));
1063     fprintf(stdout, "   No error messages (n)    : %s\n", (no_err_msg?        "On" : "Off"));
1064     fprintf(stdout, "   Exhaustive (e)           : %s\n", (!quick?            "On" : "Off"));
1065     fprintf(stdout, "   Leaks (l)                : %s\n", (leaks?             "On" : "Off"));
1066     fprintf(stdout, "   Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1067     fprintf(stdout, "-----------------------------------------------\n");
1068 
1069     /* Check whether ICU will initialize without forcing the build data directory into
1070      *  the ICU_DATA path.  Success here means either the data dll contains data, or that
1071      *  this test program was run with ICU_DATA set externally.  Failure of this check
1072      *  is normal when ICU data is not packaged into a shared library.
1073      *
1074      *  Whether or not this test succeeds, we want to cleanup and reinitialize
1075      *  with a data path so that data loading from individual files can be tested.
1076      */
1077     u_init(&errorCode);
1078     if (U_FAILURE(errorCode)) {
1079         fprintf(stderr,
1080             "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
1081         defaultDataFound = FALSE;
1082     }
1083     else {
1084         defaultDataFound = TRUE;
1085     }
1086     u_cleanup();
1087     errorCode = U_ZERO_ERROR;
1088 
1089     /* Initialize ICU */
1090     if (!defaultDataFound) {
1091         IntlTest::setICU_DATA();   // Must set data directory before u_init() is called.
1092     }
1093     u_init(&errorCode);
1094     if (U_FAILURE(errorCode)) {
1095         fprintf(stderr,
1096             "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1097             "*** Check the ICU_DATA environment variable and \n"
1098             "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1099             if(warnOnMissingData == 0) {
1100                 fprintf(stderr, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1101                 u_cleanup();
1102                 return 1;
1103             }
1104     }
1105 
1106 
1107     // initial check for the default converter
1108     errorCode = U_ZERO_ERROR;
1109     cnv = ucnv_open(0, &errorCode);
1110     if(cnv != 0) {
1111         // ok
1112         ucnv_close(cnv);
1113     } else {
1114         fprintf(stdout,
1115                 "*** %s! The default converter [%s] cannot be opened.\n"
1116                 "*** Check the ICU_DATA environment variable and\n"
1117                 "*** check that the data files are present.\n",
1118                 warnOrErr, ucnv_getDefaultName());
1119         if(!warnOnMissingData) {
1120           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1121           return 1;
1122         }
1123     }
1124 
1125     // try more data
1126     cnv = ucnv_open(TRY_CNV_2, &errorCode);
1127     if(cnv != 0) {
1128         // ok
1129         ucnv_close(cnv);
1130     } else {
1131         fprintf(stdout,
1132                 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1133                 "*** Check the ICU_DATA environment variable and \n"
1134                 "*** check that the data files are present.\n", warnOrErr);
1135         if(!warnOnMissingData) {
1136           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1137           return 1;
1138         }
1139     }
1140 
1141     UResourceBundle *rb = ures_open(0, "en", &errorCode);
1142     ures_close(rb);
1143     if(U_FAILURE(errorCode)) {
1144         fprintf(stdout,
1145                 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1146                 "*** Check the ICU_DATA environment variable and \n"
1147                 "*** check that the data files are present.\n", warnOrErr);
1148         if(!warnOnMissingData) {
1149           fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1150           return 1;
1151         }
1152     }
1153 
1154     Locale originalLocale;  // Save the default locale for comparison later on.
1155 
1156     /* TODO: Add option to call u_cleanup and rerun tests. */
1157     if (all) {
1158         major.runTest();
1159         if (leaks) {
1160             major.run_phase2( NULL, NULL );
1161         }
1162     }else{
1163         for (int i = 1; i < argc; ++i) {
1164             if (argv[i][0] != '-') {
1165                 char* name = argv[i];
1166                 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1167                 char* parameter = strchr( name, '@' );
1168                 if (parameter) {
1169                     *parameter = 0;
1170                     parameter += 1;
1171                 }
1172                 execCount = 0;
1173                 UBool res = major.runTest( name, parameter );
1174                 if (leaks && res) {
1175                     major.run_phase2( name, parameter );
1176                 }
1177                 if (!res || (execCount <= 0)) {
1178                     fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1179                     all_tests_exist = FALSE;
1180                 }
1181             }
1182         }
1183     }
1184 
1185 #if !UCONFIG_NO_FORMATTING
1186     CalendarTimeZoneTest::cleanup();
1187 #endif
1188 
1189     free(_testDataPath);
1190     _testDataPath = 0;
1191 
1192     Locale lastDefaultLocale;
1193     if (originalLocale != lastDefaultLocale) {
1194         major.errln("FAILURE: A test changed the default locale without resetting it.");
1195     }
1196 
1197     fprintf(stdout, "\n--------------------------------------\n");
1198     if (major.getErrors() == 0) {
1199         /* Call it twice to make sure that the defaults were reset. */
1200         /* Call it before the OK message to verify proper cleanup. */
1201         u_cleanup();
1202         u_cleanup();
1203 
1204         fprintf(stdout, "OK: All tests passed without error.\n");
1205 
1206         if (major.getDataErrors() != 0) {
1207             fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1208         }
1209     }else{
1210         fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1211         major.printErrors();
1212 
1213 
1214         if (major.getDataErrors() != 0) {
1215             fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1216                     "\tstock ICU data (i.e some have been added or removed), consider using\n"
1217                     "\tthe '-w' option to turn these errors into warnings.\n");
1218         }
1219 
1220         /* Call afterwards to display errors. */
1221         u_cleanup();
1222     }
1223 
1224     fprintf(stdout, "--------------------------------------\n");
1225 
1226     if (execCount <= 0) {
1227         fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1228     }
1229     endTime = uprv_getUTCtime();
1230     diffTime = (int32_t)(endTime - startTime);
1231     printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1232         (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1233         (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1234         (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1235         (int)(diffTime%U_MILLIS_PER_SECOND));
1236     return major.getErrors();
1237 }
1238 
loadTestData(UErrorCode & err)1239 const char* IntlTest::loadTestData(UErrorCode& err){
1240     if( _testDataPath == NULL){
1241         const char*      directory=NULL;
1242         UResourceBundle* test =NULL;
1243         char* tdpath=NULL;
1244         const char* tdrelativepath;
1245 
1246 #if defined (U_TOPBUILDDIR)
1247         tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1248         directory = U_TOPBUILDDIR;
1249 #else
1250         tdrelativepath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1251         directory = pathToDataDirectory();
1252 #endif
1253 
1254         tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1255 
1256 
1257         /* u_getDataDirectory shoul return \source\data ... set the
1258          * directory to ..\source\data\..\test\testdata\out\testdata
1259          */
1260         strcpy(tdpath, directory);
1261         strcat(tdpath, tdrelativepath);
1262         strcat(tdpath,"testdata");
1263 
1264         test=ures_open(tdpath, "testtypes", &err);
1265 
1266         if(U_FAILURE(err)){
1267             err = U_FILE_ACCESS_ERROR;
1268             it_errln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1269             return "";
1270         }
1271         ures_close(test);
1272         _testDataPath = tdpath;
1273         return _testDataPath;
1274     }
1275     return _testDataPath;
1276 }
1277 
getTestDataPath(UErrorCode & err)1278 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1279     return loadTestData(err);
1280 }
1281 
1282 /* Returns the path to icu/source/test/testdata/ */
getSourceTestData(UErrorCode &)1283 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1284     const char *srcDataDir = NULL;
1285 #ifdef U_TOPSRCDIR
1286     srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1287 #else
1288     srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1289     FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
1290     if (f) {
1291         /* We're in icu/source/test/intltest/ */
1292         fclose(f);
1293     }
1294     else {
1295         /* We're in icu/source/test/intltest/(Debug|Release) */
1296         srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1297     }
1298 #endif
1299     return srcDataDir;
1300 }
1301 
1302 const char* IntlTest::fgDataDir = NULL;
1303 
1304 /* returns the path to icu/source/data */
pathToDataDirectory()1305 const char *  IntlTest::pathToDataDirectory()
1306 {
1307 
1308     if(fgDataDir != NULL) {
1309         return fgDataDir;
1310     }
1311 
1312     /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1313     //              to point to the top of the build hierarchy, which may or
1314     //              may not be the same as the source directory, depending on
1315     //              the configure options used.  At any rate,
1316     //              set the data path to the built data from this directory.
1317     //              The value is complete with quotes, so it can be used
1318     //              as-is as a string constant.
1319     */
1320 #if defined (U_TOPSRCDIR)
1321     {
1322         fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1323     }
1324 #else
1325 
1326     /* On Windows, the file name obtained from __FILE__ includes a full path.
1327      *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
1328      *             Change to    "wherever\icu\source\data"
1329      */
1330     {
1331         static char p[sizeof(__FILE__) + 10];
1332         char *pBackSlash;
1333         int i;
1334 
1335         strcpy(p, __FILE__);
1336         /* We want to back over three '\' chars.                            */
1337         /*   Only Windows should end up here, so looking for '\' is safe.   */
1338         for (i=1; i<=3; i++) {
1339             pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1340             if (pBackSlash != NULL) {
1341                 *pBackSlash = 0;        /* Truncate the string at the '\'   */
1342             }
1343         }
1344 
1345         if (pBackSlash != NULL) {
1346             /* We found and truncated three names from the path.
1347             *  Now append "source\data" and set the environment
1348             */
1349             strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1350             fgDataDir = p;
1351         }
1352         else {
1353             /* __FILE__ on MSVC7 does not contain the directory */
1354             FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1355             if (file) {
1356                 fclose(file);
1357                 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1358             }
1359             else {
1360                 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1361             }
1362         }
1363     }
1364 #endif
1365 
1366     return fgDataDir;
1367 
1368 }
1369 
1370 /*
1371  * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1372  * It converts a character string into a UnicodeString, with
1373  * unescaping \u sequences.
1374  */
CharsToUnicodeString(const char * chars)1375 UnicodeString CharsToUnicodeString(const char* chars)
1376 {
1377     UnicodeString str(chars, ""); // Invariant conversion
1378     return str.unescape();
1379 }
1380 
ctou(const char * chars)1381 UnicodeString ctou(const char* chars) {
1382     return CharsToUnicodeString(chars);
1383 }
1384 
1385 #define RAND_M  (714025)
1386 #define RAND_IA (1366)
1387 #define RAND_IC (150889)
1388 
1389 static int32_t RAND_SEED;
1390 
1391 /**
1392  * Returns a uniform random value x, with 0.0 <= x < 1.0.  Use
1393  * with care: Does not return all possible values; returns one of
1394  * 714,025 values, uniformly spaced.  However, the period is
1395  * effectively infinite.  See: Numerical Recipes, section 7.1.
1396  *
1397  * @param seedp pointer to seed. Set *seedp to any negative value
1398  * to restart the sequence.
1399  */
random(int32_t * seedp)1400 float IntlTest::random(int32_t* seedp) {
1401     static int32_t iy, ir[98];
1402     static UBool first=TRUE;
1403     int32_t j;
1404     if (*seedp < 0 || first) {
1405         first = FALSE;
1406         if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1407         for (j=1;j<=97;++j) {
1408             *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1409             ir[j]=(*seedp);
1410         }
1411         *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1412         iy=(*seedp);
1413     }
1414     j=(int32_t)(1 + 97.0*iy/RAND_M);
1415     U_ASSERT(j>=1 && j<=97);
1416     iy=ir[j];
1417     *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1418     ir[j]=(*seedp);
1419     return (float) iy/RAND_M;
1420 }
1421 
1422 /**
1423  * Convenience method using a global seed.
1424  */
random()1425 float IntlTest::random() {
1426     return random(&RAND_SEED);
1427 }
1428 
toHex(int32_t i)1429 static inline UChar toHex(int32_t i) {
1430     return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1431 }
1432 
escape(const UnicodeString & s,UnicodeString & result)1433 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1434     for (int32_t i=0; i<s.length(); ++i) {
1435         UChar c = s[i];
1436         if (c <= (UChar)0x7F) {
1437             result += c;
1438         } else {
1439             result += (UChar)0x5c;
1440             result += (UChar)0x75;
1441             result += toHex((c >> 12) & 0xF);
1442             result += toHex((c >>  8) & 0xF);
1443             result += toHex((c >>  4) & 0xF);
1444             result += toHex( c        & 0xF);
1445         }
1446     }
1447     return result;
1448 }
1449 
1450 #define VERBOSE_ASSERTIONS
1451 
assertTrue(const char * message,UBool condition,UBool quiet)1452 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet) {
1453     if (!condition) {
1454         errln("FAIL: assertTrue() failed: %s", message);
1455     } else if (!quiet) {
1456         logln("Ok: %s", message);
1457     }
1458     return condition;
1459 }
1460 
assertFalse(const char * message,UBool condition,UBool quiet)1461 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1462     if (condition) {
1463         errln("FAIL: assertFalse() failed: %s", message);
1464     } else if (!quiet) {
1465         logln("Ok: %s", message);
1466     }
1467     return !condition;
1468 }
1469 
assertSuccess(const char * message,UErrorCode ec)1470 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) {
1471     if (U_FAILURE(ec)) {
1472         errln("FAIL: %s (%s)", message, u_errorName(ec));
1473         return FALSE;
1474     }
1475     return TRUE;
1476 }
1477 
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual)1478 UBool IntlTest::assertEquals(const char* message,
1479                              const UnicodeString& expected,
1480                              const UnicodeString& actual) {
1481     if (expected != actual) {
1482         errln((UnicodeString)"FAIL: " + message + "; got " +
1483               prettify(actual) +
1484               "; expected " + prettify(expected));
1485         return FALSE;
1486     }
1487 #ifdef VERBOSE_ASSERTIONS
1488     else {
1489         logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1490     }
1491 #endif
1492     return TRUE;
1493 }
1494 
assertEquals(const char * message,const char * expected,const char * actual)1495 UBool IntlTest::assertEquals(const char* message,
1496                              const char* expected,
1497                              const char* actual) {
1498     if (uprv_strcmp(expected, actual) != 0) {
1499         errln((UnicodeString)"FAIL: " + message + "; got \"" +
1500               actual +
1501               "\"; expected \"" + expected + "\"");
1502         return FALSE;
1503     }
1504 #ifdef VERBOSE_ASSERTIONS
1505     else {
1506         logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1507     }
1508 #endif
1509     return TRUE;
1510 }
1511 
1512 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual)1513 UBool IntlTest::assertEquals(const char* message,
1514                              const Formattable& expected,
1515                              const Formattable& actual) {
1516     if (expected != actual) {
1517         errln((UnicodeString)"FAIL: " + message + "; got " +
1518               toString(actual) +
1519               "; expected " + toString(expected));
1520         return FALSE;
1521     }
1522 #ifdef VERBOSE_ASSERTIONS
1523     else {
1524         logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1525     }
1526 #endif
1527     return TRUE;
1528 }
1529 #endif
1530 
1531 static char ASSERT_BUF[256];
1532 
extractToAssertBuf(const UnicodeString & message)1533 static const char* extractToAssertBuf(const UnicodeString& message) {
1534     UnicodeString buf;
1535     escape(message, buf);
1536     buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1537     ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1538     return ASSERT_BUF;
1539 }
1540 
assertTrue(const UnicodeString & message,UBool condition,UBool quiet)1541 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1542     return assertTrue(extractToAssertBuf(message), condition, quiet);
1543 }
1544 
assertFalse(const UnicodeString & message,UBool condition,UBool quiet)1545 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1546     return assertFalse(extractToAssertBuf(message), condition, quiet);
1547 }
1548 
assertSuccess(const UnicodeString & message,UErrorCode ec)1549 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1550     return assertSuccess(extractToAssertBuf(message), ec);
1551 }
1552 
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual)1553 UBool IntlTest::assertEquals(const UnicodeString& message,
1554                              const UnicodeString& expected,
1555                              const UnicodeString& actual) {
1556     return assertEquals(extractToAssertBuf(message), expected, actual);
1557 }
1558 
assertEquals(const UnicodeString & message,const char * expected,const char * actual)1559 UBool IntlTest::assertEquals(const UnicodeString& message,
1560                              const char* expected,
1561                              const char* actual) {
1562     return assertEquals(extractToAssertBuf(message), expected, actual);
1563 }
1564 //--------------------------------------------------------------------
1565 // Time bomb - allows temporary behavior that expires at a given
1566 //             release
1567 //--------------------------------------------------------------------
1568 
isICUVersionAtLeast(const UVersionInfo x)1569 UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) {
1570     UVersionInfo v;
1571     u_getVersion(v);
1572     return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0);
1573 }
1574 
1575 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)1576 UBool IntlTest::assertEquals(const UnicodeString& message,
1577                              const Formattable& expected,
1578                              const Formattable& actual) {
1579     return assertEquals(extractToAssertBuf(message), expected, actual);
1580 }
1581 #endif
1582 
1583 /*
1584  * Hey, Emacs, please set the following:
1585  *
1586  * Local Variables:
1587  * indent-tabs-mode: nil
1588  * End:
1589  *
1590  */
1591