1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2009, 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
48static char* _testDataPath=NULL;
49
50// Static list of errors found
51static 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
58UnicodeString
59UCharToUnicodeString(UChar c)
60{ return UnicodeString(c); }
61
62// [rtg] Just to get things working
63UnicodeString
64operator+(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
76UnicodeString
77operator+(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
89UnicodeString
90Int64ToUnicodeString(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
106UnicodeString
107operator+(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 */
128UnicodeString _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 */
193UnicodeString 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
203UnicodeString toString(int32_t n) {
204    return UnicodeString() + (long)n;
205}
206
207// stephen - cleaned up 05/05/99
208UnicodeString operator+(const UnicodeString& left, char num)
209{ return left + (long)num; }
210UnicodeString operator+(const UnicodeString& left, short num)
211{ return left + (long)num; }
212UnicodeString operator+(const UnicodeString& left, int num)
213{ return left + (long)num; }
214UnicodeString operator+(const UnicodeString& left, unsigned char num)
215{ return left + (unsigned long)num; }
216UnicodeString operator+(const UnicodeString& left, unsigned short num)
217{ return left + (unsigned long)num; }
218UnicodeString operator+(const UnicodeString& left, unsigned int num)
219{ return left + (unsigned long)num; }
220UnicodeString operator+(const UnicodeString& left, float num)
221{ return left + (double)num; }
222
223//------------------
224
225// Append a hex string to the target
226UnicodeString&
227IntlTest::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
262UnicodeString&
263IntlTest::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
298UnicodeString
299IntlTest::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 */
357void 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
426static const int32_t indentLevel_offset = 3;
427static const char delim = '/';
428
429IntlTest* IntlTest::gTest = NULL;
430
431static int32_t execCount = 0;
432
433void it_log( UnicodeString message )
434{
435    if (IntlTest::gTest)
436        IntlTest::gTest->log( message );
437}
438
439void it_logln( UnicodeString message )
440{
441    if (IntlTest::gTest)
442        IntlTest::gTest->logln( message );
443}
444
445void it_logln( void )
446{
447    if (IntlTest::gTest)
448        IntlTest::gTest->logln();
449}
450
451void it_info( UnicodeString message )
452{
453    if (IntlTest::gTest)
454        IntlTest::gTest->info( message );
455}
456
457void it_infoln( UnicodeString message )
458{
459    if (IntlTest::gTest)
460        IntlTest::gTest->infoln( message );
461}
462
463void it_infoln( void )
464{
465    if (IntlTest::gTest)
466        IntlTest::gTest->infoln();
467}
468
469void it_err()
470{
471    if (IntlTest::gTest)
472        IntlTest::gTest->err();
473}
474
475void it_err( UnicodeString message )
476{
477    if (IntlTest::gTest)
478        IntlTest::gTest->err( message );
479}
480
481void it_errln( UnicodeString message )
482{
483    if (IntlTest::gTest)
484        IntlTest::gTest->errln( message );
485}
486
487void it_dataerr( UnicodeString message )
488{
489    if (IntlTest::gTest)
490        IntlTest::gTest->dataerr( message );
491}
492
493void it_dataerrln( UnicodeString message )
494{
495    if (IntlTest::gTest)
496        IntlTest::gTest->dataerrln( message );
497}
498
499IntlTest::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    threadCount = 1;
512    testoutfp = stdout;
513    LL_indentlevel = indentLevel_offset;
514    numProps = 0;
515}
516
517void IntlTest::setCaller( IntlTest* callingTest )
518{
519    caller = callingTest;
520    if (caller) {
521        warn_on_missing_data = caller->warn_on_missing_data;
522        verbose = caller->verbose;
523        no_err_msg = caller->no_err_msg;
524        quick = caller->quick;
525        testoutfp = caller->testoutfp;
526        LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
527        numProps = caller->numProps;
528        for (int32_t i = 0; i < numProps; i++) {
529            proplines[i] = caller->proplines[i];
530        }
531    }
532}
533
534UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
535{
536    execCount--; // correct a previously assumed test-exec, as this only calls a subtest
537    testToBeCalled.setCaller( this );
538    return testToBeCalled.runTest( testPath, par );
539}
540
541void IntlTest::setPath( char* pathVal )
542{
543    this->testPath = pathVal;
544}
545
546UBool IntlTest::setVerbose( UBool verboseVal )
547{
548    UBool rval = this->verbose;
549    this->verbose = verboseVal;
550    return rval;
551}
552
553UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
554{
555    UBool rval = this->warn_on_missing_data;
556    this->warn_on_missing_data = warn_on_missing_dataVal;
557    return rval;
558}
559
560UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
561{
562    UBool rval = this->no_err_msg;
563    this->no_err_msg = no_err_msgVal;
564    return rval;
565}
566
567UBool IntlTest::setQuick( UBool quickVal )
568{
569    UBool rval = this->quick;
570    this->quick = quickVal;
571    return rval;
572}
573
574UBool IntlTest::setLeaks( UBool leaksVal )
575{
576    UBool rval = this->leaks;
577    this->leaks = leaksVal;
578    return rval;
579}
580
581int32_t IntlTest::setThreadCount( int32_t count )
582{
583    int32_t rval = this->threadCount;
584    this->threadCount = count;
585    return rval;
586}
587
588int32_t IntlTest::getErrors( void )
589{
590    return errorCount;
591}
592
593int32_t IntlTest::getDataErrors( void )
594{
595    return dataErrorCount;
596}
597
598UBool IntlTest::runTest( char* name, char* par )
599{
600    UBool rval;
601    char* pos = NULL;
602
603    if (name)
604        pos = strchr( name, delim ); // check if name contains path (by looking for '/')
605    if (pos) {
606        testPath = pos+1;   // store subpath for calling subtest
607        *pos = 0;       // split into two strings
608    }else{
609        testPath = NULL;
610    }
611
612    if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
613        rval = runTestLoop( NULL, par );
614
615    }else if (strcmp( name, "LIST" ) == 0) {
616        this->usage();
617        rval = TRUE;
618
619    }else{
620        rval = runTestLoop( name, par );
621    }
622
623    if (pos)
624        *pos = delim;  // restore original value at pos
625    return rval;
626}
627
628// call individual tests, to be overriden to call implementations
629void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
630{
631    // to be overriden by a method like:
632    /*
633    switch (index) {
634        case 0: name = "First Test"; if (exec) FirstTest( par ); break;
635        case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
636        default: name = ""; break;
637    }
638    */
639    this->errln("*** runIndexedTest needs to be overriden! ***");
640    name = ""; exec = exec; index = index; par = par;
641}
642
643
644UBool IntlTest::runTestLoop( char* testname, char* par )
645{
646    int32_t    index = 0;
647    const char*   name;
648    UBool  run_this_test;
649    int32_t    lastErrorCount;
650    UBool  rval = FALSE;
651    UBool   lastTestFailed;
652
653    IntlTest* saveTest = gTest;
654    gTest = this;
655    do {
656        this->runIndexedTest( index, FALSE, name, par );
657        if (strcmp(name,"skip") == 0) {
658            run_this_test = FALSE;
659        } else {
660            if (!name || (name[0] == 0))
661                break;
662            if (!testname) {
663                run_this_test = TRUE;
664            }else{
665                run_this_test = (UBool) (strcmp( name, testname ) == 0);
666            }
667        }
668        if (run_this_test) {
669            lastErrorCount = errorCount;
670            execCount++;
671            this->runIndexedTest( index, TRUE, name, par );
672            rval = TRUE; // at least one test has been called
673            char msg[256];
674            if (lastErrorCount == errorCount) {
675                sprintf( msg, "---OK:   %s", name );
676                lastTestFailed = FALSE;
677            }else{
678                sprintf(msg, "---ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
679
680                for(int i=0;i<LL_indentlevel;i++) {
681                    errorList += " ";
682                }
683                errorList += name;
684                errorList += "\n";
685                lastTestFailed = TRUE;
686            }
687            LL_indentlevel -= 3;
688            if (lastTestFailed) {
689                LL_message( "", TRUE);
690            }
691            LL_message( msg, TRUE);
692            if (lastTestFailed) {
693                LL_message( "", TRUE);
694            }
695            LL_indentlevel += 3;
696        }
697        index++;
698    }while(name);
699
700    gTest = saveTest;
701    return rval;
702}
703
704
705/**
706* Adds given string to the log if we are in verbose mode.
707*/
708void IntlTest::log( const UnicodeString &message )
709{
710    if( verbose ) {
711        LL_message( message, FALSE );
712    }
713}
714
715/**
716* Adds given string to the log if we are in verbose mode. Adds a new line to
717* the given message.
718*/
719void IntlTest::logln( const UnicodeString &message )
720{
721    if( verbose ) {
722        LL_message( message, TRUE );
723    }
724}
725
726void IntlTest::logln( void )
727{
728    if( verbose ) {
729        LL_message( "", TRUE );
730    }
731}
732
733/**
734* Unconditionally adds given string to the log.
735*/
736void IntlTest::info( const UnicodeString &message )
737{
738  LL_message( message, FALSE );
739}
740
741/**
742* Unconditionally adds given string to the log. Adds a new line to
743* the given message.
744*/
745void IntlTest::infoln( const UnicodeString &message )
746{
747  LL_message( message, TRUE );
748}
749
750void IntlTest::infoln( void )
751{
752  LL_message( "", TRUE );
753}
754
755int32_t IntlTest::IncErrorCount( void )
756{
757    errorCount++;
758    if (caller) caller->IncErrorCount();
759    return errorCount;
760}
761
762int32_t IntlTest::IncDataErrorCount( void )
763{
764    dataErrorCount++;
765    if (caller) caller->IncDataErrorCount();
766    return dataErrorCount;
767}
768
769void IntlTest::err()
770{
771    IncErrorCount();
772}
773
774void IntlTest::err( const UnicodeString &message )
775{
776    IncErrorCount();
777    if (!no_err_msg) LL_message( message, FALSE );
778}
779
780void IntlTest::errln( const UnicodeString &message )
781{
782    IncErrorCount();
783    if (!no_err_msg) LL_message( message, TRUE );
784}
785
786void IntlTest::dataerr( const UnicodeString &message )
787{
788    IncDataErrorCount();
789
790    if (!warn_on_missing_data) {
791        IncErrorCount();
792    }
793
794    if (!no_err_msg) LL_message( message, FALSE );
795}
796
797void IntlTest::dataerrln( const UnicodeString &message )
798{
799    IncDataErrorCount();
800    UnicodeString msg;
801    if (!warn_on_missing_data) {
802        IncErrorCount();
803        msg = message;
804    } else {
805        msg = UnicodeString("[DATA] " + message);
806    }
807
808    if (!no_err_msg) LL_message( msg + " - (Are you missing data?)", TRUE );
809}
810
811void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
812    if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
813        dataerrln(message);
814    } else {
815        errln(message);
816    }
817}
818
819/* convenience functions that include sprintf formatting */
820void IntlTest::log(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    if( verbose ) {
830        log(UnicodeString(buffer, ""));
831    }
832}
833
834void IntlTest::logln(const char *fmt, ...)
835{
836    char buffer[4000];
837    va_list ap;
838
839    va_start(ap, fmt);
840    /* sprintf it just to make sure that the information is valid */
841    vsprintf(buffer, fmt, ap);
842    va_end(ap);
843    if( verbose ) {
844        logln(UnicodeString(buffer, ""));
845    }
846}
847
848/* convenience functions that include sprintf formatting */
849void IntlTest::info(const char *fmt, ...)
850{
851    char buffer[4000];
852    va_list ap;
853
854    va_start(ap, fmt);
855    /* sprintf it just to make sure that the information is valid */
856    vsprintf(buffer, fmt, ap);
857    va_end(ap);
858    info(UnicodeString(buffer, ""));
859}
860
861void IntlTest::infoln(const char *fmt, ...)
862{
863    char buffer[4000];
864    va_list ap;
865
866    va_start(ap, fmt);
867    /* sprintf it just to make sure that the information is valid */
868    vsprintf(buffer, fmt, ap);
869    va_end(ap);
870    infoln(UnicodeString(buffer, ""));
871}
872
873void IntlTest::err(const char *fmt, ...)
874{
875    char buffer[4000];
876    va_list ap;
877
878    va_start(ap, fmt);
879    vsprintf(buffer, fmt, ap);
880    va_end(ap);
881    err(UnicodeString(buffer, ""));
882}
883
884void IntlTest::errln(const char *fmt, ...)
885{
886    char buffer[4000];
887    va_list ap;
888
889    va_start(ap, fmt);
890    vsprintf(buffer, fmt, ap);
891    va_end(ap);
892    errln(UnicodeString(buffer, ""));
893}
894
895void IntlTest::dataerrln(const char *fmt, ...)
896{
897    char buffer[4000];
898    va_list ap;
899
900    va_start(ap, fmt);
901    vsprintf(buffer, fmt, ap);
902    va_end(ap);
903    dataerrln(UnicodeString(buffer, ""));
904}
905
906void IntlTest::errcheckln(UErrorCode status, const char *fmt, ...)
907{
908    char buffer[4000];
909    va_list ap;
910
911    va_start(ap, fmt);
912    vsprintf(buffer, fmt, ap);
913    va_end(ap);
914
915    if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
916        dataerrln(UnicodeString(buffer, ""));
917    } else {
918        errln(UnicodeString(buffer, ""));
919    }
920}
921
922void IntlTest::printErrors()
923{
924     IntlTest::LL_message(errorList, TRUE);
925}
926
927void IntlTest::LL_message( UnicodeString message, UBool newline )
928{
929    // string that starts with a LineFeed character and continues
930    // with spaces according to the current indentation
931    static const UChar indentUChars[] = {
932        '\n',
933        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
934        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
935        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
936        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
937        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
938        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
939        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
940        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
941        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
942        32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
943    };
944    UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
945
946    char buffer[10000];
947    int32_t length;
948
949    // stream out the indentation string first if necessary
950    length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
951    if (length > 0) {
952        fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
953    }
954
955    // replace each LineFeed by the indentation string
956    message.findAndReplace(UnicodeString((UChar)'\n'), indent);
957
958    // stream out the message
959    length = message.extract(0, message.length(), buffer, sizeof(buffer));
960    if (length > 0) {
961        length = length > 10000 ? 10000 : length;
962        fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
963    }
964
965    if (newline) {
966        char newLine = '\n';
967        fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
968    }
969
970    // A newline usually flushes the buffer, but
971    // flush the message just in case of a core dump.
972    fflush((FILE *)testoutfp);
973}
974
975/**
976* Print a usage message for this test class.
977*/
978void IntlTest::usage( void )
979{
980    UBool save_verbose = setVerbose( TRUE );
981    logln("Test names:");
982    logln("-----------");
983
984    int32_t index = 0;
985    const char* name = NULL;
986    do{
987        this->runIndexedTest( index, FALSE, name );
988        if (!name) break;
989        logln(name);
990        index++;
991    }while (name && (name[0] != 0));
992    setVerbose( save_verbose );
993}
994
995
996// memory leak reporting software will be able to take advantage of the testsuite
997// being run a second time local to a specific method in order to report only actual leaks
998UBool
999IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1000{
1001    UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1002    strLeak->append(" for verifying purify filter");
1003    return this->runTest( name, par );
1004}
1005
1006
1007#if UCONFIG_NO_LEGACY_CONVERSION
1008#   define TRY_CNV_1 "iso-8859-1"
1009#   define TRY_CNV_2 "ibm-1208"
1010#else
1011#   define TRY_CNV_1 "iso-8859-7"
1012#   define TRY_CNV_2 "sjis"
1013#endif
1014
1015int
1016main(int argc, char* argv[])
1017{
1018    UBool syntax = FALSE;
1019    UBool all = FALSE;
1020    UBool verbose = FALSE;
1021    UBool no_err_msg = FALSE;
1022    UBool quick = TRUE;
1023    UBool name = FALSE;
1024    UBool leaks = FALSE;
1025    UBool warnOnMissingData = FALSE;
1026    UBool defaultDataFound = FALSE;
1027    int32_t threadCount = 1;
1028    UErrorCode errorCode = U_ZERO_ERROR;
1029    UConverter *cnv = NULL;
1030    const char *warnOrErr = "Failure";
1031    UDate startTime, endTime;
1032    int32_t diffTime;
1033    const char *props[IntlTest::kMaxProps];
1034    int32_t nProps = 0;
1035
1036    U_MAIN_INIT_ARGS(argc, argv);
1037
1038    startTime = uprv_getUTCtime();
1039
1040    for (int i = 1; i < argc; ++i) {
1041        if (argv[i][0] == '-') {
1042            const char* str = argv[i] + 1;
1043            if (strcmp("verbose", str) == 0 ||
1044                strcmp("v", str) == 0)
1045                verbose = TRUE;
1046            else if (strcmp("noerrormsg", str) == 0 ||
1047                     strcmp("n", str) == 0)
1048                no_err_msg = TRUE;
1049            else if (strcmp("exhaustive", str) == 0 ||
1050                     strcmp("e", str) == 0)
1051                quick = FALSE;
1052            else if (strcmp("all", str) == 0 ||
1053                     strcmp("a", str) == 0)
1054                all = TRUE;
1055            else if (strcmp("leaks", str) == 0 ||
1056                     strcmp("l", str) == 0)
1057                leaks = TRUE;
1058            else if (strcmp("w", str) == 0) {
1059              warnOnMissingData = TRUE;
1060              warnOrErr = "WARNING";
1061            }
1062            else if (strncmp("threads:", str, 8) == 0) {
1063                threadCount = atoi(str + 8);
1064            }
1065            else if (strncmp("prop:", str, 5) == 0) {
1066                if (nProps < IntlTest::kMaxProps) {
1067                    props[nProps] = str + 5;
1068                }
1069                nProps++;
1070            }
1071            else {
1072                syntax = TRUE;
1073            }
1074        }else{
1075            name = TRUE;
1076        }
1077    }
1078
1079    if (!all && !name) {
1080        all = TRUE;
1081    } else if (all && name) {
1082        syntax = TRUE;
1083    }
1084
1085    if (syntax) {
1086        fprintf(stdout,
1087                "### Syntax:\n"
1088                "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1089                "### \n"
1090                "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1091                "### exhaustive (e), leaks (l), prop:<propery>=<value>, \n"
1092                "### threads:<threadCount> (Mulithreading must first be \n"
1093                "###     enabled otherwise this will be ignored. \n"
1094                "###     The default thread count is 1.),\n"
1095                "### (Specify either -all (shortcut -a) or a test name). \n"
1096                "### -all will run all of the tests.\n"
1097                "### \n"
1098                "### To get a list of the test names type: intltest LIST \n"
1099                "### To run just the utility tests type: intltest utility \n"
1100                "### \n"
1101                "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1102                "### For example to list the utility tests type: intltest utility/LIST \n"
1103                "### To run just the Locale test type: intltest utility/LocaleTest \n"
1104                "### \n"
1105                "### A parameter can be specified for a test by appending '@' and the value \n"
1106                "### to the testname. \n\n");
1107        return 1;
1108    }
1109
1110    if (nProps > IntlTest::kMaxProps) {
1111        fprintf(stdout, "### Too many properties.  Exiting.\n");
1112    }
1113
1114    UBool all_tests_exist = TRUE;
1115    MajorTestLevel major;
1116    major.setVerbose( verbose );
1117    major.setNoErrMsg( no_err_msg );
1118    major.setQuick( quick );
1119    major.setLeaks( leaks );
1120    major.setThreadCount( threadCount );
1121    major.setWarnOnMissingData( warnOnMissingData );
1122    for (int32_t i = 0; i < nProps; i++) {
1123        major.setProperty(props[i]);
1124    }
1125    fprintf(stdout, "-----------------------------------------------\n");
1126    fprintf(stdout, " IntlTest (C++) Test Suite for                 \n");
1127    fprintf(stdout, "   International Components for Unicode %s\n", U_ICU_VERSION);
1128    {
1129	const char *charsetFamily = "Unknown";
1130        int32_t voidSize = (int32_t)sizeof(void*);
1131        int32_t bits = voidSize * 8;
1132        if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1133           charsetFamily="ASCII";
1134        } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1135           charsetFamily="EBCDIC";
1136        }
1137        fprintf(stdout,
1138                    "   Bits: %d, Byte order: %s, Chars: %s\n",
1139                     bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1140                     charsetFamily);
1141    }
1142    fprintf(stdout, "-----------------------------------------------\n");
1143    fprintf(stdout, " Options:                                       \n");
1144    fprintf(stdout, "   all (a)                  : %s\n", (all?               "On" : "Off"));
1145    fprintf(stdout, "   Verbose (v)              : %s\n", (verbose?           "On" : "Off"));
1146    fprintf(stdout, "   No error messages (n)    : %s\n", (no_err_msg?        "On" : "Off"));
1147    fprintf(stdout, "   Exhaustive (e)           : %s\n", (!quick?            "On" : "Off"));
1148    fprintf(stdout, "   Leaks (l)                : %s\n", (leaks?             "On" : "Off"));
1149    fprintf(stdout, "   Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1150#if (ICU_USE_THREADS==0)
1151    fprintf(stdout, "   Threads                  : Disabled\n");
1152#else
1153    fprintf(stdout, "   Threads                  : %d\n", threadCount);
1154#endif
1155    for (int32_t i = 0; i < nProps; i++) {
1156        fprintf(stdout, "   Custom property (prop:)  : %s\n", props[i]);
1157    }
1158    fprintf(stdout, "-----------------------------------------------\n");
1159
1160    /* Check whether ICU will initialize without forcing the build data directory into
1161     *  the ICU_DATA path.  Success here means either the data dll contains data, or that
1162     *  this test program was run with ICU_DATA set externally.  Failure of this check
1163     *  is normal when ICU data is not packaged into a shared library.
1164     *
1165     *  Whether or not this test succeeds, we want to cleanup and reinitialize
1166     *  with a data path so that data loading from individual files can be tested.
1167     */
1168    u_init(&errorCode);
1169    if (U_FAILURE(errorCode)) {
1170        fprintf(stderr,
1171            "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
1172        defaultDataFound = FALSE;
1173    }
1174    else {
1175        defaultDataFound = TRUE;
1176    }
1177    u_cleanup();
1178    errorCode = U_ZERO_ERROR;
1179
1180    /* Initialize ICU */
1181    if (!defaultDataFound) {
1182        IntlTest::setICU_DATA();   // Must set data directory before u_init() is called.
1183    }
1184    u_init(&errorCode);
1185    if (U_FAILURE(errorCode)) {
1186        fprintf(stderr,
1187            "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1188            "*** Check the ICU_DATA environment variable and \n"
1189            "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1190            if(warnOnMissingData == 0) {
1191                fprintf(stderr, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1192                u_cleanup();
1193                return 1;
1194            }
1195    }
1196
1197
1198    // initial check for the default converter
1199    errorCode = U_ZERO_ERROR;
1200    cnv = ucnv_open(0, &errorCode);
1201    if(cnv != 0) {
1202        // ok
1203        ucnv_close(cnv);
1204    } else {
1205        fprintf(stdout,
1206                "*** %s! The default converter [%s] cannot be opened.\n"
1207                "*** Check the ICU_DATA environment variable and\n"
1208                "*** check that the data files are present.\n",
1209                warnOrErr, ucnv_getDefaultName());
1210        if(!warnOnMissingData) {
1211          fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1212          return 1;
1213        }
1214    }
1215
1216    // try more data
1217    cnv = ucnv_open(TRY_CNV_2, &errorCode);
1218    if(cnv != 0) {
1219        // ok
1220        ucnv_close(cnv);
1221    } else {
1222        fprintf(stdout,
1223                "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1224                "*** Check the ICU_DATA environment variable and \n"
1225                "*** check that the data files are present.\n", warnOrErr);
1226        if(!warnOnMissingData) {
1227          fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1228          return 1;
1229        }
1230    }
1231
1232    UResourceBundle *rb = ures_open(0, "en", &errorCode);
1233    ures_close(rb);
1234    if(U_FAILURE(errorCode)) {
1235        fprintf(stdout,
1236                "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1237                "*** Check the ICU_DATA environment variable and \n"
1238                "*** check that the data files are present.\n", warnOrErr);
1239        if(!warnOnMissingData) {
1240          fprintf(stdout, "*** Exiting.  Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1241          return 1;
1242        }
1243    }
1244
1245    Locale originalLocale;  // Save the default locale for comparison later on.
1246
1247    /* TODO: Add option to call u_cleanup and rerun tests. */
1248    if (all) {
1249        major.runTest();
1250        if (leaks) {
1251            major.run_phase2( NULL, NULL );
1252        }
1253    }else{
1254        for (int i = 1; i < argc; ++i) {
1255            if (argv[i][0] != '-') {
1256                char* name = argv[i];
1257                fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1258                char* parameter = strchr( name, '@' );
1259                if (parameter) {
1260                    *parameter = 0;
1261                    parameter += 1;
1262                }
1263                execCount = 0;
1264                UBool res = major.runTest( name, parameter );
1265                if (leaks && res) {
1266                    major.run_phase2( name, parameter );
1267                }
1268                if (!res || (execCount <= 0)) {
1269                    fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1270                    all_tests_exist = FALSE;
1271                }
1272            }
1273        }
1274    }
1275
1276#if !UCONFIG_NO_FORMATTING
1277    CalendarTimeZoneTest::cleanup();
1278#endif
1279
1280    free(_testDataPath);
1281    _testDataPath = 0;
1282
1283    Locale lastDefaultLocale;
1284    if (originalLocale != lastDefaultLocale) {
1285        major.errln("FAILURE: A test changed the default locale without resetting it.");
1286    }
1287
1288    fprintf(stdout, "\n--------------------------------------\n");
1289    if (major.getErrors() == 0) {
1290        /* Call it twice to make sure that the defaults were reset. */
1291        /* Call it before the OK message to verify proper cleanup. */
1292        u_cleanup();
1293        u_cleanup();
1294
1295        fprintf(stdout, "OK: All tests passed without error.\n");
1296
1297        if (major.getDataErrors() != 0) {
1298            fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1299        }
1300    }else{
1301        fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1302        major.printErrors();
1303
1304
1305        if (major.getDataErrors() != 0) {
1306            fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1307                    "\tstock ICU data (i.e some have been added or removed), consider using\n"
1308                    "\tthe '-w' option to turn these errors into warnings.\n");
1309        }
1310
1311        /* Call afterwards to display errors. */
1312        u_cleanup();
1313    }
1314
1315    fprintf(stdout, "--------------------------------------\n");
1316
1317    if (execCount <= 0) {
1318        fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1319    }
1320    endTime = uprv_getUTCtime();
1321    diffTime = (int32_t)(endTime - startTime);
1322    printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1323        (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1324        (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1325        (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1326        (int)(diffTime%U_MILLIS_PER_SECOND));
1327    return major.getErrors();
1328}
1329
1330const char* IntlTest::loadTestData(UErrorCode& err){
1331    if( _testDataPath == NULL){
1332        const char*      directory=NULL;
1333        UResourceBundle* test =NULL;
1334        char* tdpath=NULL;
1335        const char* tdrelativepath;
1336
1337#if defined (U_TOPBUILDDIR)
1338        tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1339        directory = U_TOPBUILDDIR;
1340#else
1341        tdrelativepath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1342        directory = pathToDataDirectory();
1343#endif
1344
1345        tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1346
1347
1348        /* u_getDataDirectory shoul return \source\data ... set the
1349         * directory to ..\source\data\..\test\testdata\out\testdata
1350         */
1351        strcpy(tdpath, directory);
1352        strcat(tdpath, tdrelativepath);
1353        strcat(tdpath,"testdata");
1354
1355        test=ures_open(tdpath, "testtypes", &err);
1356
1357        if(U_FAILURE(err)){
1358            err = U_FILE_ACCESS_ERROR;
1359            it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1360            return "";
1361        }
1362        ures_close(test);
1363        _testDataPath = tdpath;
1364        return _testDataPath;
1365    }
1366    return _testDataPath;
1367}
1368
1369const char* IntlTest::getTestDataPath(UErrorCode& err) {
1370    return loadTestData(err);
1371}
1372
1373/* Returns the path to icu/source/test/testdata/ */
1374const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1375    const char *srcDataDir = NULL;
1376#ifdef U_TOPSRCDIR
1377    srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1378#else
1379    srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1380    FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
1381    if (f) {
1382        /* We're in icu/source/test/intltest/ */
1383        fclose(f);
1384    }
1385    else {
1386        /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1387        srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1388    }
1389#endif
1390    return srcDataDir;
1391}
1392
1393const char* IntlTest::fgDataDir = NULL;
1394
1395/* returns the path to icu/source/data */
1396const char *  IntlTest::pathToDataDirectory()
1397{
1398
1399    if(fgDataDir != NULL) {
1400        return fgDataDir;
1401    }
1402
1403    /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1404    //              to point to the top of the build hierarchy, which may or
1405    //              may not be the same as the source directory, depending on
1406    //              the configure options used.  At any rate,
1407    //              set the data path to the built data from this directory.
1408    //              The value is complete with quotes, so it can be used
1409    //              as-is as a string constant.
1410    */
1411#if defined (U_TOPSRCDIR)
1412    {
1413        fgDataDir = U_TOPSRCDIR  U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1414    }
1415#else
1416
1417    /* On Windows, the file name obtained from __FILE__ includes a full path.
1418     *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
1419     *             Change to    "wherever\icu\source\data"
1420     */
1421    {
1422        static char p[sizeof(__FILE__) + 10];
1423        char *pBackSlash;
1424        int i;
1425
1426        strcpy(p, __FILE__);
1427        /* We want to back over three '\' chars.                            */
1428        /*   Only Windows should end up here, so looking for '\' is safe.   */
1429        for (i=1; i<=3; i++) {
1430            pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1431            if (pBackSlash != NULL) {
1432                *pBackSlash = 0;        /* Truncate the string at the '\'   */
1433            }
1434        }
1435
1436        if (pBackSlash != NULL) {
1437            /* We found and truncated three names from the path.
1438            *  Now append "source\data" and set the environment
1439            */
1440            strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1441            fgDataDir = p;
1442        }
1443        else {
1444            /* __FILE__ on MSVC7 does not contain the directory */
1445            FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1446            if (file) {
1447                fclose(file);
1448                fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1449            }
1450            else {
1451                fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1452            }
1453        }
1454    }
1455#endif
1456
1457    return fgDataDir;
1458
1459}
1460
1461/*
1462 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1463 * It converts a character string into a UnicodeString, with
1464 * unescaping \u sequences.
1465 */
1466UnicodeString CharsToUnicodeString(const char* chars){
1467    UnicodeString str(chars, ""); // Invariant conversion
1468    return str.unescape();
1469}
1470
1471UnicodeString ctou(const char* chars) {
1472    return CharsToUnicodeString(chars);
1473}
1474
1475#define RAND_M  (714025)
1476#define RAND_IA (1366)
1477#define RAND_IC (150889)
1478
1479static int32_t RAND_SEED;
1480
1481/**
1482 * Returns a uniform random value x, with 0.0 <= x < 1.0.  Use
1483 * with care: Does not return all possible values; returns one of
1484 * 714,025 values, uniformly spaced.  However, the period is
1485 * effectively infinite.  See: Numerical Recipes, section 7.1.
1486 *
1487 * @param seedp pointer to seed. Set *seedp to any negative value
1488 * to restart the sequence.
1489 */
1490float IntlTest::random(int32_t* seedp) {
1491    static int32_t iy, ir[98];
1492    static UBool first=TRUE;
1493    int32_t j;
1494    if (*seedp < 0 || first) {
1495        first = FALSE;
1496        if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1497        for (j=1;j<=97;++j) {
1498            *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1499            ir[j]=(*seedp);
1500        }
1501        *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1502        iy=(*seedp);
1503    }
1504    j=(int32_t)(1 + 97.0*iy/RAND_M);
1505    U_ASSERT(j>=1 && j<=97);
1506    iy=ir[j];
1507    *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1508    ir[j]=(*seedp);
1509    return (float) iy/RAND_M;
1510}
1511
1512/**
1513 * Convenience method using a global seed.
1514 */
1515float IntlTest::random() {
1516    return random(&RAND_SEED);
1517}
1518
1519static inline UChar toHex(int32_t i) {
1520    return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1521}
1522
1523static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1524    for (int32_t i=0; i<s.length(); ++i) {
1525        UChar c = s[i];
1526        if (c <= (UChar)0x7F) {
1527            result += c;
1528        } else {
1529            result += (UChar)0x5c;
1530            result += (UChar)0x75;
1531            result += toHex((c >> 12) & 0xF);
1532            result += toHex((c >>  8) & 0xF);
1533            result += toHex((c >>  4) & 0xF);
1534            result += toHex( c        & 0xF);
1535        }
1536    }
1537    return result;
1538}
1539
1540#define VERBOSE_ASSERTIONS
1541
1542UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError) {
1543    if (!condition) {
1544        if (possibleDataError) {
1545            dataerrln("FAIL: assertTrue() failed: %s", message);
1546        } else {
1547            errln("FAIL: assertTrue() failed: %s", message);
1548        }
1549    } else if (!quiet) {
1550        logln("Ok: %s", message);
1551    }
1552    return condition;
1553}
1554
1555UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1556    if (condition) {
1557        errln("FAIL: assertFalse() failed: %s", message);
1558    } else if (!quiet) {
1559        logln("Ok: %s", message);
1560    }
1561    return !condition;
1562}
1563
1564UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError) {
1565    if (U_FAILURE(ec)) {
1566        if (possibleDataError) {
1567            dataerrln("FAIL: %s (%s)", message, u_errorName(ec));
1568        } else {
1569            errcheckln(ec, "FAIL: %s (%s)", message, u_errorName(ec));
1570        }
1571
1572        return FALSE;
1573    }
1574    return TRUE;
1575}
1576
1577UBool IntlTest::assertEquals(const char* message,
1578                             const UnicodeString& expected,
1579                             const UnicodeString& actual,
1580                             UBool possibleDataError) {
1581    if (expected != actual) {
1582        if (possibleDataError) {
1583            dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1584                  prettify(actual) +
1585                  "; expected " + prettify(expected));
1586        } else {
1587            errln((UnicodeString)"FAIL: " + message + "; got " +
1588                  prettify(actual) +
1589                  "; expected " + prettify(expected));
1590        }
1591        return FALSE;
1592    }
1593#ifdef VERBOSE_ASSERTIONS
1594    else {
1595        logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1596    }
1597#endif
1598    return TRUE;
1599}
1600
1601UBool IntlTest::assertEquals(const char* message,
1602                             const char* expected,
1603                             const char* actual) {
1604    if (uprv_strcmp(expected, actual) != 0) {
1605        errln((UnicodeString)"FAIL: " + message + "; got \"" +
1606              actual +
1607              "\"; expected \"" + expected + "\"");
1608        return FALSE;
1609    }
1610#ifdef VERBOSE_ASSERTIONS
1611    else {
1612        logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1613    }
1614#endif
1615    return TRUE;
1616}
1617
1618#if !UCONFIG_NO_FORMATTING
1619UBool IntlTest::assertEquals(const char* message,
1620                             const Formattable& expected,
1621                             const Formattable& actual) {
1622    if (expected != actual) {
1623        errln((UnicodeString)"FAIL: " + message + "; got " +
1624              toString(actual) +
1625              "; expected " + toString(expected));
1626        return FALSE;
1627    }
1628#ifdef VERBOSE_ASSERTIONS
1629    else {
1630        logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1631    }
1632#endif
1633    return TRUE;
1634}
1635#endif
1636
1637static char ASSERT_BUF[256];
1638
1639static const char* extractToAssertBuf(const UnicodeString& message) {
1640    UnicodeString buf;
1641    escape(message, buf);
1642    buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1643    ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1644    return ASSERT_BUF;
1645}
1646
1647UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1648    return assertTrue(extractToAssertBuf(message), condition, quiet);
1649}
1650
1651UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1652    return assertFalse(extractToAssertBuf(message), condition, quiet);
1653}
1654
1655UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1656    return assertSuccess(extractToAssertBuf(message), ec);
1657}
1658
1659UBool IntlTest::assertEquals(const UnicodeString& message,
1660                             const UnicodeString& expected,
1661                             const UnicodeString& actual) {
1662    return assertEquals(extractToAssertBuf(message), expected, actual);
1663}
1664
1665UBool IntlTest::assertEquals(const UnicodeString& message,
1666                             const char* expected,
1667                             const char* actual) {
1668    return assertEquals(extractToAssertBuf(message), expected, actual);
1669}
1670//--------------------------------------------------------------------
1671// Time bomb - allows temporary behavior that expires at a given
1672//             release
1673//--------------------------------------------------------------------
1674
1675UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) {
1676    UVersionInfo v;
1677    u_getVersion(v);
1678    return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0);
1679}
1680
1681#if !UCONFIG_NO_FORMATTING
1682UBool IntlTest::assertEquals(const UnicodeString& message,
1683                             const Formattable& expected,
1684                             const Formattable& actual) {
1685    return assertEquals(extractToAssertBuf(message), expected, actual);
1686}
1687#endif
1688
1689void IntlTest::setProperty(const char* propline) {
1690    if (numProps < kMaxProps) {
1691        proplines[numProps] = propline;
1692    }
1693    numProps++;
1694}
1695
1696const char* IntlTest::getProperty(const char* prop) {
1697    const char* val = NULL;
1698    for (int32_t i = 0; i < numProps; i++) {
1699        int32_t plen = uprv_strlen(prop);
1700        if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
1701                && proplines[i][plen] == '='
1702                && uprv_strncmp(proplines[i], prop, plen) == 0) {
1703            val = &(proplines[i][plen+1]);
1704            break;
1705        }
1706    }
1707    return val;
1708}
1709
1710/*
1711 * Hey, Emacs, please set the following:
1712 *
1713 * Local Variables:
1714 * indent-tabs-mode: nil
1715 * End:
1716 *
1717 */
1718