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", static_cast<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=") + static_cast<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(static_cast<char16_t>(91)/*[*/);
226 s.append(_toString(f));
227 s.append(static_cast<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() + static_cast<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 + static_cast<long>(num); }
operator +(const UnicodeString & left,short num)253 UnicodeString operator+(const UnicodeString& left, short num)
254 { return left + static_cast<long>(num); }
operator +(const UnicodeString & left,int num)255 UnicodeString operator+(const UnicodeString& left, int num)
256 { return left + static_cast<long>(num); }
operator +(const UnicodeString & left,unsigned char num)257 UnicodeString operator+(const UnicodeString& left, unsigned char num)
258 { return left + static_cast<unsigned long>(num); }
operator +(const UnicodeString & left,unsigned short num)259 UnicodeString operator+(const UnicodeString& left, unsigned short num)
260 { return left + static_cast<unsigned long>(num); }
operator +(const UnicodeString & left,unsigned int num)261 UnicodeString operator+(const UnicodeString& left, unsigned int num)
262 { return left + static_cast<unsigned long>(num); }
operator +(const UnicodeString & left,float num)263 UnicodeString operator+(const UnicodeString& left, float num)
264 { return left + static_cast<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) == static_cast<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 = static_cast<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 = static_cast<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", static_cast<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, static_cast<FILE*>(testoutfp));
1129 if (isErr) currErr.append(buffer, length);
1130 }
1131
1132 // replace each LineFeed by the indentation string
1133 message.findAndReplace(UnicodeString(static_cast<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, static_cast<FILE*>(testoutfp));
1140 if (isErr) currErr.append(buffer, length);
1141 }
1142
1143 if (newline) {
1144 char newLine = '\n';
1145 fwrite(&newLine, sizeof(newLine), 1, static_cast<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(static_cast<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 = static_cast<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", static_cast<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, 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 = static_cast<int32_t>(endTime - startTime);
1565 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1566 (diffTime % U_MILLIS_PER_DAY) / U_MILLIS_PER_HOUR,
1567 (diffTime % U_MILLIS_PER_HOUR) / U_MILLIS_PER_MINUTE,
1568 (diffTime % U_MILLIS_PER_MINUTE) / U_MILLIS_PER_SECOND,
1569 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
fileExists(const char * fileName)1599 static bool fileExists(const char* fileName) {
1600 // Test for `srcDataDir` existing by checking for `srcDataDir`/message2/valid-tests.json
1601 U_ASSERT(fileName != nullptr);
1602 FILE *f = fopen(fileName, "r");
1603 if (f) {
1604 fclose(f);
1605 return true;
1606 }
1607 return false;
1608 }
1609
1610 /**
1611 * Returns the path to icu/testdata/
1612 */
getSharedTestData(UErrorCode & err)1613 const char *IntlTest::getSharedTestData(UErrorCode& err) {
1614 #define SOURCE_TARBALL_TOP U_TOPSRCDIR U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1615 #define REPO_TOP SOURCE_TARBALL_TOP ".." U_FILE_SEP_STRING
1616 #define FILE_NAME U_FILE_SEP_STRING "message2" U_FILE_SEP_STRING "valid-tests.json"
1617 const char *srcDataDir = nullptr;
1618 const char *testFile = nullptr;
1619 if (U_SUCCESS(err)) {
1620 #ifdef U_TOPSRCDIR
1621 // Try U_TOPSRCDIR/../testdata (source tarball)
1622 srcDataDir = SOURCE_TARBALL_TOP "testdata" U_FILE_SEP_STRING;
1623 testFile = SOURCE_TARBALL_TOP "testdata" FILE_NAME;
1624 if (!fileExists(testFile)) {
1625 // If that doesn't exist, try U_TOPSRCDIR/../../testdata (in-repo)
1626 srcDataDir = REPO_TOP "testdata" U_FILE_SEP_STRING;
1627 testFile = REPO_TOP "testdata" FILE_NAME;
1628 if (!fileExists(testFile)) {
1629 // If neither exists, return null
1630 err = U_FILE_ACCESS_ERROR;
1631 srcDataDir = nullptr;
1632 }
1633 }
1634 #else
1635 // Try ../../../../testdata (if we're in icu/source/test/intltest)
1636 // and ../../../../../../testdata (if we're in icu/source/test/intltest/Platform/(Debug|Release)
1637 #define TOP ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING
1638 #define TOP_TOP ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING TOP
1639 srcDataDir = TOP "testdata" U_FILE_SEP_STRING;
1640 testFile = TOP "testdata" FILE_NAME;
1641 if (!fileExists(testFile)) {
1642 srcDataDir = TOP_TOP "testdata" U_FILE_SEP_STRING;
1643 testFile = TOP_TOP "testdata" FILE_NAME;
1644 if (!fileExists(testFile)) {
1645 err = U_FILE_ACCESS_ERROR;
1646 srcDataDir = nullptr;
1647 }
1648 }
1649 #endif
1650 }
1651 return srcDataDir;
1652 }
1653
getUnidataPath(char path[])1654 char *IntlTest::getUnidataPath(char path[]) {
1655 const int kUnicodeDataTxtLength = 15; // strlen("UnicodeData.txt")
1656
1657 // Look inside ICU_DATA first.
1658 strcpy(path, pathToDataDirectory());
1659 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1660 FILE *f = fopen(path, "r");
1661 if(f != nullptr) {
1662 fclose(f);
1663 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1664 return path;
1665 }
1666
1667 // As a fallback, try to guess where the source data was located
1668 // at the time ICU was built, and look there.
1669 # ifdef U_TOPSRCDIR
1670 strcpy(path, U_TOPSRCDIR U_FILE_SEP_STRING "data");
1671 # else
1672 UErrorCode errorCode = U_ZERO_ERROR;
1673 const char *testDataPath = loadTestData(errorCode);
1674 if(U_FAILURE(errorCode)) {
1675 it_errln(UnicodeString(
1676 "unable to find path to source/data/unidata/ and loadTestData() failed: ") +
1677 u_errorName(errorCode));
1678 return nullptr;
1679 }
1680 strcpy(path, testDataPath);
1681 strcat(path, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1682 U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".."
1683 U_FILE_SEP_STRING "data");
1684 # endif
1685 strcat(path, U_FILE_SEP_STRING);
1686 strcat(path, "unidata" U_FILE_SEP_STRING "UnicodeData.txt");
1687 f = fopen(path, "r");
1688 if(f != nullptr) {
1689 fclose(f);
1690 *(strchr(path, 0) - kUnicodeDataTxtLength) = 0; // Remove the basename.
1691 return path;
1692 }
1693 return nullptr;
1694 }
1695
1696 /* returns the path to icu/source/data */
pathToDataDirectory()1697 const char * IntlTest::pathToDataDirectory()
1698 {
1699 return ctest_dataSrcDir();
1700 }
1701
1702 /*
1703 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1704 * It converts an invariant-character string into a UnicodeString, with
1705 * unescaping \u sequences.
1706 */
CharsToUnicodeString(const char * chars)1707 UnicodeString CharsToUnicodeString(const char* chars){
1708 return UnicodeString(chars, -1, US_INV).unescape();
1709 }
1710
ctou(const char * chars)1711 UnicodeString ctou(const char* chars) {
1712 return CharsToUnicodeString(chars);
1713 }
1714
1715 #define RAND_M (714025)
1716 #define RAND_IA (1366)
1717 #define RAND_IC (150889)
1718
1719 static int32_t RAND_SEED;
1720
1721 /**
1722 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1723 * with care: Does not return all possible values; returns one of
1724 * 714,025 values, uniformly spaced. However, the period is
1725 * effectively infinite. See: Numerical Recipes, section 7.1.
1726 *
1727 * @param seedp pointer to seed. Set *seedp to any negative value
1728 * to restart the sequence.
1729 */
random(int32_t * seedp)1730 float IntlTest::random(int32_t* seedp) {
1731 static int32_t iy, ir[98];
1732 static UBool first=true;
1733 int32_t j;
1734 if (*seedp < 0 || first) {
1735 first = false;
1736 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1737 for (j=1;j<=97;++j) {
1738 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1739 ir[j]=(*seedp);
1740 }
1741 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1742 iy=(*seedp);
1743 }
1744 j = static_cast<int32_t>(1 + 97.0 * iy / RAND_M);
1745 U_ASSERT(j>=1 && j<=97);
1746 iy=ir[j];
1747 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1748 ir[j]=(*seedp);
1749 return static_cast<float>(iy) / RAND_M;
1750 }
1751
1752 /**
1753 * Convenience method using a global seed.
1754 */
random()1755 float IntlTest::random() {
1756 return random(&RAND_SEED);
1757 }
1758
1759
1760 /*
1761 * Integer random number class implementation.
1762 * Similar to C++ std::minstd_rand, with the same algorithm & constants.
1763 */
icu_rand(uint32_t seed)1764 IntlTest::icu_rand::icu_rand(uint32_t seed) {
1765 seed = seed % 2147483647UL;
1766 if (seed == 0) {
1767 seed = 1;
1768 }
1769 fLast = seed;
1770 }
1771
~icu_rand()1772 IntlTest::icu_rand::~icu_rand() {}
1773
seed(uint32_t seed)1774 void IntlTest::icu_rand::seed(uint32_t seed) {
1775 if (seed == 0) {
1776 seed = 1;
1777 }
1778 fLast = seed;
1779 }
1780
operator ()()1781 uint32_t IntlTest::icu_rand::operator() () {
1782 fLast = (static_cast<uint64_t>(fLast) * 48271UL) % 2147483647UL;
1783 return fLast;
1784 }
1785
getSeed()1786 uint32_t IntlTest::icu_rand::getSeed() {
1787 return fLast;
1788 }
1789
1790
1791
toHex(int32_t i)1792 static inline char16_t toHex(int32_t i) {
1793 return static_cast<char16_t>(i + (i < 10 ? 0x30 : (0x41 - 10)));
1794 }
1795
escape(const UnicodeString & s,UnicodeString & result)1796 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1797 for (int32_t i=0; i<s.length(); ++i) {
1798 char16_t c = s[i];
1799 if (c <= static_cast<char16_t>(0x7F)) {
1800 result += c;
1801 } else {
1802 result += static_cast<char16_t>(0x5c);
1803 result += static_cast<char16_t>(0x75);
1804 result += toHex((c >> 12) & 0xF);
1805 result += toHex((c >> 8) & 0xF);
1806 result += toHex((c >> 4) & 0xF);
1807 result += toHex( c & 0xF);
1808 }
1809 }
1810 return result;
1811 }
1812
1813 #define VERBOSE_ASSERTIONS
1814
assertTrue(const char * message,UBool condition,UBool quiet,UBool possibleDataError,const char * file,int line)1815 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet, UBool possibleDataError, const char *file, int line) {
1816 if (file != nullptr) {
1817 if (!condition) {
1818 if (possibleDataError) {
1819 dataerrln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1820 } else {
1821 errln("%s:%d: FAIL: assertTrue() failed: %s", file, line, message);
1822 }
1823 } else if (!quiet) {
1824 logln("%s:%d: Ok: %s", file, line, message);
1825 }
1826 } else {
1827 if (!condition) {
1828 if (possibleDataError) {
1829 dataerrln("FAIL: assertTrue() failed: %s", message);
1830 } else {
1831 errln("FAIL: assertTrue() failed: %s", message);
1832 }
1833 } else if (!quiet) {
1834 logln("Ok: %s", message);
1835 }
1836
1837 }
1838 return condition;
1839 }
1840
assertFalse(const char * message,UBool condition,UBool quiet,UBool possibleDataError)1841 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet, UBool possibleDataError) {
1842 if (condition) {
1843 if (possibleDataError) {
1844 dataerrln("FAIL: assertFalse() failed: %s", message);
1845 } else {
1846 errln("FAIL: assertFalse() failed: %s", message);
1847 }
1848 } else if (!quiet) {
1849 logln("Ok: %s", message);
1850 }
1851 return !condition;
1852 }
1853
assertSuccess(const char * message,UErrorCode ec,UBool possibleDataError,const char * file,int line)1854 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError, const char *file, int line) {
1855 if( file==nullptr ) {
1856 file = ""; // prevent failure if no file given
1857 }
1858 if (U_FAILURE(ec)) {
1859 if (possibleDataError) {
1860 dataerrln("FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1861 } else {
1862 errcheckln(ec, "FAIL: %s:%d: %s (%s)", file, line, message, u_errorName(ec));
1863 }
1864 return false;
1865 } else {
1866 logln("OK: %s:%d: %s - (%s)", file, line, message, u_errorName(ec));
1867 }
1868 return true;
1869 }
1870
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)1871 UBool IntlTest::assertEquals(const char* message,
1872 const UnicodeString& expected,
1873 const UnicodeString& actual,
1874 UBool possibleDataError) {
1875 if (expected != actual) {
1876 if (possibleDataError) {
1877 dataerrln(UnicodeString("FAIL: ") + message + "; got " +
1878 prettify(actual) +
1879 "; expected " + prettify(expected));
1880 } else {
1881 errln(UnicodeString("FAIL: ") + message + "; got " +
1882 prettify(actual) +
1883 "; expected " + prettify(expected));
1884 }
1885 return false;
1886 }
1887 #ifdef VERBOSE_ASSERTIONS
1888 else {
1889 logln(UnicodeString("Ok: ") + message + "; got " + prettify(actual));
1890 }
1891 #endif
1892 return true;
1893 }
1894
assertEquals(const char * message,const char * expected,const char * actual)1895 UBool IntlTest::assertEquals(const char* message,
1896 const char* expected,
1897 const char* actual) {
1898 U_ASSERT(expected != nullptr);
1899 U_ASSERT(actual != nullptr);
1900 if (uprv_strcmp(expected, actual) != 0) {
1901 errln(UnicodeString("FAIL: ") + message + "; got \"" +
1902 actual +
1903 "\"; expected \"" + expected + "\"");
1904 return false;
1905 }
1906 #ifdef VERBOSE_ASSERTIONS
1907 else {
1908 logln(UnicodeString("Ok: ") + message + "; got \"" + actual + "\"");
1909 }
1910 #endif
1911 return true;
1912 }
1913
assertEquals(const char * message,int32_t expected,int32_t actual)1914 UBool IntlTest::assertEquals(const char* message,
1915 int32_t expected,
1916 int32_t actual) {
1917 if (expected != actual) {
1918 errln(UnicodeString("FAIL: ") + message + "; got " +
1919 actual + "=0x" + toHex(actual) +
1920 "; expected " + expected + "=0x" + toHex(expected));
1921 return false;
1922 }
1923 #ifdef VERBOSE_ASSERTIONS
1924 else {
1925 logln(UnicodeString("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual));
1926 }
1927 #endif
1928 return true;
1929 }
1930
assertEquals(const char * message,int64_t expected,int64_t actual)1931 UBool IntlTest::assertEquals(const char* message,
1932 int64_t expected,
1933 int64_t actual) {
1934 if (expected != actual) {
1935 errln(UnicodeString("FAIL: ") + message + "; got int64 " +
1936 Int64ToUnicodeString(actual) +
1937 "; expected " + Int64ToUnicodeString(expected) );
1938 return false;
1939 }
1940 #ifdef VERBOSE_ASSERTIONS
1941 else {
1942 logln(UnicodeString("Ok: ") + message + "; got int64 " + Int64ToUnicodeString(actual));
1943 }
1944 #endif
1945 return true;
1946 }
1947
assertEquals(const char * message,double expected,double actual)1948 UBool IntlTest::assertEquals(const char* message,
1949 double expected,
1950 double actual) {
1951 bool bothNaN = std::isnan(expected) && std::isnan(actual);
1952 if (expected != actual && !bothNaN) {
1953 errln(UnicodeString("FAIL: ") + message + "; got " +
1954 actual +
1955 "; expected " + expected);
1956 return false;
1957 }
1958 #ifdef VERBOSE_ASSERTIONS
1959 else {
1960 logln(UnicodeString("Ok: ") + message + "; got " + actual);
1961 }
1962 #endif
1963 return true;
1964 }
1965
assertEquals(const char * message,UBool expected,UBool actual)1966 UBool IntlTest::assertEquals(const char* message,
1967 UBool expected,
1968 UBool actual) {
1969 if (expected != actual) {
1970 errln(UnicodeString("FAIL: ") + message + "; got " +
1971 toString(actual) +
1972 "; expected " + toString(expected));
1973 return false;
1974 }
1975 #ifdef VERBOSE_ASSERTIONS
1976 else {
1977 logln(UnicodeString("Ok: ") + message + "; got " + toString(actual));
1978 }
1979 #endif
1980 return true;
1981 }
1982
1983
assertEquals(const char * message,UErrorCode expected,UErrorCode actual)1984 UBool IntlTest::assertEquals(const char* message,
1985 UErrorCode expected,
1986 UErrorCode actual) {
1987 if (expected != actual) {
1988 errln(UnicodeString("FAIL: ") + message + "; got " +
1989 u_errorName(actual) +
1990 "; expected " + u_errorName(expected));
1991 return false;
1992 }
1993 #ifdef VERBOSE_ASSERTIONS
1994 else {
1995 logln(UnicodeString("Ok: ") + message + "; got " + u_errorName(actual));
1996 }
1997 #endif
1998 return true;
1999 }
2000
assertEquals(const char * message,const UnicodeSet & expected,const UnicodeSet & actual)2001 UBool IntlTest::assertEquals(const char* message,
2002 const UnicodeSet& expected,
2003 const UnicodeSet& actual) {
2004 IcuTestErrorCode status(*this, "assertEqualsUniSet");
2005 if (expected != actual) {
2006 errln(UnicodeString("FAIL: ") + message + "; got " +
2007 toString(actual, status) +
2008 "; expected " + toString(expected, status));
2009 return false;
2010 }
2011 #ifdef VERBOSE_ASSERTIONS
2012 else {
2013 logln(UnicodeString("Ok: ") + message + "; got " + toString(actual, status));
2014 }
2015 #endif
2016 return true;
2017 }
2018
2019
2020 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual,UBool possibleDataError)2021 UBool IntlTest::assertEquals(const char* message,
2022 const Formattable& expected,
2023 const Formattable& actual,
2024 UBool possibleDataError) {
2025 if (expected != actual) {
2026 if (possibleDataError) {
2027 dataerrln(UnicodeString("FAIL: ") + message + "; got " +
2028 toString(actual) +
2029 "; expected " + toString(expected));
2030 } else {
2031 errln(UnicodeString("FAIL: ") + message + "; got " +
2032 toString(actual) +
2033 "; expected " + toString(expected));
2034 }
2035 return false;
2036 }
2037 #ifdef VERBOSE_ASSERTIONS
2038 else {
2039 logln(UnicodeString("Ok: ") + message + "; got " + toString(actual));
2040 }
2041 #endif
2042 return true;
2043 }
2044 #endif
2045
vectorToString(const std::vector<std::string> & strings)2046 std::string vectorToString(const std::vector<std::string>& strings) {
2047 std::string result = "{";
2048 bool first = true;
2049 for (auto element : strings) {
2050 if (first) {
2051 first = false;
2052 } else {
2053 result += ", ";
2054 }
2055 result += "\"";
2056 result += element;
2057 result += "\"";
2058 }
2059 result += "}";
2060 return result;
2061 }
2062
assertEquals(const char * message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2063 UBool IntlTest::assertEquals(const char* message,
2064 const std::vector<std::string>& expected,
2065 const std::vector<std::string>& actual) {
2066 if (expected != actual) {
2067 std::string expectedAsString = vectorToString(expected);
2068 std::string actualAsString = vectorToString(actual);
2069 errln(UnicodeString("FAIL: ") + message +
2070 "; got " + actualAsString.c_str() +
2071 "; expected " + expectedAsString.c_str());
2072 return false;
2073 }
2074 #ifdef VERBOSE_ASSERTIONS
2075 else {
2076 logln(UnicodeString("Ok: ") + message + "; got " + vectorToString(actual).c_str());
2077 }
2078 #endif
2079 return true;
2080 }
2081
assertNotEquals(const char * message,int32_t expectedNot,int32_t actual)2082 UBool IntlTest::assertNotEquals(const char* message,
2083 int32_t expectedNot,
2084 int32_t actual) {
2085 if (expectedNot == actual) {
2086 errln(UnicodeString("FAIL: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2087 "; expected != " + expectedNot);
2088 return false;
2089 }
2090 #ifdef VERBOSE_ASSERTIONS
2091 else {
2092 logln(UnicodeString("Ok: ") + message + "; got " + actual + "=0x" + toHex(actual) +
2093 " != " + expectedNot);
2094 }
2095 #endif
2096 return true;
2097 }
2098
assertEqualsNear(const char * message,double expected,double actual,double delta)2099 UBool IntlTest::assertEqualsNear(const char* message,
2100 double expected,
2101 double actual,
2102 double delta) {
2103 bool bothNaN = std::isnan(expected) && std::isnan(actual);
2104 bool bothPosInf = uprv_isPositiveInfinity(expected) && uprv_isPositiveInfinity(actual);
2105 bool bothNegInf = uprv_isNegativeInfinity(expected) && uprv_isNegativeInfinity(actual);
2106 if (bothPosInf || bothNegInf || bothNaN) {
2107 // We don't care about delta in these cases
2108 return true;
2109 }
2110 if (std::isnan(delta) || std::isinf(delta)) {
2111 errln(UnicodeString("FAIL: ") + message + "; nonsensical delta " + delta +
2112 " - delta may not be NaN or Inf. (Got " + actual + "; expected " + expected + ".)");
2113 return false;
2114 }
2115 double difference = std::abs(expected - actual);
2116 if (expected != actual && (difference > delta || std::isnan(difference))) {
2117 errln(UnicodeString("FAIL: ") + message + "; got " + actual + "; expected " + expected +
2118 "; acceptable delta " + delta);
2119 return false;
2120 }
2121 #ifdef VERBOSE_ASSERTIONS
2122 else {
2123 logln(UnicodeString("Ok: ") + message + "; got " + actual);
2124 }
2125 #endif
2126 return true;
2127 }
2128
2129 static char ASSERT_BUF[256];
2130
extractToAssertBuf(const UnicodeString & message)2131 static const char* extractToAssertBuf(const UnicodeString& message) {
2132 UnicodeString buf;
2133 escape(message, buf);
2134 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF) - 1, nullptr);
2135 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
2136 return ASSERT_BUF;
2137 }
2138
assertTrue(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2139 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2140 return assertTrue(extractToAssertBuf(message), condition, quiet, possibleDataError);
2141 }
2142
assertFalse(const UnicodeString & message,UBool condition,UBool quiet,UBool possibleDataError)2143 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet, UBool possibleDataError) {
2144 return assertFalse(extractToAssertBuf(message), condition, quiet, possibleDataError);
2145 }
2146
assertSuccess(const UnicodeString & message,UErrorCode ec)2147 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
2148 return assertSuccess(extractToAssertBuf(message), ec);
2149 }
2150
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual,UBool possibleDataError)2151 UBool IntlTest::assertEquals(const UnicodeString& message,
2152 const UnicodeString& expected,
2153 const UnicodeString& actual,
2154 UBool possibleDataError) {
2155 return assertEquals(extractToAssertBuf(message), expected, actual, possibleDataError);
2156 }
2157
assertEquals(const UnicodeString & message,const char * expected,const char * actual)2158 UBool IntlTest::assertEquals(const UnicodeString& message,
2159 const char* expected,
2160 const char* actual) {
2161 return assertEquals(extractToAssertBuf(message), expected, actual);
2162 }
assertEquals(const UnicodeString & message,UBool expected,UBool actual)2163 UBool IntlTest::assertEquals(const UnicodeString& message,
2164 UBool expected,
2165 UBool actual) {
2166 return assertEquals(extractToAssertBuf(message), expected, actual);
2167 }
assertEquals(const UnicodeString & message,int32_t expected,int32_t actual)2168 UBool IntlTest::assertEquals(const UnicodeString& message,
2169 int32_t expected,
2170 int32_t actual) {
2171 return assertEquals(extractToAssertBuf(message), expected, actual);
2172 }
assertEquals(const UnicodeString & message,int64_t expected,int64_t actual)2173 UBool IntlTest::assertEquals(const UnicodeString& message,
2174 int64_t expected,
2175 int64_t actual) {
2176 return assertEquals(extractToAssertBuf(message), expected, actual);
2177 }
assertEquals(const UnicodeString & message,double expected,double actual)2178 UBool IntlTest::assertEquals(const UnicodeString& message,
2179 double expected,
2180 double actual) {
2181 return assertEquals(extractToAssertBuf(message), expected, actual);
2182 }
assertEquals(const UnicodeString & message,UErrorCode expected,UErrorCode actual)2183 UBool IntlTest::assertEquals(const UnicodeString& message,
2184 UErrorCode expected,
2185 UErrorCode actual) {
2186 return assertEquals(extractToAssertBuf(message), expected, actual);
2187 }
assertEquals(const UnicodeString & message,const UnicodeSet & expected,const UnicodeSet & actual)2188 UBool IntlTest::assertEquals(const UnicodeString& message,
2189 const UnicodeSet& expected,
2190 const UnicodeSet& actual) {
2191 return assertEquals(extractToAssertBuf(message), expected, actual);
2192 }
assertEquals(const UnicodeString & message,const std::vector<std::string> & expected,const std::vector<std::string> & actual)2193 UBool IntlTest::assertEquals(const UnicodeString& message,
2194 const std::vector<std::string>& expected,
2195 const std::vector<std::string>& actual) {
2196 return assertEquals(extractToAssertBuf(message), expected, actual);
2197 }
assertNotEquals(const UnicodeString & message,int32_t expectedNot,int32_t actual)2198 UBool IntlTest::assertNotEquals(const UnicodeString &message,
2199 int32_t expectedNot,
2200 int32_t actual) {
2201 return assertNotEquals(extractToAssertBuf(message), expectedNot, actual);
2202 }
assertEqualsNear(const UnicodeString & message,double expected,double actual,double delta)2203 UBool IntlTest::assertEqualsNear(const UnicodeString& message,
2204 double expected,
2205 double actual,
2206 double delta) {
2207 return assertEqualsNear(extractToAssertBuf(message), expected, actual, delta);
2208 }
2209
2210 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)2211 UBool IntlTest::assertEquals(const UnicodeString& message,
2212 const Formattable& expected,
2213 const Formattable& actual) {
2214 return assertEquals(extractToAssertBuf(message), expected, actual);
2215 }
2216 #endif
2217
setProperty(const char * propline)2218 void IntlTest::setProperty(const char* propline) {
2219 if (numProps < kMaxProps) {
2220 proplines[numProps] = propline;
2221 }
2222 numProps++;
2223 }
2224
getProperty(const char * prop)2225 const char* IntlTest::getProperty(const char* prop) {
2226 const char* val = nullptr;
2227 for (int32_t i = 0; i < numProps; i++) {
2228 int32_t plen = static_cast<int32_t>(uprv_strlen(prop));
2229 if (static_cast<int32_t>(uprv_strlen(proplines[i])) > plen + 1
2230 && proplines[i][plen] == '='
2231 && uprv_strncmp(proplines[i], prop, plen) == 0) {
2232 val = &(proplines[i][plen+1]);
2233 break;
2234 }
2235 }
2236 return val;
2237 }
2238
2239 //-------------------------------------------------------------------------------
2240 //
2241 // ReadAndConvertFile Read a text data file, convert it to UChars, and
2242 // return the data in one big char16_t * buffer, which the caller must delete.
2243 //
2244 // parameters:
2245 // fileName: the name of the file, with no directory part. The test data directory
2246 // is assumed.
2247 // ulen an out parameter, receives the actual length (in UChars) of the file data.
2248 // encoding The file encoding. If the file contains a BOM, that will override the encoding
2249 // specified here. The BOM, if it exists, will be stripped from the returned data.
2250 // Pass nullptr for the system default encoding.
2251 // status
2252 // returns:
2253 // The file data, converted to char16_t.
2254 // The caller must delete this when done with
2255 // delete [] theBuffer;
2256 //
2257 //
2258 //--------------------------------------------------------------------------------
ReadAndConvertFile(const char * fileName,int & ulen,const char * encoding,UErrorCode & status)2259 char16_t *IntlTest::ReadAndConvertFile(const char *fileName, int &ulen, const char *encoding, UErrorCode &status) {
2260 char16_t *retPtr = nullptr;
2261 char *fileBuf = nullptr;
2262 UConverter* conv = nullptr;
2263 FILE *f = nullptr;
2264
2265 ulen = 0;
2266 if (U_FAILURE(status)) {
2267 return retPtr;
2268 }
2269
2270 //
2271 // Open the file.
2272 //
2273 f = fopen(fileName, "rb");
2274 if (f == nullptr) {
2275 dataerrln("Error opening test data file %s\n", fileName);
2276 status = U_FILE_ACCESS_ERROR;
2277 return nullptr;
2278 }
2279 //
2280 // Read it in
2281 //
2282 int fileSize;
2283 int amt_read;
2284
2285 fseek( f, 0, SEEK_END);
2286 fileSize = ftell(f);
2287 fileBuf = new char[fileSize];
2288 fseek(f, 0, SEEK_SET);
2289 amt_read = static_cast<int>(fread(fileBuf, 1, fileSize, f));
2290 if (amt_read != fileSize || fileSize <= 0) {
2291 errln("Error reading test data file.");
2292 goto cleanUpAndReturn;
2293 }
2294
2295 //
2296 // Look for a Unicode Signature (BOM) on the data just read
2297 //
2298 int32_t signatureLength;
2299 const char * fileBufC;
2300 const char* bomEncoding;
2301
2302 fileBufC = fileBuf;
2303 bomEncoding = ucnv_detectUnicodeSignature(
2304 fileBuf, fileSize, &signatureLength, &status);
2305 if(bomEncoding!=nullptr ){
2306 fileBufC += signatureLength;
2307 fileSize -= signatureLength;
2308 encoding = bomEncoding;
2309 }
2310
2311 //
2312 // Open a converter to take the rule file to UTF-16
2313 //
2314 conv = ucnv_open(encoding, &status);
2315 if (U_FAILURE(status)) {
2316 goto cleanUpAndReturn;
2317 }
2318
2319 //
2320 // Convert the rules to char16_t.
2321 // Preflight first to determine required buffer size.
2322 //
2323 ulen = ucnv_toUChars(conv,
2324 nullptr, // dest,
2325 0, // destCapacity,
2326 fileBufC,
2327 fileSize,
2328 &status);
2329 if (status == U_BUFFER_OVERFLOW_ERROR) {
2330 // Buffer Overflow is expected from the preflight operation.
2331 status = U_ZERO_ERROR;
2332
2333 retPtr = new char16_t[ulen+1];
2334 ucnv_toUChars(conv,
2335 retPtr, // dest,
2336 ulen+1,
2337 fileBufC,
2338 fileSize,
2339 &status);
2340 }
2341
2342 cleanUpAndReturn:
2343 fclose(f);
2344 delete []fileBuf;
2345 ucnv_close(conv);
2346 if (U_FAILURE(status)) {
2347 errln("ucnv_toUChars: ICU Error \"%s\"\n", u_errorName(status));
2348 delete []retPtr;
2349 retPtr = nullptr;
2350 ulen = 0;
2351 }
2352 return retPtr;
2353 }
2354
2355 #if !UCONFIG_NO_BREAK_ITERATION
LSTMDataIsBuilt()2356 UBool LSTMDataIsBuilt() {
2357 // If we can find the LSTM data, the RBBI will use the LSTM engine.
2358 // So we skip the test which depending on the dictionary data.
2359 UErrorCode status = U_ZERO_ERROR;
2360 DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_THAI, status));
2361 UBool thaiDataIsBuilt = U_SUCCESS(status);
2362 status = U_ZERO_ERROR;
2363 DeleteLSTMData(CreateLSTMDataForScript(USCRIPT_MYANMAR, status));
2364 UBool burmeseDataIsBuilt = U_SUCCESS(status);
2365 return thaiDataIsBuilt | burmeseDataIsBuilt;
2366 }
2367
skipLSTMTest()2368 UBool IntlTest::skipLSTMTest() {
2369 return ! LSTMDataIsBuilt();
2370 }
skipDictionaryTest()2371 UBool IntlTest::skipDictionaryTest() {
2372 return LSTMDataIsBuilt();
2373 }
2374 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */
2375
2376 /*
2377 * Hey, Emacs, please set the following:
2378 *
2379 * Local Variables:
2380 * indent-tabs-mode: nil
2381 * End:
2382 *
2383 */
2384