]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/intltest.cpp
ICU-6.2.6.tar.gz
[apple/icu.git] / icuSources / test / intltest / intltest.cpp
CommitLineData
b75a7d8f
A
1/********************************************************************
2 * COPYRIGHT:
374ca955 3 * Copyright (c) 1997-2004, 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"
b75a7d8f
A
36
37#ifdef XP_MAC_CONSOLE
38#include <console.h>
39#include "Files.h"
40#endif
41
42
43static char* _testDataPath=NULL;
44
45// Static list of errors found
46static UnicodeString errorList;
47
48//-----------------------------------------------------------------------------
49//convenience classes to ease porting code that uses the Java
50//string-concatenation operator (moved from findword test by rtg)
51
52// [LIU] Just to get things working
53UnicodeString
54UCharToUnicodeString(UChar c)
55{ return UnicodeString(c); }
56
b75a7d8f
A
57// [rtg] Just to get things working
58UnicodeString
59operator+(const UnicodeString& left,
60 long num)
61{
62 char buffer[64]; // nos changed from 10 to 64
63 char danger = 'p'; // guard against overrunning the buffer (rtg)
64
65 sprintf(buffer, "%ld", num);
66 assert(danger == 'p');
67
68 return left + buffer;
69}
70
71UnicodeString
72operator+(const UnicodeString& left,
73 unsigned long num)
74{
75 char buffer[64]; // nos changed from 10 to 64
76 char danger = 'p'; // guard against overrunning the buffer (rtg)
77
78 sprintf(buffer, "%lu", num);
79 assert(danger == 'p');
80
81 return left + buffer;
82}
83
374ca955
A
84UnicodeString
85Int64ToUnicodeString(int64_t num)
86{
87 char buffer[64]; // nos changed from 10 to 64
88 char danger = 'p'; // guard against overrunning the buffer (rtg)
89
90#ifdef WIN32
91 sprintf(buffer, "%I64d", num);
92#else
93 sprintf(buffer, "%lld", num);
94#endif
95 assert(danger == 'p');
96
97 return buffer;
98}
99
b75a7d8f
A
100// [LIU] Just to get things working
101UnicodeString
102operator+(const UnicodeString& left,
103 double num)
104{
105 char buffer[64]; // was 32, made it arbitrarily bigger (rtg)
106 char danger = 'p'; // guard against overrunning the buffer (rtg)
107
374ca955
A
108 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
109 // 53*log(2)/log(10) = 15.95
110 // so there is no need to show more than 16 digits. [alan]
111
112 sprintf(buffer, "%.16g", num);
b75a7d8f
A
113 assert(danger == 'p');
114
115 return left + buffer;
116}
117
118#if !UCONFIG_NO_FORMATTING
119
120/**
374ca955 121 * Return a string display for for this, without surrounding braces.
b75a7d8f 122 */
374ca955 123UnicodeString _toString(const Formattable& f) {
b75a7d8f
A
124 UnicodeString s;
125 switch (f.getType()) {
126 case Formattable::kDate:
127 {
128 UErrorCode status = U_ZERO_ERROR;
129 SimpleDateFormat fmt(status);
130 if (U_SUCCESS(status)) {
131 FieldPosition pos;
132 fmt.format(f.getDate(), s, pos);
374ca955 133 s.insert(0, "Date:");
b75a7d8f 134 } else {
374ca955 135 s = UnicodeString("Error creating date format]");
b75a7d8f
A
136 }
137 }
138 break;
139 case Formattable::kDouble:
374ca955 140 s = UnicodeString("double:") + f.getDouble();
b75a7d8f
A
141 break;
142 case Formattable::kLong:
374ca955 143 s = UnicodeString("long:") + f.getLong();
b75a7d8f 144 break;
374ca955
A
145
146 case Formattable::kInt64:
147 s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64());
148 break;
149
b75a7d8f
A
150 case Formattable::kString:
151 f.getString(s);
374ca955 152 s.insert(0, "String:");
b75a7d8f
A
153 break;
154 case Formattable::kArray:
155 {
156 int32_t i, n;
157 const Formattable* array = f.getArray(n);
374ca955 158 s.insert(0, UnicodeString("Array:"));
b75a7d8f
A
159 UnicodeString delim(", ");
160 for (i=0; i<n; ++i) {
161 if (i > 0) {
162 s.append(delim);
163 }
374ca955 164 s = s + _toString(array[i]);
b75a7d8f 165 }
b75a7d8f
A
166 }
167 break;
374ca955
A
168 case Formattable::kObject:
169 if (f.getObject()->getDynamicClassID() ==
170 CurrencyAmount::getStaticClassID()) {
171 const CurrencyAmount& c = (const CurrencyAmount&) *f.getObject();
172 s = _toString(c.getNumber()) + " " + UnicodeString(c.getISOCurrency());
173 } else {
174 s = UnicodeString("Unknown UObject");
175 }
176 break;
177 default:
178 s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType();
179 break;
b75a7d8f
A
180 }
181 return s;
182}
183
374ca955
A
184/**
185 * Originally coded this as operator+, but that makes the expression
186 * + char* ambiguous. - liu
187 */
188UnicodeString toString(const Formattable& f) {
189 UnicodeString s((UChar)91/*[*/);
190 s.append(_toString(f));
191 s.append((UChar)0x5d/*]*/);
192 return s;
193}
194
b75a7d8f
A
195#endif
196
374ca955
A
197// useful when operator+ won't cooperate
198UnicodeString toString(int32_t n) {
199 return UnicodeString() + (long)n;
200}
201
b75a7d8f
A
202// stephen - cleaned up 05/05/99
203UnicodeString operator+(const UnicodeString& left, char num)
204{ return left + (long)num; }
205UnicodeString operator+(const UnicodeString& left, short num)
206{ return left + (long)num; }
207UnicodeString operator+(const UnicodeString& left, int num)
208{ return left + (long)num; }
209UnicodeString operator+(const UnicodeString& left, unsigned char num)
210{ return left + (unsigned long)num; }
211UnicodeString operator+(const UnicodeString& left, unsigned short num)
212{ return left + (unsigned long)num; }
213UnicodeString operator+(const UnicodeString& left, unsigned int num)
214{ return left + (unsigned long)num; }
215UnicodeString operator+(const UnicodeString& left, float num)
216{ return left + (double)num; }
217
218//------------------
219
220// Append a hex string to the target
221UnicodeString&
222IntlTest::appendHex(uint32_t number,
223 int32_t digits,
224 UnicodeString& target)
225{
226 static const UChar digitString[] = {
227 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
228 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
229 }; /* "0123456789ABCDEF" */
230
231 switch (digits)
232 {
233 case 8:
234 target += digitString[(number >> 28) & 0xF];
235 case 7:
236 target += digitString[(number >> 24) & 0xF];
237 case 6:
238 target += digitString[(number >> 20) & 0xF];
239 case 5:
240 target += digitString[(number >> 16) & 0xF];
241 case 4:
242 target += digitString[(number >> 12) & 0xF];
243 case 3:
244 target += digitString[(number >> 8) & 0xF];
245 case 2:
246 target += digitString[(number >> 4) & 0xF];
247 case 1:
248 target += digitString[(number >> 0) & 0xF];
249 break;
250 default:
251 target += "**";
252 }
253 return target;
254}
255
256// Replace nonprintable characters with unicode escapes
257UnicodeString&
258IntlTest::prettify(const UnicodeString &source,
259 UnicodeString &target)
260{
261 int32_t i;
262
263 target.remove();
264 target += "\"";
265
266 for (i = 0; i < source.length(); )
267 {
268 UChar32 ch = source.char32At(i);
269 i += UTF_CHAR_LENGTH(ch);
270
271 if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
272 {
273 if (ch <= 0xFFFF) {
274 target += "\\u";
275 appendHex(ch, 4, target);
276 } else {
277 target += "\\U";
278 appendHex(ch, 8, target);
279 }
280 }
281 else
282 {
283 target += ch;
284 }
285 }
286
287 target += "\"";
288
289 return target;
290}
291
292// Replace nonprintable characters with unicode escapes
293UnicodeString
294IntlTest::prettify(const UnicodeString &source, UBool parseBackslash)
295{
296 int32_t i;
297 UnicodeString target;
298 target.remove();
299 target += "\"";
300
301 for (i = 0; i < source.length();)
302 {
303 UChar32 ch = source.char32At(i);
304 i += UTF_CHAR_LENGTH(ch);
305
306 if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
307 {
308 if (parseBackslash) {
309 // If we are preceded by an odd number of backslashes,
310 // then this character has already been backslash escaped.
311 // Delete a backslash.
312 int32_t backslashCount = 0;
313 for (int32_t j=target.length()-1; j>=0; --j) {
314 if (target.charAt(j) == (UChar)92) {
315 ++backslashCount;
316 } else {
317 break;
318 }
319 }
320 if ((backslashCount % 2) == 1) {
321 target.truncate(target.length() - 1);
322 }
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#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) || defined(OS2)
344#define PREV_DIR ".."
345#else
346#define PREV_DIR "/../"
347#endif
348
349void
350IntlTest::pathnameInContext( char* fullname, int32_t maxsize, const char* relPath ) //nosmac
351{
352 const char* mainDir;
353 char sepChar;
354 const char inpSepChar = '|';
355
356 // So what's going on is that ICU_DATA during tests points to:
357 // ICU | source | data
358 //and we want ICU | source |
359 //
360 // We'll add | test | testdata
361 //
362 // So, just add a .. here - back up one level
363
364 mainDir = u_getDataDirectory();
365 sepChar = U_FILE_SEP_CHAR;
366 char sepString[] = U_FILE_SEP_STRING;
367
368#if defined(XP_MAC)
369 Str255 volName;
370 int16_t volNum;
371 OSErr err = GetVol( volName, &volNum );
372 if (err != noErr)
373 volName[0] = 0;
374 mainDir = (char*) &(volName[1]);
375 mainDir[volName[0]] = 0;
376#else
377 char mainDirBuffer[255];
378 if(mainDir!=NULL) {
379 strcpy(mainDirBuffer, mainDir);
380 strcat(mainDirBuffer, PREV_DIR);
381 } else {
382 mainDirBuffer[0]='\0';
383 }
384 mainDir=mainDirBuffer;
385#endif
386
387 if (relPath[0] == '|')
388 relPath++;
389 int32_t lenMainDir = strlen(mainDir);
390 int32_t lenRelPath = strlen(relPath);
391 if (maxsize < lenMainDir + lenRelPath + 2) {
392 fullname[0] = 0;
393 return;
394 }
395 strcpy(fullname, mainDir);
396 strcat(fullname, sepString);
397 strcat(fullname, relPath);
398 char* tmp = strchr(fullname, inpSepChar);
399 while (tmp) {
400 *tmp = sepChar;
401 tmp = strchr(tmp+1, inpSepChar);
402 }
403}
404
405/* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
406 * set, try to deduce the directory in which ICU was built,
407 * and set ICU_DATA to "icu/source/data" in that location.
408 * The intent is to allow the tests to have a good chance
409 * of running without requiring that the user manually set
410 * ICU_DATA. Common data isn't a problem, since it is
411 * picked up via a static (build time) reference, but the
412 * tests dynamically load some data.
413 */
414void IntlTest::setICU_DATA() {
415 const char *original_ICU_DATA = getenv("ICU_DATA");
416
417 if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) {
418 /* If the user set ICU_DATA, don't second-guess the person. */
419 return;
420 }
421
422 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
423 // to point to the top of the build hierarchy, which may or
424 // may not be the same as the source directory, depending on
425 // the configure options used. At any rate,
426 // set the data path to the built data from this directory.
374ca955 427 // The value is complete with quotes, so it can be used
b75a7d8f
A
428 // as-is as a string constant.
429
430#if defined (U_TOPBUILDDIR)
431 {
432 static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
433 u_setDataDirectory(env_string);
434 return;
435 }
436
437#else
438 // Use #else so we don't get compiler warnings due to the return above.
439
440 /* On Windows, the file name obtained from __FILE__ includes a full path.
441 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
442 * Change to "wherever\icu\source\data"
443 */
444 {
445 char p[sizeof(__FILE__) + 10];
446 char *pBackSlash;
447 int i;
448
449 strcpy(p, __FILE__);
450 /* We want to back over three '\' chars. */
451 /* Only Windows should end up here, so looking for '\' is safe. */
452 for (i=1; i<=3; i++) {
453 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
454 if (pBackSlash != NULL) {
455 *pBackSlash = 0; /* Truncate the string at the '\' */
456 }
457 }
458
459 if (pBackSlash != NULL) {
460 /* We found and truncated three names from the path.
461 * Now append "source\data" and set the environment
462 */
463 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
464 u_setDataDirectory(p); /* p is "ICU_DATA=wherever\icu\source\data" */
465 return;
466 }
467 else {
468 /* __FILE__ on MSVC7 does not contain the directory */
469 u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
470 return;
471 }
472 }
473#endif
474
475 /* No location for the data dir was identifiable.
476 * Add other fallbacks for the test data location here if the need arises
477 */
478}
479
480
481//--------------------------------------------------------------------------------------
482
483static const int32_t indentLevel_offset = 3;
484static const char delim = '/';
485
486IntlTest* IntlTest::gTest = NULL;
487
488static int32_t execCount = 0;
489
490void it_log( UnicodeString message )
491{
492 if (IntlTest::gTest)
493 IntlTest::gTest->log( message );
494}
495
496void it_logln( UnicodeString message )
497{
498 if (IntlTest::gTest)
499 IntlTest::gTest->logln( message );
500}
501
502void it_logln( void )
503{
504 if (IntlTest::gTest)
505 IntlTest::gTest->logln();
506}
507
508void it_info( UnicodeString message )
509{
510 if (IntlTest::gTest)
511 IntlTest::gTest->info( message );
512}
513
514void it_infoln( UnicodeString message )
515{
516 if (IntlTest::gTest)
517 IntlTest::gTest->infoln( message );
518}
519
520void it_infoln( void )
521{
522 if (IntlTest::gTest)
523 IntlTest::gTest->infoln();
524}
525
526void it_err()
527{
528 if (IntlTest::gTest)
529 IntlTest::gTest->err();
530}
531
532void it_err( UnicodeString message )
533{
534 if (IntlTest::gTest)
535 IntlTest::gTest->err( message );
536}
537
538void it_errln( UnicodeString message )
539{
540 if (IntlTest::gTest)
541 IntlTest::gTest->errln( message );
542}
543
b75a7d8f
A
544
545IntlTest::IntlTest()
546{
547 caller = NULL;
548 path = NULL;
549 LL_linestart = TRUE;
550 errorCount = 0;
551 verbose = FALSE;
552 no_err_msg = FALSE;
553 quick = FALSE;
554 leaks = FALSE;
555 testoutfp = stdout;
556 LL_indentlevel = indentLevel_offset;
557}
558
559void IntlTest::setCaller( IntlTest* callingTest )
560{
561 caller = callingTest;
562 if (caller) {
563 verbose = caller->verbose;
564 no_err_msg = caller->no_err_msg;
565 quick = caller->quick;
566 testoutfp = caller->testoutfp;
567 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
568 }
569}
570
571UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
572{
573 execCount--; // correct a previously assumed test-exec, as this only calls a subtest
574 testToBeCalled.setCaller( this );
575 return testToBeCalled.runTest( path, par );
576}
577
578void IntlTest::setPath( char* pathVal )
579{
580 this->path = pathVal;
581}
582
583UBool IntlTest::setVerbose( UBool verboseVal )
584{
585 UBool rval = this->verbose;
586 this->verbose = verboseVal;
587 return rval;
588}
589
590UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
591{
592 UBool rval = this->no_err_msg;
593 this->no_err_msg = no_err_msgVal;
594 return rval;
595}
596
597UBool IntlTest::setQuick( UBool quickVal )
598{
599 UBool rval = this->quick;
600 this->quick = quickVal;
601 return rval;
602}
603
604UBool IntlTest::setLeaks( UBool leaksVal )
605{
606 UBool rval = this->leaks;
607 this->leaks = leaksVal;
608 return rval;
609}
610
611int32_t IntlTest::getErrors( void )
612{
613 return errorCount;
614}
615
616UBool IntlTest::runTest( char* name, char* par )
617{
618 UBool rval;
619 char* pos = NULL;
620
621 if (name)
622 pos = strchr( name, delim ); // check if name contains path (by looking for '/')
623 if (pos) {
624 path = pos+1; // store subpath for calling subtest
625 *pos = 0; // split into two strings
626 }else{
627 path = NULL;
628 }
629
630 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
374ca955 631 rval = runTestLoop( NULL, par );
b75a7d8f
A
632
633 }else if (strcmp( name, "LIST" ) == 0) {
634 this->usage();
635 rval = TRUE;
636
637 }else{
638 rval = runTestLoop( name, par );
639 }
640
641 if (pos)
642 *pos = delim; // restore original value at pos
643 return rval;
644}
645
646// call individual tests, to be overriden to call implementations
647void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
648{
649 // to be overriden by a method like:
650 /*
651 switch (index) {
652 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
653 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
654 default: name = ""; break;
655 }
656 */
657 this->errln("*** runIndexedTest needs to be overriden! ***");
658 name = ""; exec = exec; index = index; par = par;
659}
660
661
662UBool IntlTest::runTestLoop( char* testname, char* par )
663{
664 int32_t index = 0;
665 const char* name;
666 UBool run_this_test;
667 int32_t lastErrorCount;
668 UBool rval = FALSE;
669 UBool lastTestFailed;
670
671 IntlTest* saveTest = gTest;
672 gTest = this;
673 do {
374ca955 674 this->runIndexedTest( index, FALSE, name, par );
b75a7d8f
A
675 if (!name || (name[0] == 0))
676 break;
677 if (!testname) {
678 run_this_test = TRUE;
679 }else{
680 run_this_test = (UBool) (strcmp( name, testname ) == 0);
681 }
682 if (run_this_test) {
683 lastErrorCount = errorCount;
684 execCount++;
685 this->runIndexedTest( index, TRUE, name, par );
686 rval = TRUE; // at least one test has been called
687 char msg[256];
688 if (lastErrorCount == errorCount) {
689 sprintf( msg, "---OK: %s", name );
690 lastTestFailed = FALSE;
691 }else{
692 sprintf(msg, "---ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
693
694 for(int i=0;i<LL_indentlevel;i++) {
695 errorList += " ";
696 }
697 errorList += name;
698 errorList += "\n";
699 lastTestFailed = TRUE;
700 }
701 LL_indentlevel -= 3;
702 if (lastTestFailed) {
703 LL_message( "", TRUE);
704 }
705 LL_message( msg, TRUE);
706 if (lastTestFailed) {
707 LL_message( "", TRUE);
708 }
709 LL_indentlevel += 3;
710 }
711 index++;
712 }while(name);
713
714 gTest = saveTest;
715 return rval;
716}
717
718
719/**
720* Adds given string to the log if we are in verbose mode.
721*/
722void IntlTest::log( const UnicodeString &message )
723{
724 if( verbose ) {
725 LL_message( message, FALSE );
726 }
727}
728
729/**
730* Adds given string to the log if we are in verbose mode. Adds a new line to
731* the given message.
732*/
733void IntlTest::logln( const UnicodeString &message )
734{
735 if( verbose ) {
736 LL_message( message, TRUE );
737 }
738}
739
740void IntlTest::logln( void )
741{
742 if( verbose ) {
743 LL_message( "", TRUE );
744 }
745}
746
747/**
748* Unconditionally adds given string to the log.
749*/
750void IntlTest::info( const UnicodeString &message )
751{
752 LL_message( message, FALSE );
753}
754
755/**
756* Unconditionally adds given string to the log. Adds a new line to
757* the given message.
758*/
759void IntlTest::infoln( const UnicodeString &message )
760{
761 LL_message( message, TRUE );
762}
763
764void IntlTest::infoln( void )
765{
766 LL_message( "", TRUE );
767}
768
769int32_t IntlTest::IncErrorCount( void )
770{
771 errorCount++;
772 if (caller) caller->IncErrorCount();
773 return errorCount;
774}
775
776void IntlTest::err() {
777 IncErrorCount();
778}
779
780void IntlTest::err( const UnicodeString &message )
781{
782 IncErrorCount();
783 if (!no_err_msg) LL_message( message, FALSE );
784}
785
786void IntlTest::errln( const UnicodeString &message )
787{
788 IncErrorCount();
789 if (!no_err_msg) LL_message( message, TRUE );
790}
791
792/* convenience functions that include sprintf formatting */
793void IntlTest::log(const char *fmt, ...)
794{
374ca955 795 char buffer[4000];
b75a7d8f
A
796 va_list ap;
797
798 va_start(ap, fmt);
799 /* sprintf it just to make sure that the information is valid */
800 vsprintf(buffer, fmt, ap);
801 va_end(ap);
802 if( verbose ) {
803 log(UnicodeString(buffer, ""));
804 }
805}
806
807void IntlTest::logln(const char *fmt, ...)
808{
374ca955 809 char buffer[4000];
b75a7d8f
A
810 va_list ap;
811
812 va_start(ap, fmt);
813 /* sprintf it just to make sure that the information is valid */
814 vsprintf(buffer, fmt, ap);
815 va_end(ap);
816 if( verbose ) {
817 logln(UnicodeString(buffer, ""));
818 }
819}
820
821/* convenience functions that include sprintf formatting */
822void IntlTest::info(const char *fmt, ...)
823{
374ca955 824 char buffer[4000];
b75a7d8f
A
825 va_list ap;
826
827 va_start(ap, fmt);
828 /* sprintf it just to make sure that the information is valid */
829 vsprintf(buffer, fmt, ap);
830 va_end(ap);
831 info(UnicodeString(buffer, ""));
832}
833
834void IntlTest::infoln(const char *fmt, ...)
835{
374ca955 836 char buffer[4000];
b75a7d8f
A
837 va_list ap;
838
839 va_start(ap, fmt);
840 /* sprintf it just to make sure that the information is valid */
841 vsprintf(buffer, fmt, ap);
842 va_end(ap);
843 infoln(UnicodeString(buffer, ""));
844}
845
846void IntlTest::err(const char *fmt, ...)
847{
374ca955 848 char buffer[4000];
b75a7d8f
A
849 va_list ap;
850
851 va_start(ap, fmt);
852 vsprintf(buffer, fmt, ap);
853 va_end(ap);
854 err(UnicodeString(buffer, ""));
855}
856
857void IntlTest::errln(const char *fmt, ...)
858{
374ca955 859 char buffer[4000];
b75a7d8f
A
860 va_list ap;
861
862 va_start(ap, fmt);
863 vsprintf(buffer, fmt, ap);
864 va_end(ap);
865 errln(UnicodeString(buffer, ""));
866}
867
868void IntlTest::printErrors()
869{
870 IntlTest::LL_message(errorList, TRUE);
871}
872
873void IntlTest::LL_message( UnicodeString message, UBool newline )
874{
875 // string that starts with a LineFeed character and continues
876 // with spaces according to the current indentation
877 static const UChar indentUChars[] = {
878 '\n',
879 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
880 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
881 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
882 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
883 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
884 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
885 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
886 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
887 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
888 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
889 };
890 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
891
892 char buffer[10000];
893 int32_t length;
894
895 // stream out the indentation string first if necessary
896 length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
897 if (length > 0) {
374ca955 898 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
b75a7d8f
A
899 }
900
901 // replace each LineFeed by the indentation string
902 message.findAndReplace(UnicodeString((UChar)'\n'), indent);
903
904 // stream out the message
905 length = message.extract(0, message.length(), buffer, sizeof(buffer));
906 if (length > 0) {
374ca955 907 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
b75a7d8f
A
908 }
909
910 if (newline) {
911 char newLine = '\n';
374ca955 912 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
b75a7d8f
A
913 }
914
915 // A newline usually flushes the buffer, but
916 // flush the message just in case of a core dump.
374ca955 917 fflush((FILE *)testoutfp);
b75a7d8f
A
918}
919
920/**
921* Print a usage message for this test class.
922*/
923void IntlTest::usage( void )
924{
925 UBool save_verbose = setVerbose( TRUE );
926 logln("Test names:");
927 logln("-----------");
928
929 int32_t index = 0;
930 const char* name = NULL;
931 do{
932 this->runIndexedTest( index, FALSE, name );
933 if (!name) break;
934 logln(name);
935 index++;
936 }while (name && (name[0] != 0));
937 setVerbose( save_verbose );
938}
939
940
941// memory leak reporting software will be able to take advantage of the testsuite
942// being run a second time local to a specific method in order to report only actual leaks
943UBool
944IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
945{
946 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
947 strLeak->append(" for verifying purify filter");
948 return this->runTest( name, par );
949}
950
951
952#if UCONFIG_NO_LEGACY_CONVERSION
953# define TRY_CNV_1 "iso-8859-1"
954# define TRY_CNV_2 "ibm-1208"
955#else
956# define TRY_CNV_1 "iso-8859-7"
957# define TRY_CNV_2 "sjis"
958#endif
959
960int
961main(int argc, char* argv[])
962{
963 UBool syntax = FALSE;
374ca955 964 UBool all = FALSE;
b75a7d8f
A
965 UBool verbose = FALSE;
966 UBool no_err_msg = FALSE;
967 UBool quick = TRUE;
968 UBool name = FALSE;
969 UBool leaks = FALSE;
970 UBool warnOnMissingData = FALSE;
971 UErrorCode errorCode = U_ZERO_ERROR;
972 UConverter *cnv = NULL;
374ca955 973 const char *warnOrErr = "Failure";
b75a7d8f
A
974
975#ifdef XP_MAC_CONSOLE
976 argc = ccommand( &argv );
977#endif
978
374ca955
A
979 /* Initialize ICU */
980 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
981 u_init(&errorCode);
982 if (U_FAILURE(errorCode)) {
b75a7d8f 983 fprintf(stderr,
374ca955
A
984 "#### %s: u_init() failed, error is \"%s\".\n"
985 "#### Most commonly indicates that the ICU data is not accesible.\n"
986 "#### Check setting of ICU_DATA, or check that ICU data library is available\n"
987 "#### ICU_DATA is currently set to \"%s\"\n", argv[0], u_errorName(errorCode), u_getDataDirectory());
988 u_cleanup();
989 return 1;
b75a7d8f 990 }
374ca955 991
b75a7d8f
A
992
993 for (int i = 1; i < argc; ++i) {
994 if (argv[i][0] == '-') {
995 const char* str = argv[i] + 1;
374ca955
A
996 if (strcmp("verbose", str) == 0 ||
997 strcmp("v", str) == 0)
b75a7d8f 998 verbose = TRUE;
374ca955
A
999 else if (strcmp("noerrormsg", str) == 0 ||
1000 strcmp("n", str) == 0)
b75a7d8f 1001 no_err_msg = TRUE;
374ca955
A
1002 else if (strcmp("exhaustive", str) == 0 ||
1003 strcmp("e", str) == 0)
b75a7d8f 1004 quick = FALSE;
374ca955
A
1005 else if (strcmp("all", str) == 0 ||
1006 strcmp("a", str) == 0)
b75a7d8f 1007 all = TRUE;
374ca955
A
1008 else if (strcmp("leaks", str) == 0 ||
1009 strcmp("l", str) == 0)
b75a7d8f
A
1010 leaks = TRUE;
1011 else if (strcmp("w", str) == 0) {
1012 warnOnMissingData = TRUE;
1013 warnOrErr = "WARNING";
374ca955
A
1014 }
1015 else {
b75a7d8f
A
1016 syntax = TRUE;
1017 }
1018 }else{
1019 name = TRUE;
b75a7d8f
A
1020 }
1021 }
1022
374ca955
A
1023 if (!all && !name) {
1024 all = TRUE;
1025 } else if (all && name) {
1026 syntax = TRUE;
1027 }
b75a7d8f
A
1028
1029 if (syntax) {
1030 fprintf(stdout,
1031 "### Syntax:\n"
1032 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1033 "### where options are: verbose (v), all (a), noerrormsg (n), \n"
374ca955 1034 "### exhaustive (e), leaks (l)"
b75a7d8f
A
1035 "### (Specify either -all (shortcut -a) or a test name). \n"
1036 "### -all will run all of the tests.\n"
1037 "### \n"
1038 "### To get a list of the test names type: intltest LIST \n"
1039 "### To run just the utility tests type: intltest utility \n"
1040 "### \n"
1041 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1042 "### For example to list the utility tests type: intltest utility/LIST \n"
1043 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1044 "### \n"
1045 "### A parameter can be specified for a test by appending '@' and the value \n"
1046 "### to the testname. \n\n");
1047 return 1;
1048 }
1049
1050 UBool all_tests_exist = TRUE;
1051 MajorTestLevel major;
1052 major.setVerbose( verbose );
1053 major.setNoErrMsg( no_err_msg );
1054 major.setQuick( quick );
1055 major.setLeaks( leaks );
1056 fprintf(stdout, "-----------------------------------------------\n");
1057 fprintf(stdout, " IntlTest (C++) Test Suite for \n");
1058 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION);
1059 fprintf(stdout, "-----------------------------------------------\n");
1060 fprintf(stdout, " Options: \n");
1061 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off"));
1062 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off"));
1063 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off"));
1064 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off"));
1065 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off"));
1066 fprintf(stdout, "-----------------------------------------------\n");
1067
1068 // Check that u_init() works
1069 errorCode = U_ZERO_ERROR;
1070 u_init(&errorCode);
1071 if (U_FAILURE(errorCode)) {
1072 fprintf(stdout,
1073 "*** u_init() failed with error code = %s\n"
1074 "*** Check the ICU_DATA environment variable and\n"
1075 "*** check that the data files are present.\n",
1076 u_errorName(errorCode));
1077 if(!warnOnMissingData) {
374ca955 1078 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
b75a7d8f
A
1079 return 1;
1080 }
1081 }
1082
1083
1084 // initial check for the default converter
1085 errorCode = U_ZERO_ERROR;
1086 cnv = ucnv_open(0, &errorCode);
1087 if(cnv != 0) {
1088 // ok
1089 ucnv_close(cnv);
1090 } else {
1091 fprintf(stdout,
1092 "*** %s! The default converter [%s] cannot be opened.\n"
1093 "*** Check the ICU_DATA environment variable and\n"
1094 "*** check that the data files are present.\n",
1095 warnOrErr, ucnv_getDefaultName());
1096 if(!warnOnMissingData) {
374ca955 1097 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
b75a7d8f
A
1098 return 1;
1099 }
1100 }
1101
1102 // try more data
1103 cnv = ucnv_open(TRY_CNV_2, &errorCode);
1104 if(cnv != 0) {
1105 // ok
1106 ucnv_close(cnv);
1107 } else {
1108 fprintf(stdout,
1109 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1110 "*** Check the ICU_DATA environment variable and \n"
1111 "*** check that the data files are present.\n", warnOrErr);
1112 if(!warnOnMissingData) {
374ca955 1113 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
b75a7d8f
A
1114 return 1;
1115 }
1116 }
1117
1118 UResourceBundle *rb = ures_open(0, "en", &errorCode);
1119 ures_close(rb);
1120 if(U_FAILURE(errorCode)) {
1121 fprintf(stdout,
1122 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1123 "*** Check the ICU_DATA environment variable and \n"
1124 "*** check that the data files are present.\n", warnOrErr);
1125 if(!warnOnMissingData) {
374ca955 1126 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
b75a7d8f
A
1127 return 1;
1128 }
1129 }
1130
1131 /* TODO: Add option to call u_cleanup and rerun tests. */
1132 if (all) {
1133 major.runTest();
1134 if (leaks) {
1135 major.run_phase2( NULL, NULL );
1136 }
1137 }else{
1138 for (int i = 1; i < argc; ++i) {
1139 if (argv[i][0] != '-') {
1140 char* name = argv[i];
1141 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1142 char* parameter = strchr( name, '@' );
1143 if (parameter) {
1144 *parameter = 0;
1145 parameter += 1;
1146 }
1147 execCount = 0;
1148 UBool res = major.runTest( name, parameter );
1149 if (leaks && res) {
1150 major.run_phase2( name, parameter );
1151 }
1152 if (!res || (execCount <= 0)) {
1153 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1154 all_tests_exist = FALSE;
1155 }
1156 }
1157 }
1158 }
1159
1160#if !UCONFIG_NO_FORMATTING
1161 CalendarTimeZoneTest::cleanup();
1162#endif
1163
1164 free(_testDataPath);
1165 _testDataPath = 0;
1166
1167 fprintf(stdout, "\n--------------------------------------\n");
1168 if (major.getErrors() == 0) {
1169 /* Call it twice to make sure that the defaults were reset. */
1170 /* Call it before the OK message to verify proper cleanup. */
1171 u_cleanup();
1172 u_cleanup();
1173
1174 fprintf(stdout, "OK: All tests passed without error.\n");
1175 }else{
1176 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1177 major.printErrors();
1178
1179 /* Call afterwards to display errors. */
1180 u_cleanup();
1181 }
1182
1183 fprintf(stdout, "--------------------------------------\n");
1184
b75a7d8f
A
1185 if (execCount <= 0) {
1186 fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1187 }
1188 return major.getErrors();
1189}
1190
1191const char* IntlTest::loadTestData(UErrorCode& err){
1192 if( _testDataPath == NULL){
1193 const char* directory=NULL;
1194 UResourceBundle* test =NULL;
1195 char* tdpath=NULL;
1196 const char* tdrelativepath;
1197
1198#if defined (U_TOPBUILDDIR)
1199 tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1200 directory = U_TOPBUILDDIR;
1201#else
1202 tdrelativepath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1203 directory = pathToDataDirectory();
1204#endif
1205
1206 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1207
1208
1209 /* u_getDataDirectory shoul return \source\data ... set the
1210 * directory to ..\source\data\..\test\testdata\out\testdata
1211 */
374ca955 1212 strcpy(tdpath, directory);
b75a7d8f
A
1213 strcat(tdpath, tdrelativepath);
1214 strcat(tdpath,"testdata");
1215
1216 test=ures_open(tdpath, "testtypes", &err);
1217
1218 if(U_FAILURE(err)){
1219 err = U_FILE_ACCESS_ERROR;
1220 it_errln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1221 return "";
1222 }
1223 ures_close(test);
1224 _testDataPath = tdpath;
1225 return _testDataPath;
1226 }
1227 return _testDataPath;
1228}
1229
374ca955
A
1230const char* IntlTest::getTestDataPath(UErrorCode& err) {
1231 return loadTestData(err);
1232}
1233
1234/* Returns the path to icu/source/test/testdata/ */
1235const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1236 const char *srcDataDir = NULL;
1237#ifdef U_TOPSRCDIR
1238 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1239#else
1240 srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1241 FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
1242 if (f) {
1243 /* We're in icu/source/test/intltest/ */
1244 fclose(f);
1245 }
1246 else {
1247 /* We're in icu/source/test/intltest/(Debug|Release) */
1248 srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1249 }
1250#endif
1251 return srcDataDir;
1252}
1253
b75a7d8f
A
1254const char* IntlTest::fgDataDir = NULL;
1255
1256/* returns the path to icu/source/data */
1257const char * IntlTest::pathToDataDirectory()
1258{
1259
1260 if(fgDataDir != NULL) {
1261 return fgDataDir;
1262 }
1263
1264 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1265 // to point to the top of the build hierarchy, which may or
1266 // may not be the same as the source directory, depending on
1267 // the configure options used. At any rate,
1268 // set the data path to the built data from this directory.
1269 // The value is complete with quotes, so it can be used
1270 // as-is as a string constant.
1271 */
1272#if defined (U_TOPSRCDIR)
1273 {
1274 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1275 }
1276#else
1277
1278 /* On Windows, the file name obtained from __FILE__ includes a full path.
1279 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1280 * Change to "wherever\icu\source\data"
1281 */
1282 {
1283 static char p[sizeof(__FILE__) + 10];
1284 char *pBackSlash;
1285 int i;
1286
1287 strcpy(p, __FILE__);
1288 /* We want to back over three '\' chars. */
1289 /* Only Windows should end up here, so looking for '\' is safe. */
1290 for (i=1; i<=3; i++) {
1291 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1292 if (pBackSlash != NULL) {
1293 *pBackSlash = 0; /* Truncate the string at the '\' */
1294 }
1295 }
1296
1297 if (pBackSlash != NULL) {
1298 /* We found and truncated three names from the path.
1299 * Now append "source\data" and set the environment
1300 */
1301 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1302 fgDataDir = p;
1303 }
1304 else {
1305 /* __FILE__ on MSVC7 does not contain the directory */
374ca955
A
1306 FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1307 if (file) {
1308 fclose(file);
1309 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1310 }
1311 else {
1312 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1313 }
b75a7d8f
A
1314 }
1315 }
1316#endif
1317
1318 return fgDataDir;
1319
1320}
1321
1322/*
1323 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1324 * It converts a character string into a UnicodeString, with
1325 * unescaping \u sequences.
1326 */
1327UnicodeString CharsToUnicodeString(const char* chars)
1328{
1329 UnicodeString str(chars, ""); // Invariant conversion
1330 return str.unescape();
1331}
1332
374ca955
A
1333UnicodeString ctou(const char* chars) {
1334 return CharsToUnicodeString(chars);
1335}
1336
1337#define RAND_M (714025)
1338#define RAND_IA (1366)
1339#define RAND_IC (150889)
1340
1341static int32_t RAND_SEED;
1342
1343/**
1344 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1345 * with care: Does not return all possible values; returns one of
1346 * 714,025 values, uniformly spaced. However, the period is
1347 * effectively infinite. See: Numerical Recipes, section 7.1.
1348 *
1349 * @param seedp pointer to seed. Set *seedp to any negative value
1350 * to restart the sequence.
1351 */
1352float IntlTest::random(int32_t* seedp) {
1353 static int32_t iy, ir[98];
1354 static UBool first=TRUE;
1355 int32_t j;
1356 if (*seedp < 0 || first) {
1357 first = FALSE;
1358 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1359 for (j=1;j<=97;++j) {
1360 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1361 ir[j]=(*seedp);
1362 }
1363 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1364 iy=(*seedp);
1365 }
1366 j=(int32_t)(1 + 97.0*iy/RAND_M);
1367 U_ASSERT(j>=1 && j<=97);
1368 iy=ir[j];
1369 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1370 ir[j]=(*seedp);
1371 return (float) iy/RAND_M;
1372}
1373
1374/**
1375 * Convenience method using a global seed.
1376 */
1377float IntlTest::random() {
1378 return random(&RAND_SEED);
1379}
1380
1381static inline UChar toHex(int32_t i) {
1382 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1383}
1384
1385static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1386 for (int32_t i=0; i<s.length(); ++i) {
1387 UChar c = s[i];
1388 if (c <= (UChar)0x7F) {
1389 result += c;
1390 } else {
1391 result += (UChar)0x5c;
1392 result += (UChar)0x75;
1393 result += toHex((c >> 12) & 0xF);
1394 result += toHex((c >> 8) & 0xF);
1395 result += toHex((c >> 4) & 0xF);
1396 result += toHex( c & 0xF);
1397 }
1398 }
1399 return result;
1400}
1401
1402#define VERBOSE_ASSERTIONS
1403
1404UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet) {
1405 if (!condition) {
1406 errln("FAIL: assertTrue() failed: %s", message);
1407 } else if (!quiet) {
1408 logln("Ok: %s", message);
1409 }
1410 return condition;
1411}
1412
1413UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1414 if (condition) {
1415 errln("FAIL: assertFalse() failed: %s", message);
1416 } else if (!quiet) {
1417 logln("Ok: %s", message);
1418 }
1419 return !condition;
1420}
1421
1422UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) {
1423 if (U_FAILURE(ec)) {
1424 errln("FAIL: %s (%s)", message, u_errorName(ec));
1425 return FALSE;
1426 }
1427 return TRUE;
1428}
1429
1430UBool IntlTest::assertEquals(const char* message,
1431 const UnicodeString& expected,
1432 const UnicodeString& actual) {
1433 if (expected != actual) {
1434 errln((UnicodeString)"FAIL: " + message + "; got " +
1435 prettify(actual) +
1436 "; expected " + prettify(expected));
1437 return FALSE;
1438 }
1439#ifdef VERBOSE_ASSERTIONS
1440 else {
1441 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1442 }
1443#endif
1444 return TRUE;
1445}
1446
1447UBool IntlTest::assertEquals(const char* message,
1448 const char* expected,
1449 const char* actual) {
1450 if (uprv_strcmp(expected, actual) != 0) {
1451 errln((UnicodeString)"FAIL: " + message + "; got \"" +
1452 actual +
1453 "\"; expected \"" + expected + "\"");
1454 return FALSE;
1455 }
1456#ifdef VERBOSE_ASSERTIONS
1457 else {
1458 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1459 }
1460#endif
1461 return TRUE;
1462}
1463
1464#if !UCONFIG_NO_FORMATTING
1465UBool IntlTest::assertEquals(const char* message,
1466 const Formattable& expected,
1467 const Formattable& actual) {
1468 if (expected != actual) {
1469 errln((UnicodeString)"FAIL: " + message + "; got " +
1470 toString(actual) +
1471 "; expected " + toString(expected));
1472 return FALSE;
1473 }
1474#ifdef VERBOSE_ASSERTIONS
1475 else {
1476 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1477 }
1478#endif
1479 return TRUE;
1480}
1481#endif
1482
1483static char ASSERT_BUF[256];
1484
1485static const char* extractToAssertBuf(const UnicodeString& message) {
1486 UnicodeString buf;
1487 escape(message, buf);
1488 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1489 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1490 return ASSERT_BUF;
1491}
1492
1493UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1494 return assertTrue(extractToAssertBuf(message), condition, quiet);
1495}
1496
1497UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1498 return assertFalse(extractToAssertBuf(message), condition, quiet);
1499}
1500
1501UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1502 return assertSuccess(extractToAssertBuf(message), ec);
1503}
1504
1505UBool IntlTest::assertEquals(const UnicodeString& message,
1506 const UnicodeString& expected,
1507 const UnicodeString& actual) {
1508 return assertEquals(extractToAssertBuf(message), expected, actual);
1509}
1510
1511UBool IntlTest::assertEquals(const UnicodeString& message,
1512 const char* expected,
1513 const char* actual) {
1514 return assertEquals(extractToAssertBuf(message), expected, actual);
1515}
1516//--------------------------------------------------------------------
1517// Time bomb - allows temporary behavior that expires at a given
1518// release
1519//--------------------------------------------------------------------
1520
1521UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) {
1522 UVersionInfo v;
1523 u_getVersion(v);
1524 return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0);
1525}
1526
1527#if !UCONFIG_NO_FORMATTING
1528UBool IntlTest::assertEquals(const UnicodeString& message,
1529 const Formattable& expected,
1530 const Formattable& actual) {
1531 return assertEquals(extractToAssertBuf(message), expected, actual);
1532}
1533#endif
1534
b75a7d8f
A
1535/*
1536 * Hey, Emacs, please set the following:
1537 *
1538 * Local Variables:
1539 * indent-tabs-mode: nil
1540 * End:
1541 *
1542 */