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