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 #include <iostream>
24
25 #include "unicode/ctest.h" // for str_timeDelta
26 #include "unicode/curramt.h"
27 #include "unicode/locid.h"
28 #include "unicode/putil.h"
29 #include "unicode/smpdtfmt.h"
30 #include "unicode/timezone.h"
31 #include "unicode/uclean.h"
32 #include "unicode/ucnv.h"
33 #include "unicode/unistr.h"
34 #include "unicode/ures.h"
35 #include "unicode/utf16.h"
36
37 #include "intltest.h"
38
39 #include "caltztst.h"
40 #include "cmemory.h"
41 #include "cstring.h"
42 #include "itmajor.h"
43 #include "lstmbe.h"
44 #include "mutex.h"
45 #include "putilimp.h" // for uprv_getRawUTCtime()
46 #include "uassert.h"
47 #include "udbgutil.h"
48 #include "umutex.h"
49 #include "uoptions.h"
50 #include "number_decnum.h"
51
52 #ifdef XP_MAC_CONSOLE
53 #include <console.h>
54 #include "Files.h"
55 #endif
56
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 // Android-changed: Do not u_setDataDirectory because libicuuc.so initializes itself.
427 #if !defined(ANDROID_USE_ICU_REG)
428 u_setDataDirectory(ctest_dataOutDir());
429 #endif
430 }
431
432
433 //--------------------------------------------------------------------------------------
434
435 static const int32_t indentLevel_offset = 3;
436 static const char delim = '/';
437
438 IntlTest* IntlTest::gTest = NULL;
439
440 static int32_t execCount = 0;
441
it_log(UnicodeString message)442 void it_log( UnicodeString message )
443 {
444 if (IntlTest::gTest)
445 IntlTest::gTest->log( message );
446 }
447
it_logln(UnicodeString message)448 void it_logln( UnicodeString message )
449 {
450 if (IntlTest::gTest)
451 IntlTest::gTest->logln( message );
452 }
453
it_logln(void)454 void it_logln( void )
455 {
456 if (IntlTest::gTest)
457 IntlTest::gTest->logln();
458 }
459
it_info(UnicodeString message)460 void it_info( UnicodeString message )
461 {
462 if (IntlTest::gTest)
463 IntlTest::gTest->info( message );
464 }
465
it_infoln(UnicodeString message)466 void it_infoln( UnicodeString message )
467 {
468 if (IntlTest::gTest)
469 IntlTest::gTest->infoln( message );
470 }
471
it_infoln(void)472 void it_infoln( void )
473 {
474 if (IntlTest::gTest)
475 IntlTest::gTest->infoln();
476 }
477
it_err()478 void it_err()
479 {
480 if (IntlTest::gTest)
481 IntlTest::gTest->err();
482 }
483
it_err(UnicodeString message)484 void it_err( UnicodeString message )
485 {
486 if (IntlTest::gTest)
487 IntlTest::gTest->err( message );
488 }
489
it_errln(UnicodeString message)490 void it_errln( UnicodeString message )
491 {
492 if (IntlTest::gTest)
493 IntlTest::gTest->errln( message );
494 }
495
it_dataerr(UnicodeString message)496 void it_dataerr( UnicodeString message )
497 {
498 if (IntlTest::gTest)
499 IntlTest::gTest->dataerr( message );
500 }
501
it_dataerrln(UnicodeString message)502 void it_dataerrln( UnicodeString message )
503 {
504 if (IntlTest::gTest)
505 IntlTest::gTest->dataerrln( message );
506 }
507
IntlTest()508 IntlTest::IntlTest()
509 {
510 caller = NULL;
511 testPath = NULL;
512 LL_linestart = TRUE;
513 errorCount = 0;
514 dataErrorCount = 0;
515 verbose = FALSE;
516 no_time = FALSE;
517 no_err_msg = FALSE;
518 warn_on_missing_data = FALSE;
519 quick = FALSE;
520 leaks = FALSE;
521 threadCount = 12;
522 testoutfp = stdout;
523 LL_indentlevel = indentLevel_offset;
524 numProps = 0;
525 strcpy(basePath, "/");
526 currName[0]=0;
527 }
528
setCaller(IntlTest * callingTest)529 void IntlTest::setCaller( IntlTest* callingTest )
530 {
531 caller = callingTest;
532 if (caller) {
533 warn_on_missing_data = caller->warn_on_missing_data;
534 verbose = caller->verbose;
535 no_err_msg = caller->no_err_msg;
536 quick = caller->quick;
537 threadCount = caller->threadCount;
538 testoutfp = caller->testoutfp;
539 write_golden_data = caller->write_golden_data;
540 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
541 numProps = caller->numProps;
542 for (int32_t i = 0; i < numProps; i++) {
543 proplines[i] = caller->proplines[i];
544 }
545 }
546 }
547
callTest(IntlTest & testToBeCalled,char * par,const char * basename)548 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par, const char* basename)
549 {
550 execCount--; // correct a previously assumed test-exec, as this only calls a subtest
551 testToBeCalled.setCaller( this );
552 strcpy(testToBeCalled.basePath, basename);
553 strcat(testToBeCalled.basePath, this->basePath);
554 UBool result = testToBeCalled.runTest( testPath, par, testToBeCalled.basePath);
555 strcpy(testToBeCalled.basePath, basename); // reset it.
556 strcat(testToBeCalled.basePath, this->basePath);
557 return result;
558 }
559
setPath(char * pathVal)560 void IntlTest::setPath( char* pathVal )
561 {
562 this->testPath = pathVal;
563 }
564
setVerbose(UBool verboseVal)565 UBool IntlTest::setVerbose( UBool verboseVal )
566 {
567 UBool rval = this->verbose;
568 this->verbose = verboseVal;
569 return rval;
570 }
571
setNotime(UBool no_time)572 UBool IntlTest::setNotime( UBool no_time )
573 {
574 UBool rval = this->no_time;
575 this->no_time = no_time;
576 return rval;
577 }
578
setWarnOnMissingData(UBool warn_on_missing_dataVal)579 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
580 {
581 UBool rval = this->warn_on_missing_data;
582 this->warn_on_missing_data = warn_on_missing_dataVal;
583 return rval;
584 }
585
setWriteGoldenData(UBool write_golden_data)586 UBool IntlTest::setWriteGoldenData( UBool write_golden_data )
587 {
588 UBool rval = this->write_golden_data;
589 this->write_golden_data = write_golden_data;
590 return rval;
591 }
592
setNoErrMsg(UBool no_err_msgVal)593 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
594 {
595 UBool rval = this->no_err_msg;
596 this->no_err_msg = no_err_msgVal;
597 return rval;
598 }
599
setQuick(UBool quickVal)600 UBool IntlTest::setQuick( UBool quickVal )
601 {
602 UBool rval = this->quick;
603 this->quick = quickVal;
604 return rval;
605 }
606
setLeaks(UBool leaksVal)607 UBool IntlTest::setLeaks( UBool leaksVal )
608 {
609 UBool rval = this->leaks;
610 this->leaks = leaksVal;
611 return rval;
612 }
613
setThreadCount(int32_t count)614 int32_t IntlTest::setThreadCount( int32_t count )
615 {
616 int32_t rval = this->threadCount;
617 this->threadCount = count;
618 return rval;
619 }
620
getErrors(void)621 int32_t IntlTest::getErrors( void )
622 {
623 return errorCount;
624 }
625
getDataErrors(void)626 int32_t IntlTest::getDataErrors( void )
627 {
628 return dataErrorCount;
629 }
630
runTest(char * name,char * par,char * baseName)631 UBool IntlTest::runTest( char* name, char* par, char *baseName )
632 {
633 UBool rval;
634 char* pos = NULL;
635
636 char* baseNameBuffer = NULL;
637
638 if(baseName == NULL) {
639 baseNameBuffer = (char*)malloc(1024);
640 baseName=baseNameBuffer;
641 strcpy(baseName, "/");
642 }
643
644 if (name)
645 pos = strchr( name, delim ); // check if name contains path (by looking for '/')
646 if (pos) {
647 testPath = pos+1; // store subpath for calling subtest
648 *pos = 0; // split into two strings
649 }else{
650 testPath = NULL;
651 }
652
653 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
654 rval = runTestLoop( NULL, par, baseName );
655
656 }else if (strcmp( name, "LIST" ) == 0) {
657 this->usage();
658 rval = TRUE;
659
660 }else{
661 rval = runTestLoop( name, par, baseName );
662 }
663
664 if (pos)
665 *pos = delim; // restore original value at pos
666 if(baseNameBuffer!=NULL) {
667 free(baseNameBuffer);
668 }
669 return rval;
670 }
671
672 // call individual tests, to be overridden to call implementations
runIndexedTest(int32_t,UBool,const char * &,char *)673 void IntlTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
674 {
675 // to be overridden by a method like:
676 /*
677 switch (index) {
678 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
679 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
680 default: name = ""; break;
681 }
682 */
683 this->errln("*** runIndexedTest needs to be overridden! ***");
684 }
685
686
string_replace_all(std::string str,const std::string & from,const std::string & to)687 static std::string string_replace_all(std::string str, const std::string& from, const std::string& to) {
688 size_t start = 0;
689 while((start = str.find(from, start)) != std::string::npos) {
690 str.replace(start, from.length(), to);
691 start += to.length();
692 }
693 return str;
694 }
695
696 /**
697 * Escape some known characters, but the list is not perfect.
698 */
escape_xml_attribute(std::string str)699 static std::string escape_xml_attribute(std::string str) {
700 str = string_replace_all(str, "&", "&");
701 str = string_replace_all(str, "\"", """);
702 str = string_replace_all(str, "'", "'");
703 str = string_replace_all(str, "<", "<");
704 str = string_replace_all(str, ">", ">");
705 return str;
706 }
707
runTestLoop(char * testname,char * par,char * baseName)708 UBool IntlTest::runTestLoop( char* testname, char* par, char *baseName )
709 {
710 int32_t index = 0;
711 const char* name;
712 UBool run_this_test;
713 int32_t lastErrorCount;
714 UBool rval = FALSE;
715 UBool lastTestFailed;
716
717 if(baseName == NULL) {
718 printf("ERROR: baseName can't be null.\n");
719 return FALSE;
720 } else {
721 if ((char *)this->basePath != baseName) {
722 strcpy(this->basePath, baseName);
723 }
724 }
725
726 char * saveBaseLoc = baseName+strlen(baseName);
727
728 IntlTest* saveTest = gTest;
729 gTest = this;
730 do {
731 this->runIndexedTest( index, FALSE, name, par );
732 if (strcmp(name,"skip") == 0) {
733 run_this_test = FALSE;
734 } else {
735 if (!name || (name[0] == 0))
736 break;
737 if (!testname) {
738 run_this_test = TRUE;
739 }else{
740 run_this_test = (UBool) (strcmp( name, testname ) == 0);
741 }
742 }
743 if (run_this_test) {
744 lastErrorCount = errorCount;
745 execCount++;
746 char msg[256];
747 sprintf(msg, "%s {", name);
748 LL_message(msg, TRUE);
749 UDate timeStart = uprv_getRawUTCtime();
750 strcpy(saveBaseLoc,name);
751 strcat(saveBaseLoc,"/");
752
753 currErr = ""; // Reset the current error message
754 strcpy(currName, name); // set
755 this->runIndexedTest( index, TRUE, name, par );
756 currName[0]=0; // reset
757
758 UDate timeStop = uprv_getRawUTCtime();
759 rval = TRUE; // at least one test has been called
760 char secs[256];
761 if(!no_time) {
762 sprintf(secs, "%f", (timeStop-timeStart)/1000.0);
763 } else {
764 secs[0]=0;
765 }
766
767
768 strcpy(saveBaseLoc,name);
769
770
771 std::string err = currErr;
772 err = escape_xml_attribute(err);
773 ctest_xml_testcase(name, baseName, secs, (lastErrorCount!=errorCount)?err.c_str():NULL);
774
775
776 saveBaseLoc[0]=0; /* reset path */
777
778 if (lastErrorCount == errorCount) {
779 sprintf( msg, " } OK: %s ", name );
780 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
781 lastTestFailed = FALSE;
782 }else{
783 sprintf(msg, " } ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
784 if(!no_time) str_timeDelta(msg+strlen(msg),timeStop-timeStart);
785
786 for(int i=0;i<LL_indentlevel;i++) {
787 errorList += " ";
788 }
789 errorList += name;
790 errorList += "\n";
791 lastTestFailed = TRUE;
792 }
793 LL_indentlevel -= 3;
794 if (lastTestFailed) {
795 LL_message( "", TRUE);
796 }
797 LL_message( msg, TRUE);
798 if (lastTestFailed) {
799 LL_message( "", TRUE);
800 }
801 LL_indentlevel += 3;
802 }
803 index++;
804 }while(name);
805
806 *saveBaseLoc = 0;
807
808 gTest = saveTest;
809 return rval;
810 }
811
812
813 /**
814 * Adds given string to the log if we are in verbose mode.
815 */
log(const UnicodeString & message)816 void IntlTest::log( const UnicodeString &message )
817 {
818 if( verbose ) {
819 LL_message( message, FALSE );
820 }
821 }
822
823 /**
824 * Adds given string to the log if we are in verbose mode. Adds a new line to
825 * the given message.
826 */
logln(const UnicodeString & message)827 void IntlTest::logln( const UnicodeString &message )
828 {
829 if( verbose ) {
830 LL_message( message, TRUE );
831 }
832 }
833
logln(void)834 void IntlTest::logln( void )
835 {
836 if( verbose ) {
837 LL_message( "", TRUE );
838 }
839 }
840
841 /**
842 * Unconditionally adds given string to the log.
843 */
info(const UnicodeString & message)844 void IntlTest::info( const UnicodeString &message )
845 {
846 LL_message( message, FALSE );
847 }
848
849 /**
850 * Unconditionally adds given string to the log. Adds a new line to
851 * the given message.
852 */
infoln(const UnicodeString & message)853 void IntlTest::infoln( const UnicodeString &message )
854 {
855 LL_message( message, TRUE );
856 }
857
infoln(void)858 void IntlTest::infoln( void )
859 {
860 LL_message( "", TRUE );
861 }
862
IncErrorCount(void)863 int32_t IntlTest::IncErrorCount( void )
864 {
865 errorCount++;
866 if (caller) caller->IncErrorCount();
867 return errorCount;
868 }
869
IncDataErrorCount(void)870 int32_t IntlTest::IncDataErrorCount( void )
871 {
872 dataErrorCount++;
873 if (caller) caller->IncDataErrorCount();
874 return dataErrorCount;
875 }
876
err()877 void IntlTest::err()
878 {
879 IncErrorCount();
880 }
881
err(const UnicodeString & message)882 void IntlTest::err( const UnicodeString &message )
883 {
884 IncErrorCount();
885 if (!no_err_msg) LL_err_message( message, FALSE );
886 }
887
errln(const UnicodeString & message)888 void IntlTest::errln( const UnicodeString &message )
889 {
890 IncErrorCount();
891 if (!no_err_msg) LL_err_message( message, TRUE );
892 }
893
dataerr(const UnicodeString & message)894 void IntlTest::dataerr( const UnicodeString &message )
895 {
896 IncDataErrorCount();
897
898 if (!warn_on_missing_data) {
899 IncErrorCount();
900 }
901
902 if (!no_err_msg) LL_err_message( message, FALSE );
903 }
904
dataerrln(const UnicodeString & message)905 void IntlTest::dataerrln( const UnicodeString &message )
906 {
907 int32_t errCount = IncDataErrorCount();
908 UnicodeString msg;
909 if (!warn_on_missing_data) {
910 IncErrorCount();
911 msg = message;
912 } else {
913 msg = UnicodeString("[DATA] " + message);
914 }
915
916 if (!no_err_msg) {
917 if ( errCount == 1) {
918 LL_err_message( msg + " - (Are you missing data?)", TRUE ); // only show this message the first time
919 } else {
920 LL_err_message( msg , TRUE );
921 }
922 }
923 }
924
errcheckln(UErrorCode status,const UnicodeString & message)925 void IntlTest::errcheckln(UErrorCode status, const UnicodeString &message ) {
926 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
927 dataerrln(message);
928 } else {
929 errln(message);
930 }
931 }
932
933 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)934 void IntlTest::log(const char *fmt, ...)
935 {
936 char buffer[4000];
937 va_list ap;
938
939 va_start(ap, fmt);
940 /* sprintf it just to make sure that the information is valid */
941 vsprintf(buffer, fmt, ap);
942 va_end(ap);
943 if( verbose ) {
944 log(UnicodeString(buffer, (const char *)NULL));
945 }
946 }
947
logln(const char * fmt,...)948 void IntlTest::logln(const char *fmt, ...)
949 {
950 char buffer[4000];
951 va_list ap;
952
953 va_start(ap, fmt);
954 /* sprintf it just to make sure that the information is valid */
955 vsprintf(buffer, fmt, ap);
956 va_end(ap);
957 if( verbose ) {
958 logln(UnicodeString(buffer, (const char *)NULL));
959 }
960 }
961
logKnownIssue(const char * ticket,const char * fmt,...)962 UBool IntlTest::logKnownIssue(const char *ticket, const char *fmt, ...)
963 {
964 char buffer[4000];
965 va_list ap;
966
967 va_start(ap, fmt);
968 /* sprintf it just to make sure that the information is valid */
969 vsprintf(buffer, fmt, ap);
970 va_end(ap);
971 return logKnownIssue(ticket, UnicodeString(buffer, (const char *)NULL));
972 }
973
logKnownIssue(const char * ticket)974 UBool IntlTest::logKnownIssue(const char *ticket) {
975 return logKnownIssue(ticket, UnicodeString());
976 }
977
logKnownIssue(const char * ticket,const UnicodeString & msg)978 UBool IntlTest::logKnownIssue(const char *ticket, const UnicodeString &msg) {
979 if(noKnownIssues) return FALSE;
980
981 char fullpath[2048];
982 strcpy(fullpath, basePath);
983 strcat(fullpath, currName);
984 UnicodeString msg2 = msg;
985 UBool firstForTicket = TRUE, firstForWhere = TRUE;
986 knownList = udbg_knownIssue_openU(knownList, ticket, fullpath, msg2.getTerminatedBuffer(), &firstForTicket, &firstForWhere);
987
988 msg2 = UNICODE_STRING_SIMPLE("(Known issue ") +
989 UnicodeString(ticket, -1, US_INV) + UNICODE_STRING_SIMPLE(") ") + msg;
990 if(firstForTicket || firstForWhere) {
991 infoln(msg2);
992 } else {
993 logln(msg2);
994 }
995
996 return TRUE;
997 }
998
999 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)1000 void IntlTest::info(const char *fmt, ...)
1001 {
1002 char buffer[4000];
1003 va_list ap;
1004
1005 va_start(ap, fmt);
1006 /* sprintf it just to make sure that the information is valid */
1007 vsprintf(buffer, fmt, ap);
1008 va_end(ap);
1009 info(UnicodeString(buffer, (const char *)NULL));
1010 }
1011
infoln(const char * fmt,...)1012 void IntlTest::infoln(const char *fmt, ...)
1013 {
1014 char buffer[4000];
1015 va_list ap;
1016
1017 va_start(ap, fmt);
1018 /* sprintf it just to make sure that the information is valid */
1019 vsprintf(buffer, fmt, ap);
1020 va_end(ap);
1021 infoln(UnicodeString(buffer, (const char *)NULL));
1022 }
1023
err(const char * fmt,...)1024 void IntlTest::err(const char *fmt, ...)
1025 {
1026 char buffer[4000];
1027 va_list ap;
1028
1029 va_start(ap, fmt);
1030 vsprintf(buffer, fmt, ap);
1031 va_end(ap);
1032 err(UnicodeString(buffer, (const char *)NULL));
1033 }
1034
errln(const char * fmt,...)1035 void IntlTest::errln(const char *fmt, ...)
1036 {
1037 char buffer[4000];
1038 va_list ap;
1039
1040 va_start(ap, fmt);
1041 vsprintf(buffer, fmt, ap);
1042 va_end(ap);
1043 errln(UnicodeString(buffer, (const char *)NULL));
1044 }
1045
dataerrln(const char * fmt,...)1046 void IntlTest::dataerrln(const char *fmt, ...)
1047 {
1048 char buffer[4000];
1049 va_list ap;
1050
1051 va_start(ap, fmt);
1052 vsprintf(buffer, fmt, ap);
1053 va_end(ap);
1054 dataerrln(UnicodeString(buffer, (const char *)NULL));
1055 }
1056
errcheckln(UErrorCode status,const char * fmt,...)1057 void IntlTest::errcheckln(UErrorCode status, 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
1066 if (status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR) {
1067 dataerrln(UnicodeString(buffer, (const char *)NULL));
1068 } else {
1069 errln(UnicodeString(buffer, (const char *)NULL));
1070 }
1071 }
1072
printErrors()1073 void IntlTest::printErrors()
1074 {
1075 IntlTest::LL_err_message(errorList, TRUE);
1076 }
1077
printKnownIssues()1078 UBool IntlTest::printKnownIssues()
1079 {
1080 if(knownList != NULL) {
1081 udbg_knownIssue_print(knownList);
1082 udbg_knownIssue_close(knownList);
1083 return TRUE;
1084 } else {
1085 return FALSE;
1086 }
1087 }
1088
LL_err_message(const UnicodeString & message,UBool newline)1089 void IntlTest::LL_err_message( const UnicodeString& message, UBool newline ) {
1090 this->LL_message(message, newline, true);
1091 }
1092
1093
LL_message(UnicodeString message,UBool newline,UBool isErr)1094 void IntlTest::LL_message( UnicodeString message, UBool newline, UBool isErr )
1095 {
1096 // Synchronize this function.
1097 // All error messages generated by tests funnel through here.
1098 // Multithreaded tests can concurrently generate errors, requiring synchronization
1099 // to keep each message together.
1100 static UMutex messageMutex;
1101 Mutex lock(&messageMutex);
1102
1103 // string that starts with a LineFeed character and continues
1104 // with spaces according to the current indentation
1105 static const UChar indentUChars[] = {
1106 '\n',
1107 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1108 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1109 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1110 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1111 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1112 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1113 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1114 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1115 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1116 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
1117 };
1118 U_ASSERT(1 + LL_indentlevel <= UPRV_LENGTHOF(indentUChars));
1119 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
1120
1121 char buffer[30000];
1122 int32_t length;
1123
1124 // stream out the indentation string first if necessary
1125 length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
1126 if (length > 0) {
1127 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1128 if (isErr) currErr.append(buffer, length);
1129 }
1130
1131 // replace each LineFeed by the indentation string
1132 message.findAndReplace(UnicodeString((UChar)'\n'), indent);
1133
1134 // stream out the message
1135 length = message.extract(0, message.length(), buffer, sizeof(buffer));
1136 if (length > 0) {
1137 length = length > 30000 ? 30000 : length;
1138 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
1139 if (isErr) currErr.append(buffer, length);
1140 }
1141
1142 if (newline) {
1143 char newLine = '\n';
1144 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
1145 if (isErr) currErr += newLine;
1146 }
1147
1148 // A newline usually flushes the buffer, but
1149 // flush the message just in case of a core dump.
1150 fflush((FILE *)testoutfp);
1151 }
1152
1153 /**
1154 * Print a usage message for this test class.
1155 */
usage(void)1156 void IntlTest::usage( void )
1157 {
1158 UBool save_verbose = setVerbose( TRUE );
1159 logln("Test names:");
1160 logln("-----------");
1161
1162 int32_t index = 0;
1163 const char* name = NULL;
1164 do{
1165 this->runIndexedTest( index, FALSE, name );
1166 if (!name) break;
1167 logln(name);
1168 index++;
1169 }while (name && (name[0] != 0));
1170 setVerbose( save_verbose );
1171 }
1172
1173
1174 // memory leak reporting software will be able to take advantage of the testsuite
1175 // being run a second time local to a specific method in order to report only actual leaks
1176 UBool
run_phase2(char * name,char * par)1177 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
1178 {
1179 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
1180 strLeak->append(" for verifying purify filter");
1181 return this->runTest( name, par );
1182 }
1183
1184
1185 #if UCONFIG_NO_LEGACY_CONVERSION
1186 # define TRY_CNV_1 "iso-8859-1"
1187 # define TRY_CNV_2 "ibm-1208"
1188 #else
1189 # define TRY_CNV_1 "iso-8859-7"
1190 # define TRY_CNV_2 "sjis"
1191 #endif
1192
1193 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1194 U_CAPI void unistr_printLengths();
1195 #endif
1196
1197 int
main(int argc,char * argv[])1198 main(int argc, char* argv[])
1199 {
1200 UBool syntax = FALSE;
1201 UBool all = FALSE;
1202 UBool verbose = FALSE;
1203 UBool no_err_msg = FALSE;
1204 UBool no_time = FALSE;
1205 UBool quick = TRUE;
1206 UBool name = FALSE;
1207 UBool leaks = FALSE;
1208 UBool utf8 = FALSE;
1209 const char *summary_file = NULL;
1210 UBool warnOnMissingData = FALSE;
1211 UBool writeGoldenData = FALSE;
1212 UBool defaultDataFound = FALSE;
1213 int32_t threadCount = 12;
1214 UErrorCode errorCode = U_ZERO_ERROR;
1215 UConverter *cnv = NULL;
1216 const char *warnOrErr = "Failure";
1217 UDate startTime, endTime;
1218 int32_t diffTime;
1219 const char *props[IntlTest::kMaxProps];
1220 int32_t nProps = 0;
1221
1222 U_MAIN_INIT_ARGS(argc, argv);
1223
1224 startTime = uprv_getRawUTCtime();
1225
1226 for (int i = 1; i < argc; ++i) {
1227 if (argv[i][0] == '-') {
1228 const char* str = argv[i] + 1;
1229 if (strcmp("verbose", str) == 0 ||
1230 strcmp("v", str) == 0)
1231 verbose = TRUE;
1232 else if (strcmp("noerrormsg", str) == 0 ||
1233 strcmp("n", str) == 0)
1234 no_err_msg = TRUE;
1235 else if (strcmp("exhaustive", str) == 0 ||
1236 strcmp("e", str) == 0)
1237 quick = FALSE;
1238 else if (strcmp("all", str) == 0 ||
1239 strcmp("a", str) == 0)
1240 all = TRUE;
1241 else if (strcmp("utf-8", str) == 0 ||
1242 strcmp("u", str) == 0)
1243 utf8 = TRUE;
1244 else if (strcmp("noknownissues", str) == 0 ||
1245 strcmp("K", str) == 0)
1246 noKnownIssues = TRUE;
1247 else if (strcmp("leaks", str) == 0 ||
1248 strcmp("l", str) == 0)
1249 leaks = TRUE;
1250 else if (strcmp("notime", str) == 0 ||
1251 strcmp("T", str) == 0)
1252 no_time = TRUE;
1253 else if (strcmp("goldens", str) == 0 ||
1254 strcmp("G", str) == 0)
1255 writeGoldenData = TRUE;
1256 else if (strncmp("E", str, 1) == 0)
1257 summary_file = str+1;
1258 else if (strcmp("x", str)==0) {
1259 if(++i>=argc) {
1260 printf("* Error: '-x' option requires an argument. usage: '-x outfile.xml'.\n");
1261 syntax = TRUE;
1262 }
1263 if(ctest_xml_setFileName(argv[i])) { /* set the name */
1264 return 1; /* error */
1265 }
1266 } else if (strcmp("w", str) == 0) {
1267 warnOnMissingData = TRUE;
1268 warnOrErr = "WARNING";
1269 }
1270 else if (strncmp("threads:", str, 8) == 0) {
1271 threadCount = atoi(str + 8);
1272 }
1273 else if (strncmp("prop:", str, 5) == 0) {
1274 if (nProps < IntlTest::kMaxProps) {
1275 props[nProps] = str + 5;
1276 }
1277 nProps++;
1278 }
1279 else {
1280 syntax = TRUE;
1281 }
1282 }else{
1283 name = TRUE;
1284 }
1285 }
1286
1287 if (!all && !name) {
1288 all = TRUE;
1289 } else if (all && name) {
1290 syntax = TRUE;
1291 }
1292
1293 if (syntax) {
1294 fprintf(stdout,
1295 "### Syntax:\n"
1296 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1297 "### \n"
1298 "### Options are: verbose (v), all (a), noerrormsg (n), \n"
1299 "### exhaustive (e), leaks (l), -x xmlfile.xml, prop:<property>=<value>, \n"
1300 "### notime (T), \n"
1301 "### threads:<threadCount>\n"
1302 "### (The default thread count is 12.),\n"
1303 "### (Specify either -all (shortcut -a) or a test name). \n"
1304 "### -all will run all of the tests.\n"
1305 "### \n"
1306 "### To get a list of the test names type: intltest LIST \n"
1307 "### To run just the utility tests type: intltest utility \n"
1308 "### \n"
1309 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1310 "### For example to list the utility tests type: intltest utility/LIST \n"
1311 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1312 "### \n"
1313 "### A parameter can be specified for a test by appending '@' and the value \n"
1314 "### to the testname. \n\n");
1315 return 1;
1316 }
1317
1318 if (nProps > IntlTest::kMaxProps) {
1319 fprintf(stdout, "### Too many properties. Exiting.\n");
1320 }
1321
1322 MajorTestLevel major;
1323 major.setVerbose( verbose );
1324 major.setNoErrMsg( no_err_msg );
1325 major.setQuick( quick );
1326 major.setLeaks( leaks );
1327 major.setThreadCount( threadCount );
1328 major.setWarnOnMissingData( warnOnMissingData );
1329 major.setWriteGoldenData( writeGoldenData );
1330 major.setNotime (no_time);
1331 for (int32_t i = 0; i < nProps; i++) {
1332 major.setProperty(props[i]);
1333 }
1334
1335
1336 fprintf(stdout, "-----------------------------------------------\n");
1337 fprintf(stdout, " IntlTest (C++) Test Suite for \n");
1338 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION);
1339
1340
1341 {
1342 const char *charsetFamily = "Unknown";
1343 int32_t voidSize = (int32_t)sizeof(void*);
1344 int32_t bits = voidSize * 8;
1345 if(U_CHARSET_FAMILY==U_ASCII_FAMILY) {
1346 charsetFamily="ASCII";
1347 } else if(U_CHARSET_FAMILY==U_EBCDIC_FAMILY) {
1348 charsetFamily="EBCDIC";
1349 }
1350 fprintf(stdout,
1351 " Bits: %d, Byte order: %s, Chars: %s\n",
1352 bits, U_IS_BIG_ENDIAN?"Big endian":"Little endian",
1353 charsetFamily);
1354 }
1355 fprintf(stdout, "-----------------------------------------------\n");
1356 fprintf(stdout, " Options: \n");
1357 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off"));
1358 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off"));
1359 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off"));
1360 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off"));
1361 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off"));
1362 fprintf(stdout, " utf-8 (u) : %s\n", (utf8? "On" : "Off"));
1363 fprintf(stdout, " notime (T) : %s\n", (no_time? "On" : "Off"));
1364 fprintf(stdout, " noknownissues (K) : %s\n", (noKnownIssues? "On" : "Off"));
1365 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1366 fprintf(stdout, " Write golden data (G) : %s\n", (writeGoldenData? "On" : "Off"));
1367 fprintf(stdout, " Threads : %d\n", threadCount);
1368 for (int32_t i = 0; i < nProps; i++) {
1369 fprintf(stdout, " Custom property (prop:) : %s\n", props[i]);
1370 }
1371 fprintf(stdout, "-----------------------------------------------\n");
1372
1373 if(utf8) {
1374 ucnv_setDefaultName("utf-8");
1375 }
1376 /* Check whether ICU will initialize without forcing the build data directory into
1377 * the ICU_DATA path. Success here means either the data dll contains data, or that
1378 * this test program was run with ICU_DATA set externally. Failure of this check
1379 * is normal when ICU data is not packaged into a shared library.
1380 *
1381 * Whether or not this test succeeds, we want to cleanup and reinitialize
1382 * with a data path so that data loading from individual files can be tested.
1383 */
1384 u_init(&errorCode);
1385 if (U_FAILURE(errorCode)) {
1386 fprintf(stderr,
1387 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1388 defaultDataFound = FALSE;
1389 }
1390 else {
1391 defaultDataFound = TRUE;
1392 }
1393 u_cleanup();
1394 if(utf8) {
1395 ucnv_setDefaultName("utf-8");
1396 }
1397 errorCode = U_ZERO_ERROR;
1398
1399 /* Initialize ICU */
1400 if (!defaultDataFound) {
1401 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1402 }
1403 u_init(&errorCode);
1404 if (U_FAILURE(errorCode)) {
1405 fprintf(stderr,
1406 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1407 "*** Check the ICU_DATA environment variable and \n"
1408 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1409 if(warnOnMissingData == 0) {
1410 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1411 u_cleanup();
1412 return 1;
1413 }
1414 }
1415
1416 // initial check for the default converter
1417 errorCode = U_ZERO_ERROR;
1418 cnv = ucnv_open(0, &errorCode);
1419 if(cnv != 0) {
1420 // ok
1421 ucnv_close(cnv);
1422 } else {
1423 fprintf(stdout,
1424 "*** %s! The default converter [%s] cannot be opened.\n"
1425 "*** Check the ICU_DATA environment variable and\n"
1426 "*** check that the data files are present.\n",
1427 warnOrErr, ucnv_getDefaultName());
1428 if(!warnOnMissingData) {
1429 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1430 return 1;
1431 }
1432 }
1433
1434 // try more data
1435 cnv = ucnv_open(TRY_CNV_2, &errorCode);
1436 if(cnv != 0) {
1437 // ok
1438 ucnv_close(cnv);
1439 } else {
1440 fprintf(stdout,
1441 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1442 "*** Check the ICU_DATA environment variable and \n"
1443 "*** check that the data files are present.\n", warnOrErr);
1444 if(!warnOnMissingData) {
1445 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1446 return 1;
1447 }
1448 }
1449
1450 UResourceBundle *rb = ures_open(0, "en", &errorCode);
1451 ures_close(rb);
1452 if(U_FAILURE(errorCode)) {
1453 fprintf(stdout,
1454 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1455 "*** Check the ICU_DATA environment variable and \n"
1456 "*** check that the data files are present.\n", warnOrErr);
1457 if(!warnOnMissingData) {
1458 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1459 return 1;
1460 }
1461 }
1462
1463 Locale originalLocale; // Save the default locale for comparison later on.
1464
1465 if(ctest_xml_init("intltest"))
1466 return 1;
1467
1468
1469 /* TODO: Add option to call u_cleanup and rerun tests. */
1470 if (all) {
1471 major.runTest();
1472 if (leaks) {
1473 major.run_phase2( NULL, NULL );
1474 }
1475 }else{
1476 for (int i = 1; i < argc; ++i) {
1477 if (argv[i][0] != '-') {
1478 char* name = argv[i];
1479 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1480
1481 char baseName[1024] = "/";
1482
1483 char* parameter = strchr( name, '@' );
1484 if (parameter) {
1485 *parameter = 0;
1486 parameter += 1;
1487 }
1488 execCount = 0;
1489 UBool res = major.runTest( name, parameter, baseName );
1490 if (leaks && res) {
1491 major.run_phase2( name, parameter );
1492 }
1493 if (!res || (execCount <= 0)) {
1494 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1495 }
1496 } else if(!strcmp(argv[i],"-x")) {
1497 i++;
1498 }
1499 }
1500 }
1501
1502
1503 #if !UCONFIG_NO_FORMATTING
1504 CalendarTimeZoneTest::cleanup();
1505 #endif
1506
1507 Locale lastDefaultLocale;
1508 if (originalLocale != lastDefaultLocale) {
1509 major.errln("FAILURE: A test changed the default locale without resetting it.");
1510 }
1511
1512 fprintf(stdout, "\n--------------------------------------\n");
1513 if( major.printKnownIssues() ) {
1514 fprintf(stdout, " To run suppressed tests, use the -K option. \n");
1515 }
1516 if (major.getErrors() == 0) {
1517 /* Call it twice to make sure that the defaults were reset. */
1518 /* Call it before the OK message to verify proper cleanup. */
1519 u_cleanup();
1520 u_cleanup();
1521
1522 fprintf(stdout, "OK: All tests passed without error.\n");
1523
1524 if (major.getDataErrors() != 0) {
1525 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1526 }
1527 }else{
1528 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1529 major.printErrors();
1530
1531 if(summary_file != NULL) {
1532 FILE *summf = fopen(summary_file, "w");
1533 if( summf != NULL) {
1534 char buf[10000];
1535 int32_t length = errorList.extract(0, errorList.length(), buf, sizeof(buf));
1536 fwrite(buf, sizeof(*buf), length, (FILE*)summf);
1537 fclose(summf);
1538 }
1539 }
1540
1541
1542 if (major.getDataErrors() != 0) {
1543 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1544 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1545 "\tthe '-w' option to turn these errors into warnings.\n");
1546 }
1547
1548 /* Call afterwards to display errors. */
1549 u_cleanup();
1550 }
1551
1552 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
1553 unistr_printLengths();
1554 #endif
1555
1556 fprintf(stdout, "--------------------------------------\n");
1557
1558 if (execCount <= 0) {
1559 fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1560 }
1561 if(!no_time) {
1562 endTime = uprv_getRawUTCtime();
1563 diffTime = (int32_t)(endTime - startTime);
1564 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1565 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1566 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1567 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1568 (int)(diffTime%U_MILLIS_PER_SECOND));
1569 }
1570
1571 if(ctest_xml_fini())
1572 return 1;
1573
1574 #ifdef ZERO_EXIT_CODE_FOR_FAILURES
1575 // Exit code 0 to indicate the test completed.
1576 return 0;
1577 #else
1578 return major.getErrors();
1579 #endif
1580 }
1581
loadTestData(UErrorCode & err)1582 const char* IntlTest::loadTestData(UErrorCode& err){
1583 return ctest_loadTestData(&err);
1584 }
1585
getTestDataPath(UErrorCode & err)1586 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1587 return loadTestData(err);
1588 }
1589
1590 /**
1591 * Returns the path to icu/source/test/testdata/
1592 * Note: this function is parallel with C loadSourceTestData in cintltst.c
1593 */
getSourceTestData(UErrorCode &)1594 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1595 return ctest_testDataDir();
1596 }
1597
getUnidataPath(char path[])1598 char *IntlTest::getUnidataPath(char path[]) {
1599 const int kUnicodeDataTxtLength = 15; // strlen("UnicodeData.txt")
1600
1601 // Look inside ICU_DATA first.
1602 strcpy(path, pathToDataDirectory());
1603 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1604 FILE *f = fopen(path, "r");
1605 if(f != NULL) {
1606 fclose(f);
1607 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1608 return path;
1609 }
1610
1611 // As a fallback, try to guess where the source data was located
1612 // at the time ICU was built, and look there.
1613 # ifdef U_TOPSRCDIR
1614 strcpy(path, U_TOPSRCDIR U_FILE_SEP_STRING "data");
1615 # else
1616 UErrorCode errorCode = U_ZERO_ERROR;
1617 const char *testDataPath = loadTestData(errorCode);
1618 if(U_FAILURE(errorCode)) {
1619 it_errln(UnicodeString(
1620 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1621 u_errorName(errorCode));
1622 return NULL;
1623 }
1624 strcpy(path, testDataPath);
1625 strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1626 U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1627 U_FILE_SEP_STRING "data");
1628 # endif
1629 strcat(path, U_FILE_SEP_STRING);
1630 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1631 f = fopen(path, "r");
1632 if(f != NULL) {
1633 fclose(f);
1634 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1635 return path;
1636 }
1637 return NULL;
1638 }
1639
1640 /* returns the path to icu/source/data */
pathToDataDirectory()1641 const char * IntlTest::pathToDataDirectory()
1642 {
1643 return ctest_dataSrcDir();
1644 }
1645
1646 /*
1647 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1648 * It converts an invariant-character string into a UnicodeString, with
1649 * unescaping \u sequences.
1650 */
CharsToUnicodeString(const char * chars)1651 UnicodeString CharsToUnicodeString(const char* chars){
1652 return UnicodeString(chars, -1, US_INV).unescape();
1653 }
1654
ctou(const char * chars)1655 UnicodeString ctou(const char* chars) {
1656 return CharsToUnicodeString(chars);
1657 }
1658
1659 #define RAND_M (714025)
1660 #define RAND_IA (1366)
1661 #define RAND_IC (150889)
1662
1663 static int32_t RAND_SEED;
1664
1665 /**
1666 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1667 * with care: Does not return all possible values; returns one of
1668 * 714,025 values, uniformly spaced. However, the period is
1669 * effectively infinite. See: Numerical Recipes, section 7.1.
1670 *
1671 * @param seedp pointer to seed. Set *seedp to any negative value
1672 * to restart the sequence.
1673 */
random(int32_t * seedp)1674 float IntlTest::random(int32_t* seedp) {
1675 static int32_t iy, ir[98];
1676 static UBool first=TRUE;
1677 int32_t j;
1678 if (*seedp < 0 || first) {
1679 first = FALSE;
1680 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1681 for (j=1;j<=97;++j) {
1682 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1683 ir[j]=(*seedp);
1684 }
1685 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1686 iy=(*seedp);
1687 }
1688 j=(int32_t)(1 + 97.0*iy/RAND_M);
1689 U_ASSERT(j>=1 && j<=97);
1690 iy=ir[j];
1691 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1692 ir[j]=(*seedp);
1693 return (float) iy/RAND_M;
1694 }
1695
1696 /**
1697 * Convenience method using a global seed.
1698 */
random()1699 float IntlTest::random() {
1700 return random(&RAND_SEED);
1701 }
1702
1703
1704 /*
1705 * Integer random number class implementation.
1706 * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1707 */
icu_rand(uint32_t seed)1708 IntlTest::icu_rand::icu_rand(uint32_t seed) {
1709 seed = seed % 2147483647UL;
1710 if (seed == 0) {
1711 seed = 1;
1712 }
1713 fLast = seed;
1714 }
1715
~icu_rand()1716 IntlTest::icu_rand::~icu_rand() {}
1717
seed(uint32_t seed)1718 void IntlTest::icu_rand::seed(uint32_t seed) {
1719 if (seed == 0) {
1720 seed = 1;
1721 }
1722 fLast = seed;
1723 }
1724
operator ()()1725 uint32_t IntlTest::icu_rand::operator() () {
1726 fLast = ((uint64_t)fLast * 48271UL) % 2147483647UL;
1727 return fLast;
1728 }
1729
getSeed()1730 uint32_t IntlTest::icu_rand::getSeed() {
1731 return (uint32_t) fLast;
1732 }
1733
1734
1735
toHex(int32_t i)1736 static inline UChar toHex(int32_t i) {
1737 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1738 }
1739
escape(const UnicodeString & s,UnicodeString & result)1740 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1741 for (int32_t i=0; i<s.length(); ++i) {
1742 UChar c = s[i];
1743 if (c <= (UChar)0x7F) {
1744 result += c;
1745 } else {
1746 result += (UChar)0x5c;
1747 result += (UChar)0x75;
1748 result += toHex((c >> 12) & 0xF);
1749 result += toHex((c >> 8) & 0xF);
1750 result += toHex((c >> 4) & 0xF);
1751 result += toHex( c & 0xF);
1752 }
1753 }
1754 return result;
1755 }
1756
1757 #define VERBOSE_ASSERTIONS
1758
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1759 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1760 if (file != NULL) {
1761 if (!condition) {
1762 if (possibleDataError) {
1763 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1764 } else {
1765 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1766 }
1767 } else if (!quiet) {
1768 logln("%s:%d: Ok: %s", file, line, message);
1769 }
1770 } else {
1771 if (!condition) {
1772 if (possibleDataError) {
1773 dataerrln("FAIL: assertTrue() failed: %s", message);
1774 } else {
1775 errln("FAIL: assertTrue() failed: %s", message);
1776 }
1777 } else if (!quiet) {
1778 logln("Ok: %s", message);
1779 }
1780
1781 }
1782 return condition;
1783 }
1784
assertFalse(const char * message,UBool condition,UBool quiet,UBool possibleDataError)1785 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet, UBool possibleDataError) {
1786 if (condition) {
1787 if (possibleDataError) {
1788 dataerrln("FAIL: assertFalse() failed: %s", message);
1789 } else {
1790 errln("FAIL: assertFalse() failed: %s", message);
1791 }
1792 } else if (!quiet) {
1793 logln("Ok: %s", message);
1794 }
1795 return !condition;
1796 }
1797
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1798 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1799 if( file==NULL ) {
1800 file = ""; // prevent failure if no file given
1801 }
1802 if (U_FAILURE(ec)) {
1803 if (possibleDataError) {
1804 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1805 } else {
1806 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1807 }
1808 return FALSE;
1809 } else {
1810 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1811 }
1812 return TRUE;
1813 }
1814
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1815 UBool IntlTest::assertEquals(const char* message,
1816 const UnicodeString& expected,
1817 const UnicodeString& actual,
1818 UBool possibleDataError) {
1819 if (expected != actual) {
1820 if (possibleDataError) {
1821 dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1822 prettify(actual) +
1823 "; expected " + prettify(expected));
1824 } else {
1825 errln((UnicodeString)"FAIL: " + message + "; got " +
1826 prettify(actual) +
1827 "; expected " + prettify(expected));
1828 }
1829 return FALSE;
1830 }
1831 #ifdef VERBOSE_ASSERTIONS
1832 else {
1833 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1834 }
1835 #endif
1836 return TRUE;
1837 }
1838
assertEquals(const char * message,const char * expected,const char * actual)1839 UBool IntlTest::assertEquals(const char* message,
1840 const char* expected,
1841 const char* actual) {
1842 U_ASSERT(expected != nullptr);
1843 U_ASSERT(actual != nullptr);
1844 if (uprv_strcmp(expected, actual) != 0) {
1845 errln((UnicodeString)"FAIL: " + message + "; got \"" +
1846 actual +
1847 "\"; expected \"" + expected + "\"");
1848 return FALSE;
1849 }
1850 #ifdef VERBOSE_ASSERTIONS
1851 else {
1852 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1853 }
1854 #endif
1855 return TRUE;
1856 }
1857
assertEquals(const char * message,int32_t expected,int32_t actual)1858 UBool IntlTest::assertEquals(const char* message,
1859 int32_t expected,
1860 int32_t actual) {
1861 if (expected != actual) {
1862 errln((UnicodeString)"FAIL: " + message + "; got " +
1863 actual + "=0x" + toHex(actual) +
1864 "; expected " + expected + "=0x" + toHex(expected));
1865 return FALSE;
1866 }
1867 #ifdef VERBOSE_ASSERTIONS
1868 else {
1869 logln((UnicodeString)"Ok: " + message + "; got " + actual + "=0x" + toHex(actual));
1870 }
1871 #endif
1872 return TRUE;
1873 }
1874
assertEquals(const char * message,int64_t expected,int64_t actual)1875 UBool IntlTest::assertEquals(const char* message,
1876 int64_t expected,
1877 int64_t actual) {
1878 if (expected != actual) {
1879 errln((UnicodeString)"FAIL: " + message + "; got int64 " +
1880 Int64ToUnicodeString(actual) +
1881 "; expected " + Int64ToUnicodeString(expected) );
1882 return FALSE;
1883 }
1884 #ifdef VERBOSE_ASSERTIONS
1885 else {
1886 logln((UnicodeString)"Ok: " + message + "; got int64 " + Int64ToUnicodeString(actual));
1887 }
1888 #endif
1889 return TRUE;
1890 }
1891
assertEquals(const char * message,double expected,double actual)1892 UBool IntlTest::assertEquals(const char* message,
1893 double expected,
1894 double actual) {
1895 bool bothNaN = std::isnan(expected) && std::isnan(actual);
1896 if (expected != actual && !bothNaN) {
1897 errln((UnicodeString)"FAIL: " + message + "; got " +
1898 actual +
1899 "; expected " + expected);
1900 return FALSE;
1901 }
1902 #ifdef VERBOSE_ASSERTIONS
1903 else {
1904 logln((UnicodeString)"Ok: " + message + "; got " + actual);
1905 }
1906 #endif
1907 return TRUE;
1908 }
1909
assertEquals(const char * message,UBool expected,UBool actual)1910 UBool IntlTest::assertEquals(const char* message,
1911 UBool expected,
1912 UBool actual) {
1913 if (expected != actual) {
1914 errln((UnicodeString)"FAIL: " + message + "; got " +
1915 toString(actual) +
1916 "; expected " + toString(expected));
1917 return FALSE;
1918 }
1919 #ifdef VERBOSE_ASSERTIONS
1920 else {
1921 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1922 }
1923 #endif
1924 return TRUE;
1925 }
1926
1927
assertEquals(const char * message,UErrorCode expected,UErrorCode actual)1928 UBool IntlTest::assertEquals(const char* message,
1929 UErrorCode expected,
1930 UErrorCode actual) {
1931 if (expected != actual) {
1932 errln((UnicodeString)"FAIL: " + message + "; got " +
1933 u_errorName(actual) +
1934 "; expected " + u_errorName(expected));
1935 return FALSE;
1936 }
1937 #ifdef VERBOSE_ASSERTIONS
1938 else {
1939 logln((UnicodeString)"Ok: " + message + "; got " + u_errorName(actual));
1940 }
1941 #endif
1942 return TRUE;
1943 }
1944
assertEquals(const char * message,const UnicodeSet & expected,const UnicodeSet & actual)1945 UBool IntlTest::assertEquals(const char* message,
1946 const UnicodeSet& expected,
1947 const UnicodeSet& actual) {
1948 IcuTestErrorCode status(*this, "assertEqualsUniSet");
1949 if (expected != actual) {
1950 errln((UnicodeString)"FAIL: " + message + "; got " +
1951 toString(actual, status) +
1952 "; expected " + toString(expected, status));
1953 return FALSE;
1954 }
1955 #ifdef VERBOSE_ASSERTIONS
1956 else {
1957 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual, status));
1958 }
1959 #endif
1960 return TRUE;
1961 }
1962
1963
1964 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)1965 UBool IntlTest::assertEquals(const char* message,
1966 const Formattable& expected,
1967 const Formattable& actual,
1968 UBool possibleDataError) {
1969 if (expected != actual) {
1970 if (possibleDataError) {
1971 dataerrln((UnicodeString)"FAIL: " + message + "; got " +
1972 toString(actual) +
1973 "; expected " + toString(expected));
1974 } else {
1975 errln((UnicodeString)"FAIL: " + message + "; got " +
1976 toString(actual) +
1977 "; expected " + toString(expected));
1978 }
1979 return FALSE;
1980 }
1981 #ifdef VERBOSE_ASSERTIONS
1982 else {
1983 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1984 }
1985 #endif
1986 return TRUE;
1987 }
1988 #endif
1989
vectorToString(const std::vector<std::string> & strings)1990 std::string vectorToString(const std::vector<std::string>& strings) {
1991 std::string result = "{";
1992 bool first = true;
1993 for (auto element : strings) {
1994 if (first) {
1995 first = false;
1996 } else {
1997 result += ", ";
1998 }
1999 result += "\"";
2000 result += element;
2001 result += "\"";
2002 }
2003 result += "}";
2004 return result;
2005 }
2006
assertEquals(const char * message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2007 UBool IntlTest::assertEquals(const char* message,
2008 const std::vector<std::string>& expected,
2009 const std::vector<std::string>& actual) {
2010 if (expected != actual) {
2011 std::string expectedAsString = vectorToString(expected);
2012 std::string actualAsString = vectorToString(actual);
2013 errln((UnicodeString)"FAIL: " + message +
2014 "; got " + actualAsString.c_str() +
2015 "; expected " + expectedAsString.c_str());
2016 return FALSE;
2017 }
2018 #ifdef VERBOSE_ASSERTIONS
2019 else {
2020 logln((UnicodeString)"Ok: " + message + "; got " + vectorToString(actual).c_str());
2021 }
2022 #endif
2023 return TRUE;
2024 }
2025
assertNotEquals(const char * message,int32_t expectedNot,int32_t actual)2026 UBool IntlTest::assertNotEquals(const char* message,
2027 int32_t expectedNot,
2028 int32_t actual) {
2029 if (expectedNot == actual) {
2030 errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2031 "; expected != " + expectedNot);
2032 return FALSE;
2033 }
2034 #ifdef VERBOSE_ASSERTIONS
2035 else {
2036 logln((UnicodeString)("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2037 " != " + expectedNot);
2038 }
2039 #endif
2040 return TRUE;
2041 }
2042
assertEqualsNear(const char * message,double expected,double actual,double delta)2043 UBool IntlTest::assertEqualsNear(const char* message,
2044 double expected,
2045 double actual,
2046 double delta) {
2047 if (std::isnan(delta) || std::isinf(delta)) {
2048 errln((UnicodeString)("FAIL: ") + message + "; nonsensical delta " + delta +
2049 " - delta may not be NaN or Inf");
2050 return FALSE;
2051 }
2052 bool bothNaN = std::isnan(expected) && std::isnan(actual);
2053 double difference = std::abs(expected - actual);
2054 if (expected != actual && (difference > delta || std::isnan(difference)) && !bothNaN) {
2055 errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "; expected " + expected +
2056 "; acceptable delta " + delta);
2057 return FALSE;
2058 }
2059 #ifdef VERBOSE_ASSERTIONS
2060 else {
2061 logln((UnicodeString)("Ok: ") + message + "; got " + actual);
2062 }
2063 #endif
2064 return TRUE;
2065 }
2066
2067 static char ASSERT_BUF[256];
2068
extractToAssertBuf(const UnicodeString & message)2069 static const char* extractToAssertBuf(const UnicodeString& message) {
2070 UnicodeString buf;
2071 escape(message, buf);
2072 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
2073 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
2074 return ASSERT_BUF;
2075 }
2076
assertTrue(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2077 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2078 return assertTrue(extractToAssertBuf(message), condition, quiet, possibleDataError);
2079 }
2080
assertFalse(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2081 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2082 return assertFalse(extractToAssertBuf(message), condition, quiet, possibleDataError);
2083 }
2084
assertSuccess(const UnicodeString & message,UErrorCode ec)2085 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
2086 return assertSuccess(extractToAssertBuf(message), ec);
2087 }
2088
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)2089 UBool IntlTest::assertEquals(const UnicodeString& message,
2090 const UnicodeString& expected,
2091 const UnicodeString& actual,
2092 UBool possibleDataError) {
2093 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
2094 }
2095
assertEquals(const UnicodeString & message,const char * expected,const char * actual)2096 UBool IntlTest::assertEquals(const UnicodeString& message,
2097 const char* expected,
2098 const char* actual) {
2099 return assertEquals(extractToAssertBuf(message), expected, actual);
2100 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)2101 UBool IntlTest::assertEquals(const UnicodeString& message,
2102 UBool expected,
2103 UBool actual) {
2104 return assertEquals(extractToAssertBuf(message), expected, actual);
2105 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)2106 UBool IntlTest::assertEquals(const UnicodeString& message,
2107 int32_t expected,
2108 int32_t actual) {
2109 return assertEquals(extractToAssertBuf(message), expected, actual);
2110 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)2111 UBool IntlTest::assertEquals(const UnicodeString& message,
2112 int64_t expected,
2113 int64_t actual) {
2114 return assertEquals(extractToAssertBuf(message), expected, actual);
2115 }
assertEquals(const UnicodeString & message,double expected,double actual)2116 UBool IntlTest::assertEquals(const UnicodeString& message,
2117 double expected,
2118 double actual) {
2119 return assertEquals(extractToAssertBuf(message), expected, actual);
2120 }
assertEquals(const UnicodeString & message,UErrorCode expected,UErrorCode actual)2121 UBool IntlTest::assertEquals(const UnicodeString& message,
2122 UErrorCode expected,
2123 UErrorCode actual) {
2124 return assertEquals(extractToAssertBuf(message), expected, actual);
2125 }
assertEquals(const UnicodeString & message,const UnicodeSet & expected,const UnicodeSet & actual)2126 UBool IntlTest::assertEquals(const UnicodeString& message,
2127 const UnicodeSet& expected,
2128 const UnicodeSet& actual) {
2129 return assertEquals(extractToAssertBuf(message), expected, actual);
2130 }
assertEquals(const UnicodeString & message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2131 UBool IntlTest::assertEquals(const UnicodeString& message,
2132 const std::vector<std::string>& expected,
2133 const std::vector<std::string>& actual) {
2134 return assertEquals(extractToAssertBuf(message), expected, actual);
2135 }
assertNotEquals(const UnicodeString & message,int32_t expectedNot,int32_t actual)2136 UBool IntlTest::assertNotEquals(const UnicodeString &message,
2137 int32_t expectedNot,
2138 int32_t actual) {
2139 return assertNotEquals(extractToAssertBuf(message), expectedNot, actual);
2140 }
assertEqualsNear(const UnicodeString & message,double expected,double actual,double delta)2141 UBool IntlTest::assertEqualsNear(const UnicodeString& message,
2142 double expected,
2143 double actual,
2144 double delta) {
2145 return assertEqualsNear(extractToAssertBuf(message), expected, actual, delta);
2146 }
2147
2148 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)2149 UBool IntlTest::assertEquals(const UnicodeString& message,
2150 const Formattable& expected,
2151 const Formattable& actual) {
2152 return assertEquals(extractToAssertBuf(message), expected, actual);
2153 }
2154 #endif
2155
setProperty(const char * propline)2156 void IntlTest::setProperty(const char* propline) {
2157 if (numProps < kMaxProps) {
2158 proplines[numProps] = propline;
2159 }
2160 numProps++;
2161 }
2162
getProperty(const char * prop)2163 const char* IntlTest::getProperty(const char* prop) {
2164 const char* val = NULL;
2165 for (int32_t i = 0; i < numProps; i++) {
2166 int32_t plen = static_cast<int32_t>(uprv_strlen(prop));
2167 if ((int32_t)uprv_strlen(proplines[i]) > plen + 1
2168 && proplines[i][plen] == '='
2169 && uprv_strncmp(proplines[i], prop, plen) == 0) {
2170 val = &(proplines[i][plen+1]);
2171 break;
2172 }
2173 }
2174 return val;
2175 }
2176
2177 //-------------------------------------------------------------------------------
2178 //
2179 // ReadAndConvertFile Read a text data file, convert it to UChars, and
2180 // return the data in one big UChar * buffer, which the caller must delete.
2181 //
2182 // parameters:
2183 // fileName: the name of the file, with no directory part. The test data directory
2184 // is assumed.
2185 // ulen an out parameter, receives the actual length (in UChars) of the file data.
2186 // encoding The file encoding. If the file contains a BOM, that will override the encoding
2187 // specified here. The BOM, if it exists, will be stripped from the returned data.
2188 // Pass NULL for the system default encoding.
2189 // status
2190 // returns:
2191 // The file data, converted to UChar.
2192 // The caller must delete this when done with
2193 // delete [] theBuffer;
2194 //
2195 //
2196 //--------------------------------------------------------------------------------
ReadAndConvertFile(const char * fileName,int & ulen,const char * encoding,UErrorCode & status)2197 UChar *IntlTest::ReadAndConvertFile(const char *fileName, int &ulen, const char *encoding, UErrorCode &status) {
2198 UChar *retPtr = NULL;
2199 char *fileBuf = NULL;
2200 UConverter* conv = NULL;
2201 FILE *f = NULL;
2202
2203 ulen = 0;
2204 if (U_FAILURE(status)) {
2205 return retPtr;
2206 }
2207
2208 //
2209 // Open the file.
2210 //
2211 f = fopen(fileName, "rb");
2212 if (f == 0) {
2213 dataerrln("Error opening test data file %s\n", fileName);
2214 status = U_FILE_ACCESS_ERROR;
2215 return NULL;
2216 }
2217 //
2218 // Read it in
2219 //
2220 int fileSize;
2221 int amt_read;
2222
2223 fseek( f, 0, SEEK_END);
2224 fileSize = ftell(f);
2225 fileBuf = new char[fileSize];
2226 fseek(f, 0, SEEK_SET);
2227 amt_read = static_cast<int>(fread(fileBuf, 1, fileSize, f));
2228 if (amt_read != fileSize || fileSize <= 0) {
2229 errln("Error reading test data file.");
2230 goto cleanUpAndReturn;
2231 }
2232
2233 //
2234 // Look for a Unicode Signature (BOM) on the data just read
2235 //
2236 int32_t signatureLength;
2237 const char * fileBufC;
2238 const char* bomEncoding;
2239
2240 fileBufC = fileBuf;
2241 bomEncoding = ucnv_detectUnicodeSignature(
2242 fileBuf, fileSize, &signatureLength, &status);
2243 if(bomEncoding!=NULL ){
2244 fileBufC += signatureLength;
2245 fileSize -= signatureLength;
2246 encoding = bomEncoding;
2247 }
2248
2249 //
2250 // Open a converter to take the rule file to UTF-16
2251 //
2252 conv = ucnv_open(encoding, &status);
2253 if (U_FAILURE(status)) {
2254 goto cleanUpAndReturn;
2255 }
2256
2257 //
2258 // Convert the rules to UChar.
2259 // Preflight first to determine required buffer size.
2260 //
2261 ulen = ucnv_toUChars(conv,
2262 NULL, // dest,
2263 0, // destCapacity,
2264 fileBufC,
2265 fileSize,
2266 &status);
2267 if (status == U_BUFFER_OVERFLOW_ERROR) {
2268 // Buffer Overflow is expected from the preflight operation.
2269 status = U_ZERO_ERROR;
2270
2271 retPtr = new UChar[ulen+1];
2272 ucnv_toUChars(conv,
2273 retPtr, // dest,
2274 ulen+1,
2275 fileBufC,
2276 fileSize,
2277 &status);
2278 }
2279
2280 cleanUpAndReturn:
2281 fclose(f);
2282 delete []fileBuf;
2283 ucnv_close(conv);
2284 if (U_FAILURE(status)) {
2285 errln("ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status));
2286 delete []retPtr;
2287 retPtr = 0;
2288 ulen = 0;
2289 }
2290 return retPtr;
2291 }
2292
2293 #if !UCONFIG_NO_BREAK_ITERATION
LSTMDataIsBuilt()2294 UBool LSTMDataIsBuilt() {
2295 // If we can find the LSTM data, the RBBI will use the LSTM engine.
2296 // So we skip the test which depending on the dictionary data.
2297 UErrorCode status = U_ZERO_ERROR;
2298 DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_THAI, status));
2299 UBool thaiDataIsBuilt = U_SUCCESS(status);
2300 status = U_ZERO_ERROR;
2301 DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_MYANMAR, status));
2302 UBool burmeseDataIsBuilt = U_SUCCESS(status);
2303 return thaiDataIsBuilt | burmeseDataIsBuilt;
2304 }
2305
skipLSTMTest()2306 UBool IntlTest::skipLSTMTest() {
2307 return ! LSTMDataIsBuilt();
2308 }
skipDictionaryTest()2309 UBool IntlTest::skipDictionaryTest() {
2310 return LSTMDataIsBuilt();
2311 }
2312 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */
2313
2314 /*
2315 * Hey, Emacs, please set the following:
2316 *
2317 * Local Variables:
2318 * indent-tabs-mode: nil
2319 * End:
2320 *
2321 */
2322