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