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