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