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