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