1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2014, 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 testoutfp = caller->testoutfp;
565 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
566 numProps = caller->numProps;
567 for (int32_t i = 0; i < numProps; i++) {
568 proplines[i] = caller->proplines[i];
569 }
570 }
571 }
572
callTest(IntlTest & testToBeCalled,char * par)573 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
574 {
575 execCount--; // correct a previously assumed test-exec, as this only calls a subtest
576 testToBeCalled.setCaller( this );
577 strcpy(testToBeCalled.basePath, this->basePath );
578 UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath );
579 strcpy(testToBeCalled.basePath, this->basePath ); // reset it.
580 return result;
581 }
582
setPath(char * pathVal)583 void IntlTest::setPath( char* pathVal )
584 {
585 this->testPath = pathVal;
586 }
587
setVerbose(UBool verboseVal)588 UBool IntlTest::setVerbose( UBool verboseVal )
589 {
590 UBool rval = this->verbose;
591 this->verbose = verboseVal;
592 return rval;
593 }
594
setNotime(UBool no_time)595 UBool IntlTest::setNotime( UBool no_time )
596 {
597 UBool rval = this->no_time;
598 this->no_time = no_time;
599 return rval;
600 }
601
setWarnOnMissingData(UBool warn_on_missing_dataVal)602 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
603 {
604 UBool rval = this->warn_on_missing_data;
605 this->warn_on_missing_data = warn_on_missing_dataVal;
606 return rval;
607 }
608
setNoErrMsg(UBool no_err_msgVal)609 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
610 {
611 UBool rval = this->no_err_msg;
612 this->no_err_msg = no_err_msgVal;
613 return rval;
614 }
615
setQuick(UBool quickVal)616 UBool IntlTest::setQuick( UBool quickVal )
617 {
618 UBool rval = this->quick;
619 this->quick = quickVal;
620 return rval;
621 }
622
setLeaks(UBool leaksVal)623 UBool IntlTest::setLeaks( UBool leaksVal )
624 {
625 UBool rval = this->leaks;
626 this->leaks = leaksVal;
627 return rval;
628 }
629
setThreadCount(int32_t count)630 int32_t IntlTest::setThreadCount( int32_t count )
631 {
632 int32_t rval = this->threadCount;
633 this->threadCount = count;
634 return rval;
635 }
636
getErrors(void)637 int32_t IntlTest::getErrors( void )
638 {
639 return errorCount;
640 }
641
getDataErrors(void)642 int32_t IntlTest::getDataErrors( void )
643 {
644 return dataErrorCount;
645 }
646
runTest(char * name,char * par,char * baseName)647 UBool IntlTest::runTest( char* name, char* par, char *baseName )
648 {
649 UBool rval;
650 char* pos = NULL;
651
652 char* baseNameBuffer = NULL;
653
654 if(baseName == NULL) {
655 baseNameBuffer = (char*)malloc(1024);
656 baseName=baseNameBuffer;
657 strcpy(baseName, "/");
658 }
659
660 if (name)
661 pos = strchr( name, delim ); // check if name contains path (by looking for '/')
662 if (pos) {
663 testPath = pos+1; // store subpath for calling subtest
664 *pos = 0; // split into two strings
665 }else{
666 testPath = NULL;
667 }
668
669 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
670 rval = runTestLoop( NULL, par, baseName );
671
672 }else if (strcmp( name, "LIST" ) == 0) {
673 this->usage();
674 rval = TRUE;
675
676 }else{
677 rval = runTestLoop( name, par, baseName );
678 }
679
680 if (pos)
681 *pos = delim; // restore original value at pos
682 if(baseNameBuffer!=NULL) {
683 free(baseNameBuffer);
684 }
685 return rval;
686 }
687
688 // call individual tests, to be overriden to call implementations
runIndexedTest(int32_t,UBool,const char * &,char *)689 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
690 {
691 // to be overriden by a method like:
692 /*
693 switch (index) {
694 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
695 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
696 default: name = ""; break;
697 }
698 */
699 this->errln("*** runIndexedTest needs to be overriden! ***");
700 }
701
702
runTestLoop(char * testname,char * par,char * baseName)703 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
704 {
705 int32_t index = 0;
706 const char* name;
707 UBool run_this_test;
708 int32_t lastErrorCount;
709 UBool rval = FALSE;
710 UBool lastTestFailed;
711
712 if(baseName == NULL) {
713 printf("ERROR: baseName can't be null.\n");
714 return FALSE;
715 } else {
716 if ((char *)this->basePath != baseName) {
717 strcpy(this->basePath, baseName);
718 }
719 }
720
721 char * saveBaseLoc = baseName+strlen(baseName);
722
723 IntlTest* saveTest = gTest;
724 gTest = this;
725 do {
726 this->runIndexedTest( index, FALSE, name, par );
727 if (strcmp(name,"skip") == 0) {
728 run_this_test = FALSE;
729 } else {
730 if (!name || (name[0] == 0))
731 break;
732 if (!testname) {
733 run_this_test = TRUE;
734 }else{
735 run_this_test = (UBool) (strcmp( name, testname ) == 0);
736 }
737 }
738 if (run_this_test) {
739 lastErrorCount = errorCount;
740 execCount++;
741 char msg[256];
742 sprintf(msg, "%s {", name);
743 LL_message(msg, TRUE);
744 UDate timeStart = uprv_getRawUTCtime();
745 strcpy(saveBaseLoc,name);
746 strcat(saveBaseLoc,"/");
747
748 strcpy(currName, name); // set
749 this->runIndexedTest( index, TRUE, name, par );
750 currName[0]=0; // reset
751
752 UDate timeStop = uprv_getRawUTCtime();
753 rval = TRUE; // at least one test has been called
754 char secs[256];
755 if(!no_time) {
756 sprintf(secs, "%f", (timeStop-timeStart)/1000.0);
757 } else {
758 secs[0]=0;
759 }
760
761
762 strcpy(saveBaseLoc,name);
763
764
765 ctest_xml_testcase(baseName, name, secs, (lastErrorCount!=errorCount)?"err":NULL);
766
767
768 saveBaseLoc[0]=0; /* reset path */
769
770 if (lastErrorCount == errorCount) {
771 sprintf( msg, " } OK: %s ", name );
772 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
773 lastTestFailed = FALSE;
774 }else{
775 sprintf(msg, " } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
776 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
777
778 for(int i=0;i<LL_indentlevel;i++) {
779 errorList += " ";
780 }
781 errorList += name;
782 errorList += "\n";
783 lastTestFailed = TRUE;
784 }
785 LL_indentlevel -= 3;
786 if (lastTestFailed) {
787 LL_message( "", TRUE);
788 }
789 LL_message( msg, TRUE);
790 if (lastTestFailed) {
791 LL_message( "", TRUE);
792 }
793 LL_indentlevel += 3;
794 }
795 index++;
796 }while(name);
797
798 *saveBaseLoc = 0;
799
800 gTest = saveTest;
801 return rval;
802 }
803
804
805 /**
806 * Adds given string to the log if we are in verbose mode.
807 */
log(const UnicodeString & message)808 void IntlTest::log( const UnicodeString &message )
809 {
810 if( verbose ) {
811 LL_message( message, FALSE );
812 }
813 }
814
815 /**
816 * Adds given string to the log if we are in verbose mode. Adds a new line to
817 * the given message.
818 */
logln(const UnicodeString & message)819 void IntlTest::logln( const UnicodeString &message )
820 {
821 if( verbose ) {
822 LL_message( message, TRUE );
823 }
824 }
825
logln(void)826 void IntlTest::logln( void )
827 {
828 if( verbose ) {
829 LL_message( "", TRUE );
830 }
831 }
832
833 /**
834 * Unconditionally adds given string to the log.
835 */
info(const UnicodeString & message)836 void IntlTest::info( const UnicodeString &message )
837 {
838 LL_message( message, FALSE );
839 }
840
841 /**
842 * Unconditionally adds given string to the log. Adds a new line to
843 * the given message.
844 */
infoln(const UnicodeString & message)845 void IntlTest::infoln( const UnicodeString &message )
846 {
847 LL_message( message, TRUE );
848 }
849
infoln(void)850 void IntlTest::infoln( void )
851 {
852 LL_message( "", TRUE );
853 }
854
IncErrorCount(void)855 int32_t IntlTest::IncErrorCount( void )
856 {
857 errorCount++;
858 if (caller) caller->IncErrorCount();
859 return errorCount;
860 }
861
IncDataErrorCount(void)862 int32_t IntlTest::IncDataErrorCount( void )
863 {
864 dataErrorCount++;
865 if (caller) caller->IncDataErrorCount();
866 return dataErrorCount;
867 }
868
err()869 void IntlTest::err()
870 {
871 IncErrorCount();
872 }
873
err(const UnicodeString & message)874 void IntlTest::err( const UnicodeString &message )
875 {
876 IncErrorCount();
877 if (!no_err_msg) LL_message( message, FALSE );
878 }
879
errln(const UnicodeString & message)880 void IntlTest::errln( const UnicodeString &message )
881 {
882 IncErrorCount();
883 if (!no_err_msg) LL_message( message, TRUE );
884 }
885
dataerr(const UnicodeString & message)886 void IntlTest::dataerr( const UnicodeString &message )
887 {
888 IncDataErrorCount();
889
890 if (!warn_on_missing_data) {
891 IncErrorCount();
892 }
893
894 if (!no_err_msg) LL_message( message, FALSE );
895 }
896
dataerrln(const UnicodeString & message)897 void IntlTest::dataerrln( const UnicodeString &message )
898 {
899 int32_t errCount = IncDataErrorCount();
900 UnicodeString msg;
901 if (!warn_on_missing_data) {
902 IncErrorCount();
903 msg = message;
904 } else {
905 msg = UnicodeString("[DATA] " + message);
906 }
907
908 if (!no_err_msg) {
909 if ( errCount == 1) {
910 LL_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
911 } else {
912 LL_message( msg , TRUE );
913 }
914 }
915 }
916
errcheckln(UErrorCode status,const UnicodeString & message)917 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
918 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
919 dataerrln(message);
920 } else {
921 errln(message);
922 }
923 }
924
925 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)926 void IntlTest::log(const char *fmt, ...)
927 {
928 char buffer[4000];
929 va_list ap;
930
931 va_start(ap, fmt);
932 /* sprintf it just to make sure that the information is valid */
933 vsprintf(buffer, fmt, ap);
934 va_end(ap);
935 if( verbose ) {
936 log(UnicodeString(buffer, ""));
937 }
938 }
939
logln(const char * fmt,...)940 void IntlTest::logln(const char *fmt, ...)
941 {
942 char buffer[4000];
943 va_list ap;
944
945 va_start(ap, fmt);
946 /* sprintf it just to make sure that the information is valid */
947 vsprintf(buffer, fmt, ap);
948 va_end(ap);
949 if( verbose ) {
950 logln(UnicodeString(buffer, ""));
951 }
952 }
953
logKnownIssue(const char * ticket,const char * fmt,...)954 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...)
955 {
956 char buffer[4000];
957 va_list ap;
958
959 va_start(ap, fmt);
960 /* sprintf it just to make sure that the information is valid */
961 vsprintf(buffer, fmt, ap);
962 va_end(ap);
963 return logKnownIssue(ticket, UnicodeString(buffer, ""));
964 }
965
logKnownIssue(const char * ticket)966 UBool IntlTest::logKnownIssue(const char *ticket) {
967 return logKnownIssue(ticket, UnicodeString());
968 }
969
logKnownIssue(const char * ticket,const UnicodeString & msg)970 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) {
971 if(noKnownIssues) return FALSE;
972
973 char fullpath[2048];
974 strcpy(fullpath, basePath);
975 strcat(fullpath, currName);
976 UnicodeString msg2 =msg;
977 UBool firstForTicket, firstForWhere;
978 knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere);
979
980 msg2 = UNICODE_STRING_SIMPLE("(Known issue #") +
981 UnicodeString(ticket, -1, US_INV) + UNICODE_STRING_SIMPLE(") ") + msg;
982 if(firstForTicket || firstForWhere) {
983 infoln(msg2);
984 } else {
985 logln(msg2);
986 }
987
988 return TRUE;
989 }
990
991 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)992 void IntlTest::info(const char *fmt, ...)
993 {
994 char buffer[4000];
995 va_list ap;
996
997 va_start(ap, fmt);
998 /* sprintf it just to make sure that the information is valid */
999 vsprintf(buffer, fmt, ap);
1000 va_end(ap);
1001 info(UnicodeString(buffer, ""));
1002 }
1003
infoln(const char * fmt,...)1004 void IntlTest::infoln(const char *fmt, ...)
1005 {
1006 char buffer[4000];
1007 va_list ap;
1008
1009 va_start(ap, fmt);
1010 /* sprintf it just to make sure that the information is valid */
1011 vsprintf(buffer, fmt, ap);
1012 va_end(ap);
1013 infoln(UnicodeString(buffer, ""));
1014 }
1015
err(const char * fmt,...)1016 void IntlTest::err(const char *fmt, ...)
1017 {
1018 char buffer[4000];
1019 va_list ap;
1020
1021 va_start(ap, fmt);
1022 vsprintf(buffer, fmt, ap);
1023 va_end(ap);
1024 err(UnicodeString(buffer, ""));
1025 }
1026
errln(const char * fmt,...)1027 void IntlTest::errln(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 errln(UnicodeString(buffer, ""));
1036 }
1037
dataerrln(const char * fmt,...)1038 void IntlTest::dataerrln(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 dataerrln(UnicodeString(buffer, ""));
1047 }
1048
errcheckln(UErrorCode status,const char * fmt,...)1049 void IntlTest::errcheckln(UErrorCode status, 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
1058 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
1059 dataerrln(UnicodeString(buffer, ""));
1060 } else {
1061 errln(UnicodeString(buffer, ""));
1062 }
1063 }
1064
printErrors()1065 void IntlTest::printErrors()
1066 {
1067 IntlTest::LL_message(errorList, TRUE);
1068 }
1069
printKnownIssues()1070 UBool IntlTest::printKnownIssues()
1071 {
1072 if(knownList != NULL) {
1073 udbg_knownIssue_print(knownList);
1074 udbg_knownIssue_close(knownList);
1075 return TRUE;
1076 } else {
1077 return FALSE;
1078 }
1079 }
1080
LL_message(UnicodeString message,UBool newline)1081 void IntlTest::LL_message( UnicodeString message, UBool newline )
1082 {
1083 // string that starts with a LineFeed character and continues
1084 // with spaces according to the current indentation
1085 static const UChar indentUChars[] = {
1086 '\n',
1087 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
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 };
1098 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
1099
1100 char buffer[30000];
1101 int32_t length;
1102
1103 // stream out the indentation string first if necessary
1104 length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
1105 if (length > 0) {
1106 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1107 }
1108
1109 // replace each LineFeed by the indentation string
1110 message.findAndReplace(UnicodeString((UChar)'\n'), indent);
1111
1112 // stream out the message
1113 length = message.extract(0, message.length(), buffer, sizeof(buffer));
1114 if (length > 0) {
1115 length = length > 30000 ? 30000 : length;
1116 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1117 }
1118
1119 if (newline) {
1120 char newLine = '\n';
1121 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
1122 }
1123
1124 // A newline usually flushes the buffer, but
1125 // flush the message just in case of a core dump.
1126 fflush((FILE *)testoutfp);
1127 }
1128
1129 /**
1130 * Print a usage message for this test class.
1131 */
usage(void)1132 void IntlTest::usage( void )
1133 {
1134 UBool save_verbose = setVerbose( TRUE );
1135 logln("Test names:");
1136 logln("-----------");
1137
1138 int32_t index = 0;
1139 const char* name = NULL;
1140 do{
1141 this->runIndexedTest( index, FALSE, name );
1142 if (!name) break;
1143 logln(name);
1144 index++;
1145 }while (name && (name[0] != 0));
1146 setVerbose( save_verbose );
1147 }
1148
1149
1150 // memory leak reporting software will be able to take advantage of the testsuite
1151 // being run a second time local to a specific method in order to report only actual leaks
1152 UBool
run_phase2(char * name,char * par)1153 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1154 {
1155 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1156 strLeak->append(" for verifying purify filter");
1157 return this->runTest( name, par );
1158 }
1159
1160
1161 #if UCONFIG_NO_LEGACY_CONVERSION
1162 # define TRY_CNV_1 "iso-8859-1"
1163 # define TRY_CNV_2 "ibm-1208"
1164 #else
1165 # define TRY_CNV_1 "iso-8859-7"
1166 # define TRY_CNV_2 "sjis"
1167 #endif
1168
1169 int
main(int argc,char * argv[])1170 main(int argc, char* argv[])
1171 {
1172 UBool syntax = FALSE;
1173 UBool all = FALSE;
1174 UBool verbose = FALSE;
1175 UBool no_err_msg = FALSE;
1176 UBool no_time = FALSE;
1177 UBool quick = TRUE;
1178 UBool name = FALSE;
1179 UBool leaks = FALSE;
1180 UBool utf8 = FALSE;
1181 const char *summary_file = NULL;
1182 UBool warnOnMissingData = FALSE;
1183 UBool defaultDataFound = FALSE;
1184 int32_t threadCount = 1;
1185 UErrorCode errorCode = U_ZERO_ERROR;
1186 UConverter *cnv = NULL;
1187 const char *warnOrErr = "Failure";
1188 UDate startTime, endTime;
1189 int32_t diffTime;
1190 const char *props[IntlTest::kMaxProps];
1191 int32_t nProps = 0;
1192
1193 U_MAIN_INIT_ARGS(argc, argv);
1194
1195 startTime = uprv_getRawUTCtime();
1196
1197 for (int i = 1; i < argc; ++i) {
1198 if (argv[i][0] == '-') {
1199 const char* str = argv[i] + 1;
1200 if (strcmp("verbose", str) == 0 ||
1201 strcmp("v", str) == 0)
1202 verbose = TRUE;
1203 else if (strcmp("noerrormsg", str) == 0 ||
1204 strcmp("n", str) == 0)
1205 no_err_msg = TRUE;
1206 else if (strcmp("exhaustive", str) == 0 ||
1207 strcmp("e", str) == 0)
1208 quick = FALSE;
1209 else if (strcmp("all", str) == 0 ||
1210 strcmp("a", str) == 0)
1211 all = TRUE;
1212 else if (strcmp("utf-8", str) == 0 ||
1213 strcmp("u", str) == 0)
1214 utf8 = TRUE;
1215 else if (strcmp("noknownissues", str) == 0 ||
1216 strcmp("K", str) == 0)
1217 noKnownIssues = TRUE;
1218 else if (strcmp("leaks", str) == 0 ||
1219 strcmp("l", str) == 0)
1220 leaks = TRUE;
1221 else if (strcmp("notime", str) == 0 ||
1222 strcmp("T", str) == 0)
1223 no_time = TRUE;
1224 else if (strncmp("E", str, 1) == 0)
1225 summary_file = str+1;
1226 else if (strcmp("x", str)==0) {
1227 if(++i>=argc) {
1228 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1229 syntax = TRUE;
1230 }
1231 if(ctest_xml_setFileName(argv[i])) { /* set the name */
1232 return 1; /* error */
1233 }
1234 } else if (strcmp("w", str) == 0) {
1235 warnOnMissingData = TRUE;
1236 warnOrErr = "WARNING";
1237 }
1238 else if (strncmp("threads:", str, 8) == 0) {
1239 threadCount = atoi(str + 8);
1240 }
1241 else if (strncmp("prop:", str, 5) == 0) {
1242 if (nProps < IntlTest::kMaxProps) {
1243 props[nProps] = str + 5;
1244 }
1245 nProps++;
1246 }
1247 else {
1248 syntax = TRUE;
1249 }
1250 }else{
1251 name = TRUE;
1252 }
1253 }
1254
1255 if (!all && !name) {
1256 all = TRUE;
1257 } else if (all && name) {
1258 syntax = TRUE;
1259 }
1260
1261 if (syntax) {
1262 fprintf(stdout,
1263 "### Syntax:\n"
1264 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1265 "### \n"
1266 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1267 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<propery>=<value>, \n"
1268 "### notime (T), \n"
1269 "### threads:<threadCount> (Mulithreading must first be \n"
1270 "### enabled otherwise this will be ignored. \n"
1271 "### The default thread count is 1.),\n"
1272 "### (Specify either -all (shortcut -a) or a test name). \n"
1273 "### -all will run all of the tests.\n"
1274 "### \n"
1275 "### To get a list of the test names type: intltest LIST \n"
1276 "### To run just the utility tests type: intltest utility \n"
1277 "### \n"
1278 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1279 "### For example to list the utility tests type: intltest utility/LIST \n"
1280 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1281 "### \n"
1282 "### A parameter can be specified for a test by appending '@' and the value \n"
1283 "### to the testname. \n\n");
1284 return 1;
1285 }
1286
1287 if (nProps > IntlTest::kMaxProps) {
1288 fprintf(stdout, "### Too many properties. Exiting.\n");
1289 }
1290
1291 MajorTestLevel major;
1292 major.setVerbose( verbose );
1293 major.setNoErrMsg( no_err_msg );
1294 major.setQuick( quick );
1295 major.setLeaks( leaks );
1296 major.setThreadCount( threadCount );
1297 major.setWarnOnMissingData( warnOnMissingData );
1298 major.setNotime (no_time);
1299 for (int32_t i = 0; i < nProps; i++) {
1300 major.setProperty(props[i]);
1301 }
1302
1303
1304 fprintf(stdout, "-----------------------------------------------\n");
1305 fprintf(stdout, " IntlTest (C++) Test Suite for \n");
1306 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION);
1307
1308
1309 {
1310 const char *charsetFamily = "Unknown";
1311 int32_t voidSize = (int32_t)sizeof(void*);
1312 int32_t bits = voidSize * 8;
1313 if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1314 charsetFamily="ASCII";
1315 } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1316 charsetFamily="EBCDIC";
1317 }
1318 fprintf(stdout,
1319 " Bits: %d, Byte order: %s, Chars: %s\n",
1320 bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1321 charsetFamily);
1322 }
1323 fprintf(stdout, "-----------------------------------------------\n");
1324 fprintf(stdout, " Options: \n");
1325 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off"));
1326 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off"));
1327 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off"));
1328 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off"));
1329 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off"));
1330 fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off"));
1331 fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off"));
1332 fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off"));
1333 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1334 #if (ICU_USE_THREADS==0)
1335 fprintf(stdout, " Threads : Disabled\n");
1336 #else
1337 fprintf(stdout, " Threads : %d\n", threadCount);
1338 #endif
1339 for (int32_t i = 0; i < nProps; i++) {
1340 fprintf(stdout, " Custom property (prop:) : %s\n", props[i]);
1341 }
1342 fprintf(stdout, "-----------------------------------------------\n");
1343
1344 if(utf8) {
1345 ucnv_setDefaultName("utf-8");
1346 }
1347 /* Check whether ICU will initialize without forcing the build data directory into
1348 * the ICU_DATA path. Success here means either the data dll contains data, or that
1349 * this test program was run with ICU_DATA set externally. Failure of this check
1350 * is normal when ICU data is not packaged into a shared library.
1351 *
1352 * Whether or not this test succeeds, we want to cleanup and reinitialize
1353 * with a data path so that data loading from individual files can be tested.
1354 */
1355 u_init(&errorCode);
1356 if (U_FAILURE(errorCode)) {
1357 fprintf(stderr,
1358 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1359 defaultDataFound = FALSE;
1360 }
1361 else {
1362 defaultDataFound = TRUE;
1363 }
1364 u_cleanup();
1365 if(utf8) {
1366 ucnv_setDefaultName("utf-8");
1367 }
1368 errorCode = U_ZERO_ERROR;
1369
1370 /* Initialize ICU */
1371 if (!defaultDataFound) {
1372 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1373 }
1374 u_init(&errorCode);
1375 if (U_FAILURE(errorCode)) {
1376 fprintf(stderr,
1377 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1378 "*** Check the ICU_DATA environment variable and \n"
1379 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1380 if(warnOnMissingData == 0) {
1381 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1382 u_cleanup();
1383 return 1;
1384 }
1385 }
1386
1387 // initial check for the default converter
1388 errorCode = U_ZERO_ERROR;
1389 cnv = ucnv_open(0, &errorCode);
1390 if(cnv != 0) {
1391 // ok
1392 ucnv_close(cnv);
1393 } else {
1394 fprintf(stdout,
1395 "*** %s! The default converter [%s] cannot be opened.\n"
1396 "*** Check the ICU_DATA environment variable and\n"
1397 "*** check that the data files are present.\n",
1398 warnOrErr, ucnv_getDefaultName());
1399 if(!warnOnMissingData) {
1400 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1401 return 1;
1402 }
1403 }
1404
1405 // try more data
1406 cnv = ucnv_open(TRY_CNV_2, &errorCode);
1407 if(cnv != 0) {
1408 // ok
1409 ucnv_close(cnv);
1410 } else {
1411 fprintf(stdout,
1412 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1413 "*** Check the ICU_DATA environment variable and \n"
1414 "*** check that the data files are present.\n", warnOrErr);
1415 if(!warnOnMissingData) {
1416 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1417 return 1;
1418 }
1419 }
1420
1421 UResourceBundle *rb = ures_open(0, "en", &errorCode);
1422 ures_close(rb);
1423 if(U_FAILURE(errorCode)) {
1424 fprintf(stdout,
1425 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1426 "*** Check the ICU_DATA environment variable and \n"
1427 "*** check that the data files are present.\n", warnOrErr);
1428 if(!warnOnMissingData) {
1429 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1430 return 1;
1431 }
1432 }
1433
1434 Locale originalLocale; // Save the default locale for comparison later on.
1435
1436 if(ctest_xml_init("intltest"))
1437 return 1;
1438
1439
1440 /* TODO: Add option to call u_cleanup and rerun tests. */
1441 if (all) {
1442 major.runTest();
1443 if (leaks) {
1444 major.run_phase2( NULL, NULL );
1445 }
1446 }else{
1447 for (int i = 1; i < argc; ++i) {
1448 if (argv[i][0] != '-') {
1449 char* name = argv[i];
1450 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1451
1452 char baseName[1024];
1453 sprintf(baseName, "/%s/", name);
1454
1455 char* parameter = strchr( name, '@' );
1456 if (parameter) {
1457 *parameter = 0;
1458 parameter += 1;
1459 }
1460 execCount = 0;
1461 UBool res = major.runTest( name, parameter, baseName );
1462 if (leaks && res) {
1463 major.run_phase2( name, parameter );
1464 }
1465 if (!res || (execCount <= 0)) {
1466 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1467 }
1468 } else if(!strcmp(argv[i],"-x")) {
1469 i++;
1470 }
1471 }
1472 }
1473
1474
1475 #if !UCONFIG_NO_FORMATTING
1476 CalendarTimeZoneTest::cleanup();
1477 #endif
1478
1479 free(_testDataPath);
1480 _testDataPath = 0;
1481
1482 Locale lastDefaultLocale;
1483 if (originalLocale != lastDefaultLocale) {
1484 major.errln("FAILURE: A test changed the default locale without resetting it.");
1485 }
1486
1487 fprintf(stdout, "\n--------------------------------------\n");
1488 if( major.printKnownIssues() ) {
1489 fprintf(stdout, " To run suppressed tests, use the -K option. \n");
1490 }
1491 if (major.getErrors() == 0) {
1492 /* Call it twice to make sure that the defaults were reset. */
1493 /* Call it before the OK message to verify proper cleanup. */
1494 u_cleanup();
1495 u_cleanup();
1496
1497 fprintf(stdout, "OK: All tests passed without error.\n");
1498
1499 if (major.getDataErrors() != 0) {
1500 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1501 }
1502 }else{
1503 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1504 major.printErrors();
1505
1506 if(summary_file != NULL) {
1507 FILE *summf = fopen(summary_file, "w");
1508 if( summf != NULL) {
1509 char buf[10000];
1510 int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf));
1511 fwrite(buf, sizeof(*buf), length, (FILE*)summf);
1512 fclose(summf);
1513 }
1514 }
1515
1516
1517 if (major.getDataErrors() != 0) {
1518 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1519 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1520 "\tthe '-w' option to turn these errors into warnings.\n");
1521 }
1522
1523 /* Call afterwards to display errors. */
1524 u_cleanup();
1525 }
1526
1527 fprintf(stdout, "--------------------------------------\n");
1528
1529 if (execCount <= 0) {
1530 fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1531 }
1532 if(!no_time) {
1533 endTime = uprv_getRawUTCtime();
1534 diffTime = (int32_t)(endTime - startTime);
1535 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1536 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1537 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1538 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1539 (int)(diffTime%U_MILLIS_PER_SECOND));
1540 }
1541
1542 if(ctest_xml_fini())
1543 return 1;
1544
1545 return major.getErrors();
1546 }
1547
loadTestData(UErrorCode & err)1548 const char* IntlTest::loadTestData(UErrorCode& err){
1549 if( _testDataPath == NULL){
1550 const char* directory=NULL;
1551 UResourceBundle* test =NULL;
1552 char* tdpath=NULL;
1553 const char* tdrelativepath;
1554
1555 #if defined (U_TOPBUILDDIR)
1556 tdrelativepath = "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1557 directory = U_TOPBUILDDIR;
1558 #else
1559 tdrelativepath = ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1560 directory = pathToDataDirectory();
1561 #endif
1562
1563 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1564
1565
1566 /* u_getDataDirectory shoul return \source\data ... set the
1567 * directory to ..\source\data\..\test\testdata\out\testdata
1568 */
1569 strcpy(tdpath, directory);
1570 strcat(tdpath, tdrelativepath);
1571 strcat(tdpath,"testdata");
1572
1573 test=ures_open(tdpath, "testtypes", &err);
1574
1575 if(U_FAILURE(err)){
1576 err = U_FILE_ACCESS_ERROR;
1577 it_dataerrln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1578 return "";
1579 }
1580 ures_close(test);
1581 _testDataPath = tdpath;
1582 return _testDataPath;
1583 }
1584 return _testDataPath;
1585 }
1586
getTestDataPath(UErrorCode & err)1587 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1588 return loadTestData(err);
1589 }
1590
1591 /* Returns the path to icu/source/test/testdata/ */
getSourceTestData(UErrorCode &)1592 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1593 const char *srcDataDir = NULL;
1594 #ifdef U_TOPSRCDIR
1595 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1596 #else
1597 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1598 FILE *f = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING "rbbitst.txt", "r");
1599 if (f) {
1600 /* We're in icu/source/test/intltest/ */
1601 fclose(f);
1602 }
1603 else {
1604 /* We're in icu/source/test/intltest/Platform/(Debug|Release) */
1605 srcDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1606 "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
1607 }
1608 #endif
1609 return srcDataDir;
1610 }
1611
getUnidataPath(char path[])1612 char *IntlTest::getUnidataPath(char path[]) {
1613 const int kUnicodeDataTxtLength = 15; // strlen("UnicodeData.txt")
1614
1615 // Look inside ICU_DATA first.
1616 strcpy(path, pathToDataDirectory());
1617 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1618 FILE *f = fopen(path, "r");
1619 if(f != NULL) {
1620 fclose(f);
1621 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1622 return path;
1623 }
1624
1625 // As a fallback, try to guess where the source data was located
1626 // at the time ICU was built, and look there.
1627 # ifdef U_TOPSRCDIR
1628 strcpy(path, U_TOPSRCDIR U_FILE_SEP_STRING "data");
1629 # else
1630 UErrorCode errorCode = U_ZERO_ERROR;
1631 const char *testDataPath = loadTestData(errorCode);
1632 if(U_FAILURE(errorCode)) {
1633 it_errln(UnicodeString(
1634 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1635 u_errorName(errorCode));
1636 return NULL;
1637 }
1638 strcpy(path, testDataPath);
1639 strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1640 U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1641 U_FILE_SEP_STRING "data");
1642 # endif
1643 strcat(path, U_FILE_SEP_STRING);
1644 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1645 f = fopen(path, "r");
1646 if(f != NULL) {
1647 fclose(f);
1648 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1649 return path;
1650 }
1651 return NULL;
1652 }
1653
1654 const char* IntlTest::fgDataDir = NULL;
1655
1656 /* returns the path to icu/source/data */
pathToDataDirectory()1657 const char * IntlTest::pathToDataDirectory()
1658 {
1659
1660 if(fgDataDir != NULL) {
1661 return fgDataDir;
1662 }
1663
1664 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1665 // to point to the top of the build hierarchy, which may or
1666 // may not be the same as the source directory, depending on
1667 // the configure options used. At any rate,
1668 // set the data path to the built data from this directory.
1669 // The value is complete with quotes, so it can be used
1670 // as-is as a string constant.
1671 */
1672 #if defined (U_TOPSRCDIR)
1673 {
1674 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1675 }
1676 #else
1677
1678 /* On Windows, the file name obtained from __FILE__ includes a full path.
1679 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1680 * Change to "wherever\icu\source\data"
1681 */
1682 {
1683 static char p[sizeof(__FILE__) + 10];
1684 char *pBackSlash;
1685 int i;
1686
1687 strcpy(p, __FILE__);
1688 /* We want to back over three '\' chars. */
1689 /* Only Windows should end up here, so looking for '\' is safe. */
1690 for (i=1; i<=3; i++) {
1691 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1692 if (pBackSlash != NULL) {
1693 *pBackSlash = 0; /* Truncate the string at the '\' */
1694 }
1695 }
1696
1697 if (pBackSlash != NULL) {
1698 /* We found and truncated three names from the path.
1699 * Now append "source\data" and set the environment
1700 */
1701 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1702 fgDataDir = p;
1703 }
1704 else {
1705 /* __FILE__ on MSVC7 does not contain the directory */
1706 FILE *file = fopen(".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1707 if (file) {
1708 fclose(file);
1709 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1710 }
1711 else {
1712 fgDataDir = ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1713 }
1714 }
1715 }
1716 #endif
1717
1718 return fgDataDir;
1719
1720 }
1721
1722 /*
1723 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1724 * It converts an invariant-character string into a UnicodeString, with
1725 * unescaping \u sequences.
1726 */
CharsToUnicodeString(const char * chars)1727 UnicodeString CharsToUnicodeString(const char* chars){
1728 return UnicodeString(chars, -1, US_INV).unescape();
1729 }
1730
ctou(const char * chars)1731 UnicodeString ctou(const char* chars) {
1732 return CharsToUnicodeString(chars);
1733 }
1734
1735 #define RAND_M (714025)
1736 #define RAND_IA (1366)
1737 #define RAND_IC (150889)
1738
1739 static int32_t RAND_SEED;
1740
1741 /**
1742 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1743 * with care: Does not return all possible values; returns one of
1744 * 714,025 values, uniformly spaced. However, the period is
1745 * effectively infinite. See: Numerical Recipes, section 7.1.
1746 *
1747 * @param seedp pointer to seed. Set *seedp to any negative value
1748 * to restart the sequence.
1749 */
random(int32_t * seedp)1750 float IntlTest::random(int32_t* seedp) {
1751 static int32_t iy, ir[98];
1752 static UBool first=TRUE;
1753 int32_t j;
1754 if (*seedp < 0 || first) {
1755 first = FALSE;
1756 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1757 for (j=1;j<=97;++j) {
1758 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1759 ir[j]=(*seedp);
1760 }
1761 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1762 iy=(*seedp);
1763 }
1764 j=(int32_t)(1 + 97.0*iy/RAND_M);
1765 U_ASSERT(j>=1 && j<=97);
1766 iy=ir[j];
1767 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1768 ir[j]=(*seedp);
1769 return (float) iy/RAND_M;
1770 }
1771
1772 /**
1773 * Convenience method using a global seed.
1774 */
random()1775 float IntlTest::random() {
1776 return random(&RAND_SEED);
1777 }
1778
toHex(int32_t i)1779 static inline UChar toHex(int32_t i) {
1780 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1781 }
1782
escape(const UnicodeString & s,UnicodeString & result)1783 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1784 for (int32_t i=0; i<s.length(); ++i) {
1785 UChar c = s[i];
1786 if (c <= (UChar)0x7F) {
1787 result += c;
1788 } else {
1789 result += (UChar)0x5c;
1790 result += (UChar)0x75;
1791 result += toHex((c >> 12) & 0xF);
1792 result += toHex((c >> 8) & 0xF);
1793 result += toHex((c >> 4) & 0xF);
1794 result += toHex( c & 0xF);
1795 }
1796 }
1797 return result;
1798 }
1799
1800 #define VERBOSE_ASSERTIONS
1801
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1802 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1803 if (file != NULL) {
1804 if (!condition) {
1805 if (possibleDataError) {
1806 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1807 } else {
1808 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1809 }
1810 } else if (!quiet) {
1811 logln("%s:%d: Ok: %s", file, line, message);
1812 }
1813 } else {
1814 if (!condition) {
1815 if (possibleDataError) {
1816 dataerrln("FAIL: assertTrue() failed: %s", message);
1817 } else {
1818 errln("FAIL: assertTrue() failed: %s", message);
1819 }
1820 } else if (!quiet) {
1821 logln("Ok: %s", message);
1822 }
1823
1824 }
1825 return condition;
1826 }
1827
assertFalse(const char * message,UBool condition,UBool quiet)1828 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1829 if (condition) {
1830 errln("FAIL: assertFalse() failed: %s", message);
1831 } else if (!quiet) {
1832 logln("Ok: %s", message);
1833 }
1834 return !condition;
1835 }
1836
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1837 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1838 if( file==NULL ) {
1839 file = ""; // prevent failure if no file given
1840 }
1841 if (U_FAILURE(ec)) {
1842 if (possibleDataError) {
1843 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1844 } else {
1845 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1846 }
1847 return FALSE;
1848 } else {
1849 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1850 }
1851 return TRUE;
1852 }
1853
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1854 UBool IntlTest::assertEquals(const char* message,
1855 const UnicodeString& expected,
1856 const UnicodeString& actual,
1857 UBool possibleDataError) {
1858 if (expected != actual) {
1859 if (possibleDataError) {
1860 dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1861 prettify(actual) +
1862 "; expected " + prettify(expected));
1863 } else {
1864 errln((UnicodeString)"FAIL: " + message + "; got " +
1865 prettify(actual) +
1866 "; expected " + prettify(expected));
1867 }
1868 return FALSE;
1869 }
1870 #ifdef VERBOSE_ASSERTIONS
1871 else {
1872 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1873 }
1874 #endif
1875 return TRUE;
1876 }
1877
assertEquals(const char * message,const char * expected,const char * actual)1878 UBool IntlTest::assertEquals(const char* message,
1879 const char* expected,
1880 const char* actual) {
1881 if (uprv_strcmp(expected, actual) != 0) {
1882 errln((UnicodeString)"FAIL: " + message + "; got \"" +
1883 actual +
1884 "\"; expected \"" + expected + "\"");
1885 return FALSE;
1886 }
1887 #ifdef VERBOSE_ASSERTIONS
1888 else {
1889 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1890 }
1891 #endif
1892 return TRUE;
1893 }
1894
assertEquals(const char * message,int32_t expected,int32_t actual)1895 UBool IntlTest::assertEquals(const char* message,
1896 int32_t expected,
1897 int32_t actual) {
1898 if (expected != actual) {
1899 errln((UnicodeString)"FAIL: " + message + "; got " +
1900 actual + "=0x" + toHex(actual) +
1901 "; expected " + expected + "=0x" + toHex(expected));
1902 return FALSE;
1903 }
1904 #ifdef VERBOSE_ASSERTIONS
1905 else {
1906 logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual));
1907 }
1908 #endif
1909 return TRUE;
1910 }
1911
assertEquals(const char * message,int64_t expected,int64_t actual)1912 UBool IntlTest::assertEquals(const char* message,
1913 int64_t expected,
1914 int64_t actual) {
1915 if (expected != actual) {
1916 errln((UnicodeString)"FAIL: " + message + "; got int64 " +
1917 Int64ToUnicodeString(actual) +
1918 "; expected " + Int64ToUnicodeString(expected) );
1919 return FALSE;
1920 }
1921 #ifdef VERBOSE_ASSERTIONS
1922 else {
1923 logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual));
1924 }
1925 #endif
1926 return TRUE;
1927 }
1928
assertEquals(const char * message,UBool expected,UBool actual)1929 UBool IntlTest::assertEquals(const char* message,
1930 UBool expected,
1931 UBool actual) {
1932 if (expected != actual) {
1933 errln((UnicodeString)"FAIL: " + message + "; got " +
1934 toString(actual) +
1935 "; expected " + toString(expected));
1936 return FALSE;
1937 }
1938 #ifdef VERBOSE_ASSERTIONS
1939 else {
1940 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1941 }
1942 #endif
1943 return TRUE;
1944 }
1945
1946 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)1947 UBool IntlTest::assertEquals(const char* message,
1948 const Formattable& expected,
1949 const Formattable& actual,
1950 UBool possibleDataError) {
1951 if (expected != actual) {
1952 if (possibleDataError) {
1953 dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1954 toString(actual) +
1955 "; expected " + toString(expected));
1956 } else {
1957 errln((UnicodeString)"FAIL: " + message + "; got " +
1958 toString(actual) +
1959 "; expected " + toString(expected));
1960 }
1961 return FALSE;
1962 }
1963 #ifdef VERBOSE_ASSERTIONS
1964 else {
1965 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1966 }
1967 #endif
1968 return TRUE;
1969 }
1970 #endif
1971
1972 static char ASSERT_BUF[256];
1973
extractToAssertBuf(const UnicodeString & message)1974 static const char* extractToAssertBuf(const UnicodeString& message) {
1975 UnicodeString buf;
1976 escape(message, buf);
1977 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1978 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1979 return ASSERT_BUF;
1980 }
1981
assertTrue(const UnicodeString & message,UBool condition,UBool quiet)1982 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1983 return assertTrue(extractToAssertBuf(message), condition, quiet);
1984 }
1985
assertFalse(const UnicodeString & message,UBool condition,UBool quiet)1986 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1987 return assertFalse(extractToAssertBuf(message), condition, quiet);
1988 }
1989
assertSuccess(const UnicodeString & message,UErrorCode ec)1990 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1991 return assertSuccess(extractToAssertBuf(message), ec);
1992 }
1993
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1994 UBool IntlTest::assertEquals(const UnicodeString& message,
1995 const UnicodeString& expected,
1996 const UnicodeString& actual,
1997 UBool possibleDataError) {
1998 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
1999 }
2000
assertEquals(const UnicodeString & message,const char * expected,const char * actual)2001 UBool IntlTest::assertEquals(const UnicodeString& message,
2002 const char* expected,
2003 const char* actual) {
2004 return assertEquals(extractToAssertBuf(message), expected, actual);
2005 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)2006 UBool IntlTest::assertEquals(const UnicodeString& message,
2007 UBool expected,
2008 UBool actual) {
2009 return assertEquals(extractToAssertBuf(message), expected, actual);
2010 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)2011 UBool IntlTest::assertEquals(const UnicodeString& message,
2012 int32_t expected,
2013 int32_t actual) {
2014 return assertEquals(extractToAssertBuf(message), expected, actual);
2015 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)2016 UBool IntlTest::assertEquals(const UnicodeString& message,
2017 int64_t expected,
2018 int64_t actual) {
2019 return assertEquals(extractToAssertBuf(message), expected, actual);
2020 }
2021
2022 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)2023 UBool IntlTest::assertEquals(const UnicodeString& message,
2024 const Formattable& expected,
2025 const Formattable& actual) {
2026 return assertEquals(extractToAssertBuf(message), expected, actual);
2027 }
2028 #endif
2029
setProperty(const char * propline)2030 void IntlTest::setProperty(const char* propline) {
2031 if (numProps < kMaxProps) {
2032 proplines[numProps] = propline;
2033 }
2034 numProps++;
2035 }
2036
getProperty(const char * prop)2037 const char* IntlTest::getProperty(const char* prop) {
2038 const char* val = NULL;
2039 for (int32_t i = 0; i < numProps; i++) {
2040 int32_t plen = uprv_strlen(prop);
2041 if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
2042 && proplines[i][plen] == '='
2043 && uprv_strncmp(proplines[i], prop, plen) == 0) {
2044 val = &(proplines[i][plen+1]);
2045 break;
2046 }
2047 }
2048 return val;
2049 }
2050
2051 /*
2052 * Hey, Emacs, please set the following:
2053 *
2054 * Local Variables:
2055 * indent-tabs-mode: nil
2056 * End:
2057 *
2058 */
2059