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