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