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