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