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