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