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