Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / intltest / intltest.cpp
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
52 static char* _testDataPath=NULL;
53
54 // Static list of errors found
55 static UnicodeString errorList;
56 static void *knownList = NULL; // known issues
57 static 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
64 UnicodeString
65 UCharToUnicodeString(UChar c)
66 { return UnicodeString(c); }
67
68 // [rtg] Just to get things working
69 UnicodeString
70 operator+(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
82 UnicodeString
83 operator+(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
95 UnicodeString
96 Int64ToUnicodeString(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
112 UnicodeString
113 operator+(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
130 UnicodeString
131 operator+(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  */
142 UnicodeString _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  */
207 UnicodeString 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
217 UnicodeString toString(int32_t n) {
218     return UnicodeString() + (long)n;
219 }
220
221
222
223 UnicodeString toString(UBool b) {
224   return b ? UnicodeString("TRUE"):UnicodeString("FALSE");
225 }
226
227 // stephen - cleaned up 05/05/99
228 UnicodeString operator+(const UnicodeString& left, char num)
229 { return left + (long)num; }
230 UnicodeString operator+(const UnicodeString& left, short num)
231 { return left + (long)num; }
232 UnicodeString operator+(const UnicodeString& left, int num)
233 { return left + (long)num; }
234 UnicodeString operator+(const UnicodeString& left, unsigned char num)
235 { return left + (unsigned long)num; }
236 UnicodeString operator+(const UnicodeString& left, unsigned short num)
237 { return left + (unsigned long)num; }
238 UnicodeString operator+(const UnicodeString& left, unsigned int num)
239 { return left + (unsigned long)num; }
240 UnicodeString operator+(const UnicodeString& left, float num)
241 { return left + (double)num; }
242
243 //------------------
244
245 // Append a hex string to the target
246 UnicodeString&
247 IntlTest::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
296 UnicodeString
297 IntlTest::toHex(uint32_t number, int32_t digits) {
298     UnicodeString result;
299     appendHex(number, digits, result);
300     return result;
301 }
302
303 static 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
308 UnicodeString&
309 IntlTest::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
344 UnicodeString
345 IntlTest::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  */
403 void 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
472 static const int32_t indentLevel_offset = 3;
473 static const char delim = '/';
474
475 IntlTest* IntlTest::gTest = NULL;
476
477 static int32_t execCount = 0;
478
479 void it_log( UnicodeString message )
480 {
481     if (IntlTest::gTest)
482         IntlTest::gTest->log( message );
483 }
484
485 void it_logln( UnicodeString message )
486 {
487     if (IntlTest::gTest)
488         IntlTest::gTest->logln( message );
489 }
490
491 void it_logln( void )
492 {
493     if (IntlTest::gTest)
494         IntlTest::gTest->logln();
495 }
496
497 void it_info( UnicodeString message )
498 {
499     if (IntlTest::gTest)
500         IntlTest::gTest->info( message );
501 }
502
503 void it_infoln( UnicodeString message )
504 {
505     if (IntlTest::gTest)
506         IntlTest::gTest->infoln( message );
507 }
508
509 void it_infoln( void )
510 {
511     if (IntlTest::gTest)
512         IntlTest::gTest->infoln();
513 }
514
515 void it_err()
516 {
517     if (IntlTest::gTest)
518         IntlTest::gTest->err();
519 }
520
521 void it_err( UnicodeString message )
522 {
523     if (IntlTest::gTest)
524         IntlTest::gTest->err( message );
525 }
526
527 void it_errln( UnicodeString message )
528 {
529     if (IntlTest::gTest)
530         IntlTest::gTest->errln( message );
531 }
532
533 void it_dataerr( UnicodeString message )
534 {
535     if (IntlTest::gTest)
536         IntlTest::gTest->dataerr( message );
537 }
538
539 void it_dataerrln( UnicodeString message )
540 {
541     if (IntlTest::gTest)
542         IntlTest::gTest->dataerrln( message );
543 }
544
545 IntlTest::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
566 void 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
584 UBool 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
594 void IntlTest::setPath( char* pathVal )
595 {
596     this->testPath = pathVal;
597 }
598
599 UBool IntlTest::setVerbose( UBool verboseVal )
600 {
601     UBool rval = this->verbose;
602     this->verbose = verboseVal;
603     return rval;
604 }
605
606 UBool IntlTest::setNotime( UBool no_time )
607 {
608     UBool rval = this->no_time;
609     this->no_time = no_time;
610     return rval;
611 }
612
613 UBool 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
620 UBool 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
627 UBool IntlTest::setQuick( UBool quickVal )
628 {
629     UBool rval = this->quick;
630     this->quick = quickVal;
631     return rval;
632 }
633
634 UBool IntlTest::setLeaks( UBool leaksVal )
635 {
636     UBool rval = this->leaks;
637     this->leaks = leaksVal;
638     return rval;
639 }
640
641 int32_t IntlTest::setThreadCount( int32_t count )
642 {
643     int32_t rval = this->threadCount;
644     this->threadCount = count;
645     return rval;
646 }
647
648 int32_t IntlTest::getErrors( void )
649 {
650     return errorCount;
651 }
652
653 int32_t IntlTest::getDataErrors( void )
654 {
655     return dataErrorCount;
656 }
657
658 UBool 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
700 void 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
714 UBool 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 */
819 void 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 */
830 void IntlTest::logln( const UnicodeString &message )
831 {
832     if( verbose ) {
833         LL_message( message, TRUE );
834     }
835 }
836
837 void IntlTest::logln( void )
838 {
839     if( verbose ) {
840         LL_message( "", TRUE );
841     }
842 }
843
844 /**
845 * Unconditionally adds given string to the log.
846 */
847 void 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 */
856 void IntlTest::infoln( const UnicodeString &message )
857 {
858   LL_message( message, TRUE );
859 }
860
861 void IntlTest::infoln( void )
862 {
863   LL_message( "", TRUE );
864 }
865
866 int32_t IntlTest::IncErrorCount( void )
867 {
868     errorCount++;
869     if (caller) caller->IncErrorCount();
870     return errorCount;
871 }
872
873 int32_t IntlTest::IncDataErrorCount( void )
874 {
875     dataErrorCount++;
876     if (caller) caller->IncDataErrorCount();
877     return dataErrorCount;
878 }
879
880 void IntlTest::err()
881 {
882     IncErrorCount();
883 }
884
885 void IntlTest::err( const UnicodeString &message )
886 {
887     IncErrorCount();
888     if (!no_err_msg) LL_message( message, FALSE );
889 }
890
891 void IntlTest::errln( const UnicodeString &message )
892 {
893     IncErrorCount();
894     if (!no_err_msg) LL_message( message, TRUE );
895 }
896
897 void 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
908 void 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
928 void 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 */
937 void 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
951 void 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
965 UBool 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
977 UBool IntlTest::logKnownIssue(const char *ticket) {
978   return logKnownIssue(ticket, UnicodeString());
979 }
980
981 UBool 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 */
1003 void 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
1015 void 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
1027 void 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
1038 void 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
1049 void 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
1060 void 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
1076 void IntlTest::printErrors()
1077 {
1078      IntlTest::LL_message(errorList, TRUE);
1079 }
1080
1081 UBool 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
1092 static UMutex messageMutex = U_MUTEX_INITIALIZER;
1093
1094 void 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 */
1152 void 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
1172 UBool
1173 IntlTest::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
1190 U_CAPI void unistr_printLengths();
1191 #endif
1192
1193 int
1194 main(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
1571 const 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
1610 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1611     return loadTestData(err);
1612 }
1613
1614 /* Returns the path to icu/source/test/testdata/ */
1615 const 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
1635 char *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
1677 const char* IntlTest::fgDataDir = NULL;
1678
1679 /* returns the path to icu/source/data */
1680 const 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  */
1750 UnicodeString CharsToUnicodeString(const char* chars){
1751     return UnicodeString(chars, -1, US_INV).unescape();
1752 }
1753
1754 UnicodeString 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
1762 static 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  */
1773 float 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  */
1798 float 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  */
1807 IntlTest::icu_rand::icu_rand(uint32_t seed) {
1808     seed = seed % 2147483647UL;
1809     if (seed == 0) {
1810         seed = 1;
1811     }
1812     fLast = seed;
1813 }
1814
1815 IntlTest::icu_rand::~icu_rand() {}
1816
1817 void IntlTest::icu_rand::seed(uint32_t seed) {
1818     if (seed == 0) {
1819         seed = 1;
1820     }
1821     fLast = seed;
1822 }
1823
1824 uint32_t IntlTest::icu_rand::operator() () {
1825     fLast = ((uint64_t)fLast * 48271UL) % 2147483647UL;
1826     return fLast;
1827 }
1828
1829 uint32_t IntlTest::icu_rand::getSeed() {
1830     return (uint32_t) fLast;
1831 }
1832
1833
1834
1835 static inline UChar toHex(int32_t i) {
1836     return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1837 }
1838
1839 static 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
1858 UBool 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
1884 UBool 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
1893 UBool 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
1910 UBool 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
1934 UBool 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
1951 UBool 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
1968 UBool 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
1985 UBool 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
2003 UBool 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
2021 UBool 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
2046 static char ASSERT_BUF[256];
2047
2048 static 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
2056 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
2057     return assertTrue(extractToAssertBuf(message), condition, quiet);
2058 }
2059
2060 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
2061     return assertFalse(extractToAssertBuf(message), condition, quiet);
2062 }
2063
2064 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
2065     return assertSuccess(extractToAssertBuf(message), ec);
2066 }
2067
2068 UBool 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
2075 UBool IntlTest::assertEquals(const UnicodeString& message,
2076                              const char* expected,
2077                              const char* actual) {
2078     return assertEquals(extractToAssertBuf(message), expected, actual);
2079 }
2080 UBool IntlTest::assertEquals(const UnicodeString& message,
2081                              UBool expected,
2082                              UBool actual) {
2083     return assertEquals(extractToAssertBuf(message), expected, actual);
2084 }
2085 UBool IntlTest::assertEquals(const UnicodeString& message,
2086                              int32_t expected,
2087                              int32_t actual) {
2088     return assertEquals(extractToAssertBuf(message), expected, actual);
2089 }
2090 UBool 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
2097 UBool IntlTest::assertEquals(const UnicodeString& message,
2098                              const Formattable& expected,
2099                              const Formattable& actual) {
2100     return assertEquals(extractToAssertBuf(message), expected, actual);
2101 }
2102 #endif
2103
2104 void IntlTest::setProperty(const char* propline) {
2105     if (numProps < kMaxProps) {
2106         proplines[numProps] = propline;
2107     }
2108     numProps++;
2109 }
2110
2111 const 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  */