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