intltest.cpp revision b13da9df870a61b11249bf741347908dbea0edd8
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
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    testoutfp = stdout;
512    LL_indentlevel = indentLevel_offset;
513}
514
515void 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
527UBool 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
534void IntlTest::setPath( char* pathVal )
535{
536    this->testPath = pathVal;
537}
538
539UBool IntlTest::setVerbose( UBool verboseVal )
540{
541    UBool rval = this->verbose;
542    this->verbose = verboseVal;
543    return rval;
544}
545
546UBool 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
553UBool 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
560UBool IntlTest::setQuick( UBool quickVal )
561{
562    UBool rval = this->quick;
563    this->quick = quickVal;
564    return rval;
565}
566
567UBool IntlTest::setLeaks( UBool leaksVal )
568{
569    UBool rval = this->leaks;
570    this->leaks = leaksVal;
571    return rval;
572}
573
574int32_t IntlTest::getErrors( void )
575{
576    return errorCount;
577}
578
579int32_t IntlTest::getDataErrors( void )
580{
581    return dataErrorCount;
582}
583
584UBool 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
615void 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
630UBool 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*/
690void 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*/
701void IntlTest::logln( const UnicodeString &message )
702{
703    if( verbose ) {
704        LL_message( message, TRUE );
705    }
706}
707
708void IntlTest::logln( void )
709{
710    if( verbose ) {
711        LL_message( "", TRUE );
712    }
713}
714
715/**
716* Unconditionally adds given string to the log.
717*/
718void 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*/
727void IntlTest::infoln( const UnicodeString &message )
728{
729  LL_message( message, TRUE );
730}
731
732void IntlTest::infoln( void )
733{
734  LL_message( "", TRUE );
735}
736
737int32_t IntlTest::IncErrorCount( void )
738{
739    errorCount++;
740    if (caller) caller->IncErrorCount();
741    return errorCount;
742}
743
744int32_t IntlTest::IncDataErrorCount( void )
745{
746    dataErrorCount++;
747    if (caller) caller->IncDataErrorCount();
748    return dataErrorCount;
749}
750
751void IntlTest::err()
752{
753    IncErrorCount();
754}
755
756void IntlTest::err( const UnicodeString &message )
757{
758    IncErrorCount();
759    if (!no_err_msg) LL_message( message, FALSE );
760}
761
762void IntlTest::errln( const UnicodeString &message )
763{
764    IncErrorCount();
765    if (!no_err_msg) LL_message( message, TRUE );
766}
767
768void 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
779void 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 */
791void 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
805void 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 */
820void 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
832void 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
844void 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
855void 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
866void 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
877void IntlTest::printErrors()
878{
879     IntlTest::LL_message(errorList, TRUE);
880}
881
882void 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*/
933void 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
953UBool
954IntlTest::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
970int
971main(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
1239const 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
1278const char* IntlTest::getTestDataPath(UErrorCode& err) {
1279    return loadTestData(err);
1280}
1281
1282/* Returns the path to icu/source/test/testdata/ */
1283const 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
1302const char* IntlTest::fgDataDir = NULL;
1303
1304/* returns the path to icu/source/data */
1305const 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 */
1375UnicodeString CharsToUnicodeString(const char* chars)
1376{
1377    UnicodeString str(chars, ""); // Invariant conversion
1378    return str.unescape();
1379}
1380
1381UnicodeString 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
1389static 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 */
1400float 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 */
1425float IntlTest::random() {
1426    return random(&RAND_SEED);
1427}
1428
1429static inline UChar toHex(int32_t i) {
1430    return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1431}
1432
1433static 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
1452UBool 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
1461UBool 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
1470UBool 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
1478UBool 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
1495UBool 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
1513UBool 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
1531static char ASSERT_BUF[256];
1532
1533static 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
1541UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1542    return assertTrue(extractToAssertBuf(message), condition, quiet);
1543}
1544
1545UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1546    return assertFalse(extractToAssertBuf(message), condition, quiet);
1547}
1548
1549UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1550    return assertSuccess(extractToAssertBuf(message), ec);
1551}
1552
1553UBool IntlTest::assertEquals(const UnicodeString& message,
1554                             const UnicodeString& expected,
1555                             const UnicodeString& actual) {
1556    return assertEquals(extractToAssertBuf(message), expected, actual);
1557}
1558
1559UBool 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
1569UBool 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
1576UBool 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