1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2007, 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_getUTCtime()
39 #include "unicode/locid.h"
40
41
42 #ifdef XP_MAC_CONSOLE
43 #include <console.h>
44 #include "Files.h"
45 #endif
46
47
48 static char* _testDataPath=NULL;
49
50 // Static list of errors found
51 static UnicodeString errorList;
52
53 //-----------------------------------------------------------------------------
54 //convenience classes to ease porting code that uses the Java
55 //string-concatenation operator (moved from findword test by rtg)
56
57 // [LIU] Just to get things working
58 UnicodeString
UCharToUnicodeString(UChar c)59 UCharToUnicodeString(UChar c)
60 { return UnicodeString(c); }
61
62 // [rtg] Just to get things working
63 UnicodeString
operator +(const UnicodeString & left,long num)64 operator+(const UnicodeString& left,
65 long num)
66 {
67 char buffer[64]; // nos changed from 10 to 64
68 char danger = 'p'; // guard against overrunning the buffer (rtg)
69
70 sprintf(buffer, "%ld", num);
71 assert(danger == 'p');
72
73 return left + buffer;
74 }
75
76 UnicodeString
operator +(const UnicodeString & left,unsigned long num)77 operator+(const UnicodeString& left,
78 unsigned long num)
79 {
80 char buffer[64]; // nos changed from 10 to 64
81 char danger = 'p'; // guard against overrunning the buffer (rtg)
82
83 sprintf(buffer, "%lu", num);
84 assert(danger == 'p');
85
86 return left + buffer;
87 }
88
89 UnicodeString
Int64ToUnicodeString(int64_t num)90 Int64ToUnicodeString(int64_t num)
91 {
92 char buffer[64]; // nos changed from 10 to 64
93 char danger = 'p'; // guard against overrunning the buffer (rtg)
94
95 #ifdef U_WINDOWS
96 sprintf(buffer, "%I64d", num);
97 #else
98 sprintf(buffer, "%lld", (long long)num);
99 #endif
100 assert(danger == 'p');
101
102 return buffer;
103 }
104
105 // [LIU] Just to get things working
106 UnicodeString
operator +(const UnicodeString & left,double num)107 operator+(const UnicodeString& left,
108 double num)
109 {
110 char buffer[64]; // was 32, made it arbitrarily bigger (rtg)
111 char danger = 'p'; // guard against overrunning the buffer (rtg)
112
113 // IEEE floating point has 52 bits of mantissa, plus one assumed bit
114 // 53*log(2)/log(10) = 15.95
115 // so there is no need to show more than 16 digits. [alan]
116
117 sprintf(buffer, "%.17g", num);
118 assert(danger == 'p');
119
120 return left + buffer;
121 }
122
123 #if !UCONFIG_NO_FORMATTING
124
125 /**
126 * Return a string display for for this, without surrounding braces.
127 */
_toString(const Formattable & f)128 UnicodeString _toString(const Formattable& f) {
129 UnicodeString s;
130 switch (f.getType()) {
131 case Formattable::kDate:
132 {
133 UErrorCode status = U_ZERO_ERROR;
134 SimpleDateFormat fmt(status);
135 if (U_SUCCESS(status)) {
136 FieldPosition pos;
137 fmt.format(f.getDate(), s, pos);
138 s.insert(0, "Date:");
139 } else {
140 s = UnicodeString("Error creating date format]");
141 }
142 }
143 break;
144 case Formattable::kDouble:
145 s = UnicodeString("double:") + f.getDouble();
146 break;
147 case Formattable::kLong:
148 s = UnicodeString("long:") + f.getLong();
149 break;
150
151 case Formattable::kInt64:
152 s = UnicodeString("int64:") + Int64ToUnicodeString(f.getInt64());
153 break;
154
155 case Formattable::kString:
156 f.getString(s);
157 s.insert(0, "String:");
158 break;
159 case Formattable::kArray:
160 {
161 int32_t i, n;
162 const Formattable* array = f.getArray(n);
163 s.insert(0, UnicodeString("Array:"));
164 UnicodeString delim(", ");
165 for (i=0; i<n; ++i) {
166 if (i > 0) {
167 s.append(delim);
168 }
169 s = s + _toString(array[i]);
170 }
171 }
172 break;
173 case Formattable::kObject:
174 if (f.getObject()->getDynamicClassID() ==
175 CurrencyAmount::getStaticClassID()) {
176 const CurrencyAmount& c = (const CurrencyAmount&) *f.getObject();
177 s = _toString(c.getNumber()) + " " + UnicodeString(c.getISOCurrency());
178 } else {
179 s = UnicodeString("Unknown UObject");
180 }
181 break;
182 default:
183 s = UnicodeString("Unknown Formattable type=") + (int32_t)f.getType();
184 break;
185 }
186 return s;
187 }
188
189 /**
190 * Originally coded this as operator+, but that makes the expression
191 * + char* ambiguous. - liu
192 */
toString(const Formattable & f)193 UnicodeString toString(const Formattable& f) {
194 UnicodeString s((UChar)91/*[*/);
195 s.append(_toString(f));
196 s.append((UChar)0x5d/*]*/);
197 return s;
198 }
199
200 #endif
201
202 // useful when operator+ won't cooperate
toString(int32_t n)203 UnicodeString toString(int32_t n) {
204 return UnicodeString() + (long)n;
205 }
206
207 // stephen - cleaned up 05/05/99
operator +(const UnicodeString & left,char num)208 UnicodeString operator+(const UnicodeString& left, char num)
209 { return left + (long)num; }
operator +(const UnicodeString & left,short num)210 UnicodeString operator+(const UnicodeString& left, short num)
211 { return left + (long)num; }
operator +(const UnicodeString & left,int num)212 UnicodeString operator+(const UnicodeString& left, int num)
213 { return left + (long)num; }
operator +(const UnicodeString & left,unsigned char num)214 UnicodeString operator+(const UnicodeString& left, unsigned char num)
215 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned short num)216 UnicodeString operator+(const UnicodeString& left, unsigned short num)
217 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,unsigned int num)218 UnicodeString operator+(const UnicodeString& left, unsigned int num)
219 { return left + (unsigned long)num; }
operator +(const UnicodeString & left,float num)220 UnicodeString operator+(const UnicodeString& left, float num)
221 { return left + (double)num; }
222
223 //------------------
224
225 // Append a hex string to the target
226 UnicodeString&
appendHex(uint32_t number,int32_t digits,UnicodeString & target)227 IntlTest::appendHex(uint32_t number,
228 int32_t digits,
229 UnicodeString& target)
230 {
231 static const UChar digitString[] = {
232 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
233 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0
234 }; /* "0123456789ABCDEF" */
235
236 switch (digits)
237 {
238 case 8:
239 target += digitString[(number >> 28) & 0xF];
240 case 7:
241 target += digitString[(number >> 24) & 0xF];
242 case 6:
243 target += digitString[(number >> 20) & 0xF];
244 case 5:
245 target += digitString[(number >> 16) & 0xF];
246 case 4:
247 target += digitString[(number >> 12) & 0xF];
248 case 3:
249 target += digitString[(number >> 8) & 0xF];
250 case 2:
251 target += digitString[(number >> 4) & 0xF];
252 case 1:
253 target += digitString[(number >> 0) & 0xF];
254 break;
255 default:
256 target += "**";
257 }
258 return target;
259 }
260
261 // Replace nonprintable characters with unicode escapes
262 UnicodeString&
prettify(const UnicodeString & source,UnicodeString & target)263 IntlTest::prettify(const UnicodeString &source,
264 UnicodeString &target)
265 {
266 int32_t i;
267
268 target.remove();
269 target += "\"";
270
271 for (i = 0; i < source.length(); )
272 {
273 UChar32 ch = source.char32At(i);
274 i += UTF_CHAR_LENGTH(ch);
275
276 if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
277 {
278 if (ch <= 0xFFFF) {
279 target += "\\u";
280 appendHex(ch, 4, target);
281 } else {
282 target += "\\U";
283 appendHex(ch, 8, target);
284 }
285 }
286 else
287 {
288 target += ch;
289 }
290 }
291
292 target += "\"";
293
294 return target;
295 }
296
297 // Replace nonprintable characters with unicode escapes
298 UnicodeString
prettify(const UnicodeString & source,UBool parseBackslash)299 IntlTest::prettify(const UnicodeString &source, UBool parseBackslash)
300 {
301 int32_t i;
302 UnicodeString target;
303 target.remove();
304 target += "\"";
305
306 for (i = 0; i < source.length();)
307 {
308 UChar32 ch = source.char32At(i);
309 i += UTF_CHAR_LENGTH(ch);
310
311 if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
312 {
313 if (parseBackslash) {
314 // If we are preceded by an odd number of backslashes,
315 // then this character has already been backslash escaped.
316 // Delete a backslash.
317 int32_t backslashCount = 0;
318 for (int32_t j=target.length()-1; j>=0; --j) {
319 if (target.charAt(j) == (UChar)92) {
320 ++backslashCount;
321 } else {
322 break;
323 }
324 }
325 if ((backslashCount % 2) == 1) {
326 target.truncate(target.length() - 1);
327 }
328 }
329 if (ch <= 0xFFFF) {
330 target += "\\u";
331 appendHex(ch, 4, target);
332 } else {
333 target += "\\U";
334 appendHex(ch, 8, target);
335 }
336 }
337 else
338 {
339 target += ch;
340 }
341 }
342
343 target += "\"";
344
345 return target;
346 }
347
348 /* IntlTest::setICU_DATA - if the ICU_DATA environment variable is not already
349 * set, try to deduce the directory in which ICU was built,
350 * and set ICU_DATA to "icu/source/data" in that location.
351 * The intent is to allow the tests to have a good chance
352 * of running without requiring that the user manually set
353 * ICU_DATA. Common data isn't a problem, since it is
354 * picked up via a static (build time) reference, but the
355 * tests dynamically load some data.
356 */
setICU_DATA()357 void IntlTest::setICU_DATA() {
358 const char *original_ICU_DATA = getenv("ICU_DATA");
359
360 if (original_ICU_DATA != NULL && *original_ICU_DATA != 0) {
361 /* If the user set ICU_DATA, don't second-guess the person. */
362 return;
363 }
364
365 // U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
366 // to point to the top of the build hierarchy, which may or
367 // may not be the same as the source directory, depending on
368 // the configure options used. At any rate,
369 // set the data path to the built data from this directory.
370 // The value is complete with quotes, so it can be used
371 // as-is as a string constant.
372
373 #if defined (U_TOPBUILDDIR)
374 {
375 static char env_string[] = U_TOPBUILDDIR "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
376 u_setDataDirectory(env_string);
377 return;
378 }
379
380 #else
381 // Use #else so we don't get compiler warnings due to the return above.
382
383 /* On Windows, the file name obtained from __FILE__ includes a full path.
384 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
385 * Change to "wherever\icu\source\data"
386 */
387 {
388 char p[sizeof(__FILE__) + 10];
389 char *pBackSlash;
390 int i;
391
392 strcpy(p, __FILE__);
393 /* We want to back over three '\' chars. */
394 /* Only Windows should end up here, so looking for '\' is safe. */
395 for (i=1; i<=3; i++) {
396 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
397 if (pBackSlash != NULL) {
398 *pBackSlash = 0; /* Truncate the string at the '\' */
399 }
400 }
401
402 if (pBackSlash != NULL) {
403 /* We found and truncated three names from the path.
404 * Now append "source\data" and set the environment
405 */
406 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
407 u_setDataDirectory(p); /* p is "ICU_DATA=wherever\icu\source\data" */
408 return;
409 }
410 else {
411 /* __FILE__ on MSVC7 does not contain the directory */
412 u_setDataDirectory(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
413 return;
414 }
415 }
416 #endif
417
418 /* No location for the data dir was identifiable.
419 * Add other fallbacks for the test data location here if the need arises
420 */
421 }
422
423
424 //--------------------------------------------------------------------------------------
425
426 static const int32_t indentLevel_offset = 3;
427 static const char delim = '/';
428
429 IntlTest* IntlTest::gTest = NULL;
430
431 static int32_t execCount = 0;
432
it_log(UnicodeString message)433 void it_log( UnicodeString message )
434 {
435 if (IntlTest::gTest)
436 IntlTest::gTest->log( message );
437 }
438
it_logln(UnicodeString message)439 void it_logln( UnicodeString message )
440 {
441 if (IntlTest::gTest)
442 IntlTest::gTest->logln( message );
443 }
444
it_logln(void)445 void it_logln( void )
446 {
447 if (IntlTest::gTest)
448 IntlTest::gTest->logln();
449 }
450
it_info(UnicodeString message)451 void it_info( UnicodeString message )
452 {
453 if (IntlTest::gTest)
454 IntlTest::gTest->info( message );
455 }
456
it_infoln(UnicodeString message)457 void it_infoln( UnicodeString message )
458 {
459 if (IntlTest::gTest)
460 IntlTest::gTest->infoln( message );
461 }
462
it_infoln(void)463 void it_infoln( void )
464 {
465 if (IntlTest::gTest)
466 IntlTest::gTest->infoln();
467 }
468
it_err()469 void it_err()
470 {
471 if (IntlTest::gTest)
472 IntlTest::gTest->err();
473 }
474
it_err(UnicodeString message)475 void it_err( UnicodeString message )
476 {
477 if (IntlTest::gTest)
478 IntlTest::gTest->err( message );
479 }
480
it_errln(UnicodeString message)481 void it_errln( UnicodeString message )
482 {
483 if (IntlTest::gTest)
484 IntlTest::gTest->errln( message );
485 }
486
it_dataerr(UnicodeString message)487 void it_dataerr( UnicodeString message )
488 {
489 if (IntlTest::gTest)
490 IntlTest::gTest->dataerr( message );
491 }
492
it_dataerrln(UnicodeString message)493 void it_dataerrln( UnicodeString message )
494 {
495 if (IntlTest::gTest)
496 IntlTest::gTest->dataerrln( message );
497 }
498
IntlTest()499 IntlTest::IntlTest()
500 {
501 caller = NULL;
502 testPath = NULL;
503 LL_linestart = TRUE;
504 errorCount = 0;
505 dataErrorCount = 0;
506 verbose = FALSE;
507 no_err_msg = FALSE;
508 warn_on_missing_data = FALSE;
509 quick = FALSE;
510 leaks = FALSE;
511 testoutfp = stdout;
512 LL_indentlevel = indentLevel_offset;
513 }
514
setCaller(IntlTest * callingTest)515 void IntlTest::setCaller( IntlTest* callingTest )
516 {
517 caller = callingTest;
518 if (caller) {
519 verbose = caller->verbose;
520 no_err_msg = caller->no_err_msg;
521 quick = caller->quick;
522 testoutfp = caller->testoutfp;
523 LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
524 }
525 }
526
callTest(IntlTest & testToBeCalled,char * par)527 UBool IntlTest::callTest( IntlTest& testToBeCalled, char* par )
528 {
529 execCount--; // correct a previously assumed test-exec, as this only calls a subtest
530 testToBeCalled.setCaller( this );
531 return testToBeCalled.runTest( testPath, par );
532 }
533
setPath(char * pathVal)534 void IntlTest::setPath( char* pathVal )
535 {
536 this->testPath = pathVal;
537 }
538
setVerbose(UBool verboseVal)539 UBool IntlTest::setVerbose( UBool verboseVal )
540 {
541 UBool rval = this->verbose;
542 this->verbose = verboseVal;
543 return rval;
544 }
545
setWarnOnMissingData(UBool warn_on_missing_dataVal)546 UBool IntlTest::setWarnOnMissingData( UBool warn_on_missing_dataVal )
547 {
548 UBool rval = this->warn_on_missing_data;
549 this->warn_on_missing_data = warn_on_missing_dataVal;
550 return rval;
551 }
552
setNoErrMsg(UBool no_err_msgVal)553 UBool IntlTest::setNoErrMsg( UBool no_err_msgVal )
554 {
555 UBool rval = this->no_err_msg;
556 this->no_err_msg = no_err_msgVal;
557 return rval;
558 }
559
setQuick(UBool quickVal)560 UBool IntlTest::setQuick( UBool quickVal )
561 {
562 UBool rval = this->quick;
563 this->quick = quickVal;
564 return rval;
565 }
566
setLeaks(UBool leaksVal)567 UBool IntlTest::setLeaks( UBool leaksVal )
568 {
569 UBool rval = this->leaks;
570 this->leaks = leaksVal;
571 return rval;
572 }
573
getErrors(void)574 int32_t IntlTest::getErrors( void )
575 {
576 return errorCount;
577 }
578
getDataErrors(void)579 int32_t IntlTest::getDataErrors( void )
580 {
581 return dataErrorCount;
582 }
583
runTest(char * name,char * par)584 UBool IntlTest::runTest( char* name, char* par )
585 {
586 UBool rval;
587 char* pos = NULL;
588
589 if (name)
590 pos = strchr( name, delim ); // check if name contains path (by looking for '/')
591 if (pos) {
592 testPath = pos+1; // store subpath for calling subtest
593 *pos = 0; // split into two strings
594 }else{
595 testPath = NULL;
596 }
597
598 if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
599 rval = runTestLoop( NULL, par );
600
601 }else if (strcmp( name, "LIST" ) == 0) {
602 this->usage();
603 rval = TRUE;
604
605 }else{
606 rval = runTestLoop( name, par );
607 }
608
609 if (pos)
610 *pos = delim; // restore original value at pos
611 return rval;
612 }
613
614 // call individual tests, to be overriden to call implementations
runIndexedTest(int32_t index,UBool exec,const char * & name,char * par)615 void IntlTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
616 {
617 // to be overriden by a method like:
618 /*
619 switch (index) {
620 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
621 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
622 default: name = ""; break;
623 }
624 */
625 this->errln("*** runIndexedTest needs to be overriden! ***");
626 name = ""; exec = exec; index = index; par = par;
627 }
628
629
runTestLoop(char * testname,char * par)630 UBool IntlTest::runTestLoop( char* testname, char* par )
631 {
632 int32_t index = 0;
633 const char* name;
634 UBool run_this_test;
635 int32_t lastErrorCount;
636 UBool rval = FALSE;
637 UBool lastTestFailed;
638
639 IntlTest* saveTest = gTest;
640 gTest = this;
641 do {
642 this->runIndexedTest( index, FALSE, name, par );
643 if (!name || (name[0] == 0))
644 break;
645 if (!testname) {
646 run_this_test = TRUE;
647 }else{
648 run_this_test = (UBool) (strcmp( name, testname ) == 0);
649 }
650 if (run_this_test) {
651 lastErrorCount = errorCount;
652 execCount++;
653 this->runIndexedTest( index, TRUE, name, par );
654 rval = TRUE; // at least one test has been called
655 char msg[256];
656 if (lastErrorCount == errorCount) {
657 sprintf( msg, "---OK: %s", name );
658 lastTestFailed = FALSE;
659 }else{
660 sprintf(msg, "---ERRORS (%li) in %s", (long)(errorCount-lastErrorCount), name);
661
662 for(int i=0;i<LL_indentlevel;i++) {
663 errorList += " ";
664 }
665 errorList += name;
666 errorList += "\n";
667 lastTestFailed = TRUE;
668 }
669 LL_indentlevel -= 3;
670 if (lastTestFailed) {
671 LL_message( "", TRUE);
672 }
673 LL_message( msg, TRUE);
674 if (lastTestFailed) {
675 LL_message( "", TRUE);
676 }
677 LL_indentlevel += 3;
678 }
679 index++;
680 }while(name);
681
682 gTest = saveTest;
683 return rval;
684 }
685
686
687 /**
688 * Adds given string to the log if we are in verbose mode.
689 */
log(const UnicodeString & message)690 void IntlTest::log( const UnicodeString &message )
691 {
692 if( verbose ) {
693 LL_message( message, FALSE );
694 }
695 }
696
697 /**
698 * Adds given string to the log if we are in verbose mode. Adds a new line to
699 * the given message.
700 */
logln(const UnicodeString & message)701 void IntlTest::logln( const UnicodeString &message )
702 {
703 if( verbose ) {
704 LL_message( message, TRUE );
705 }
706 }
707
logln(void)708 void IntlTest::logln( void )
709 {
710 if( verbose ) {
711 LL_message( "", TRUE );
712 }
713 }
714
715 /**
716 * Unconditionally adds given string to the log.
717 */
info(const UnicodeString & message)718 void IntlTest::info( const UnicodeString &message )
719 {
720 LL_message( message, FALSE );
721 }
722
723 /**
724 * Unconditionally adds given string to the log. Adds a new line to
725 * the given message.
726 */
infoln(const UnicodeString & message)727 void IntlTest::infoln( const UnicodeString &message )
728 {
729 LL_message( message, TRUE );
730 }
731
infoln(void)732 void IntlTest::infoln( void )
733 {
734 LL_message( "", TRUE );
735 }
736
IncErrorCount(void)737 int32_t IntlTest::IncErrorCount( void )
738 {
739 errorCount++;
740 if (caller) caller->IncErrorCount();
741 return errorCount;
742 }
743
IncDataErrorCount(void)744 int32_t IntlTest::IncDataErrorCount( void )
745 {
746 dataErrorCount++;
747 if (caller) caller->IncDataErrorCount();
748 return dataErrorCount;
749 }
750
err()751 void IntlTest::err()
752 {
753 IncErrorCount();
754 }
755
err(const UnicodeString & message)756 void IntlTest::err( const UnicodeString &message )
757 {
758 IncErrorCount();
759 if (!no_err_msg) LL_message( message, FALSE );
760 }
761
errln(const UnicodeString & message)762 void IntlTest::errln( const UnicodeString &message )
763 {
764 IncErrorCount();
765 if (!no_err_msg) LL_message( message, TRUE );
766 }
767
dataerr(const UnicodeString & message)768 void IntlTest::dataerr( const UnicodeString &message )
769 {
770 IncDataErrorCount();
771
772 if (!warn_on_missing_data) {
773 IncErrorCount();
774 }
775
776 if (!no_err_msg) LL_message( message, FALSE );
777 }
778
dataerrln(const UnicodeString & message)779 void IntlTest::dataerrln( const UnicodeString &message )
780 {
781 IncDataErrorCount();
782
783 if (!warn_on_missing_data) {
784 IncErrorCount();
785 }
786
787 if (!no_err_msg) LL_message( message, TRUE );
788 }
789
790 /* convenience functions that include sprintf formatting */
log(const char * fmt,...)791 void IntlTest::log(const char *fmt, ...)
792 {
793 char buffer[4000];
794 va_list ap;
795
796 va_start(ap, fmt);
797 /* sprintf it just to make sure that the information is valid */
798 vsprintf(buffer, fmt, ap);
799 va_end(ap);
800 if( verbose ) {
801 log(UnicodeString(buffer, ""));
802 }
803 }
804
logln(const char * fmt,...)805 void IntlTest::logln(const char *fmt, ...)
806 {
807 char buffer[4000];
808 va_list ap;
809
810 va_start(ap, fmt);
811 /* sprintf it just to make sure that the information is valid */
812 vsprintf(buffer, fmt, ap);
813 va_end(ap);
814 if( verbose ) {
815 logln(UnicodeString(buffer, ""));
816 }
817 }
818
819 /* convenience functions that include sprintf formatting */
info(const char * fmt,...)820 void IntlTest::info(const char *fmt, ...)
821 {
822 char buffer[4000];
823 va_list ap;
824
825 va_start(ap, fmt);
826 /* sprintf it just to make sure that the information is valid */
827 vsprintf(buffer, fmt, ap);
828 va_end(ap);
829 info(UnicodeString(buffer, ""));
830 }
831
infoln(const char * fmt,...)832 void IntlTest::infoln(const char *fmt, ...)
833 {
834 char buffer[4000];
835 va_list ap;
836
837 va_start(ap, fmt);
838 /* sprintf it just to make sure that the information is valid */
839 vsprintf(buffer, fmt, ap);
840 va_end(ap);
841 infoln(UnicodeString(buffer, ""));
842 }
843
err(const char * fmt,...)844 void IntlTest::err(const char *fmt, ...)
845 {
846 char buffer[4000];
847 va_list ap;
848
849 va_start(ap, fmt);
850 vsprintf(buffer, fmt, ap);
851 va_end(ap);
852 err(UnicodeString(buffer, ""));
853 }
854
errln(const char * fmt,...)855 void IntlTest::errln(const char *fmt, ...)
856 {
857 char buffer[4000];
858 va_list ap;
859
860 va_start(ap, fmt);
861 vsprintf(buffer, fmt, ap);
862 va_end(ap);
863 errln(UnicodeString(buffer, ""));
864 }
865
dataerrln(const char * fmt,...)866 void IntlTest::dataerrln(const char *fmt, ...)
867 {
868 char buffer[4000];
869 va_list ap;
870
871 va_start(ap, fmt);
872 vsprintf(buffer, fmt, ap);
873 va_end(ap);
874 dataerrln(UnicodeString(buffer, ""));
875 }
876
printErrors()877 void IntlTest::printErrors()
878 {
879 IntlTest::LL_message(errorList, TRUE);
880 }
881
LL_message(UnicodeString message,UBool newline)882 void IntlTest::LL_message( UnicodeString message, UBool newline )
883 {
884 // string that starts with a LineFeed character and continues
885 // with spaces according to the current indentation
886 static const UChar indentUChars[] = {
887 '\n',
888 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
889 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
890 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
891 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
892 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
893 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
894 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
895 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
896 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
897 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
898 };
899 UnicodeString indent(FALSE, indentUChars, 1 + LL_indentlevel);
900
901 char buffer[10000];
902 int32_t length;
903
904 // stream out the indentation string first if necessary
905 length = indent.extract(1, indent.length(), buffer, sizeof(buffer));
906 if (length > 0) {
907 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
908 }
909
910 // replace each LineFeed by the indentation string
911 message.findAndReplace(UnicodeString((UChar)'\n'), indent);
912
913 // stream out the message
914 length = message.extract(0, message.length(), buffer, sizeof(buffer));
915 if (length > 0) {
916 length = length > 10000 ? 10000 : length;
917 fwrite(buffer, sizeof(*buffer), length, (FILE *)testoutfp);
918 }
919
920 if (newline) {
921 char newLine = '\n';
922 fwrite(&newLine, sizeof(newLine), 1, (FILE *)testoutfp);
923 }
924
925 // A newline usually flushes the buffer, but
926 // flush the message just in case of a core dump.
927 fflush((FILE *)testoutfp);
928 }
929
930 /**
931 * Print a usage message for this test class.
932 */
usage(void)933 void IntlTest::usage( void )
934 {
935 UBool save_verbose = setVerbose( TRUE );
936 logln("Test names:");
937 logln("-----------");
938
939 int32_t index = 0;
940 const char* name = NULL;
941 do{
942 this->runIndexedTest( index, FALSE, name );
943 if (!name) break;
944 logln(name);
945 index++;
946 }while (name && (name[0] != 0));
947 setVerbose( save_verbose );
948 }
949
950
951 // memory leak reporting software will be able to take advantage of the testsuite
952 // being run a second time local to a specific method in order to report only actual leaks
953 UBool
run_phase2(char * name,char * par)954 IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
955 {
956 UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
957 strLeak->append(" for verifying purify filter");
958 return this->runTest( name, par );
959 }
960
961
962 #if UCONFIG_NO_LEGACY_CONVERSION
963 # define TRY_CNV_1 "iso-8859-1"
964 # define TRY_CNV_2 "ibm-1208"
965 #else
966 # define TRY_CNV_1 "iso-8859-7"
967 # define TRY_CNV_2 "sjis"
968 #endif
969
970 int
main(int argc,char * argv[])971 main(int argc, char* argv[])
972 {
973 UBool syntax = FALSE;
974 UBool all = FALSE;
975 UBool verbose = FALSE;
976 UBool no_err_msg = FALSE;
977 UBool quick = TRUE;
978 UBool name = FALSE;
979 UBool leaks = FALSE;
980 UBool warnOnMissingData = FALSE;
981 UBool defaultDataFound = FALSE;
982 UErrorCode errorCode = U_ZERO_ERROR;
983 UConverter *cnv = NULL;
984 const char *warnOrErr = "Failure";
985 UDate startTime, endTime;
986 int32_t diffTime;
987
988 U_MAIN_INIT_ARGS(argc, argv);
989
990 startTime = uprv_getUTCtime();
991
992 for (int i = 1; i < argc; ++i) {
993 if (argv[i][0] == '-') {
994 const char* str = argv[i] + 1;
995 if (strcmp("verbose", str) == 0 ||
996 strcmp("v", str) == 0)
997 verbose = TRUE;
998 else if (strcmp("noerrormsg", str) == 0 ||
999 strcmp("n", str) == 0)
1000 no_err_msg = TRUE;
1001 else if (strcmp("exhaustive", str) == 0 ||
1002 strcmp("e", str) == 0)
1003 quick = FALSE;
1004 else if (strcmp("all", str) == 0 ||
1005 strcmp("a", str) == 0)
1006 all = TRUE;
1007 else if (strcmp("leaks", str) == 0 ||
1008 strcmp("l", str) == 0)
1009 leaks = TRUE;
1010 else if (strcmp("w", str) == 0) {
1011 warnOnMissingData = TRUE;
1012 warnOrErr = "WARNING";
1013 }
1014 else {
1015 syntax = TRUE;
1016 }
1017 }else{
1018 name = TRUE;
1019 }
1020 }
1021
1022 if (!all && !name) {
1023 all = TRUE;
1024 } else if (all && name) {
1025 syntax = TRUE;
1026 }
1027
1028 if (syntax) {
1029 fprintf(stdout,
1030 "### Syntax:\n"
1031 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
1032 "### where options are: verbose (v), all (a), noerrormsg (n), \n"
1033 "### exhaustive (e), leaks (l)"
1034 "### (Specify either -all (shortcut -a) or a test name). \n"
1035 "### -all will run all of the tests.\n"
1036 "### \n"
1037 "### To get a list of the test names type: intltest LIST \n"
1038 "### To run just the utility tests type: intltest utility \n"
1039 "### \n"
1040 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
1041 "### For example to list the utility tests type: intltest utility/LIST \n"
1042 "### To run just the Locale test type: intltest utility/LocaleTest \n"
1043 "### \n"
1044 "### A parameter can be specified for a test by appending '@' and the value \n"
1045 "### to the testname. \n\n");
1046 return 1;
1047 }
1048
1049 UBool all_tests_exist = TRUE;
1050 MajorTestLevel major;
1051 major.setVerbose( verbose );
1052 major.setNoErrMsg( no_err_msg );
1053 major.setQuick( quick );
1054 major.setLeaks( leaks );
1055 major.setWarnOnMissingData( warnOnMissingData );
1056 fprintf(stdout, "-----------------------------------------------\n");
1057 fprintf(stdout, " IntlTest (C++) Test Suite for \n");
1058 fprintf(stdout, " International Components for Unicode %s\n", U_ICU_VERSION);
1059 fprintf(stdout, "-----------------------------------------------\n");
1060 fprintf(stdout, " Options: \n");
1061 fprintf(stdout, " all (a) : %s\n", (all? "On" : "Off"));
1062 fprintf(stdout, " Verbose (v) : %s\n", (verbose? "On" : "Off"));
1063 fprintf(stdout, " No error messages (n) : %s\n", (no_err_msg? "On" : "Off"));
1064 fprintf(stdout, " Exhaustive (e) : %s\n", (!quick? "On" : "Off"));
1065 fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off"));
1066 fprintf(stdout, " Warn on missing data (w) : %s\n", (warnOnMissingData? "On" : "Off"));
1067 fprintf(stdout, "-----------------------------------------------\n");
1068
1069 /* Check whether ICU will initialize without forcing the build data directory into
1070 * the ICU_DATA path. Success here means either the data dll contains data, or that
1071 * this test program was run with ICU_DATA set externally. Failure of this check
1072 * is normal when ICU data is not packaged into a shared library.
1073 *
1074 * Whether or not this test succeeds, we want to cleanup and reinitialize
1075 * with a data path so that data loading from individual files can be tested.
1076 */
1077 u_init(&errorCode);
1078 if (U_FAILURE(errorCode)) {
1079 fprintf(stderr,
1080 "#### Note: ICU Init without build-specific setDataDirectory() failed.\n");
1081 defaultDataFound = FALSE;
1082 }
1083 else {
1084 defaultDataFound = TRUE;
1085 }
1086 u_cleanup();
1087 errorCode = U_ZERO_ERROR;
1088
1089 /* Initialize ICU */
1090 if (!defaultDataFound) {
1091 IntlTest::setICU_DATA(); // Must set data directory before u_init() is called.
1092 }
1093 u_init(&errorCode);
1094 if (U_FAILURE(errorCode)) {
1095 fprintf(stderr,
1096 "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1097 "*** Check the ICU_DATA environment variable and \n"
1098 "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1099 if(warnOnMissingData == 0) {
1100 fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1101 u_cleanup();
1102 return 1;
1103 }
1104 }
1105
1106
1107 // initial check for the default converter
1108 errorCode = U_ZERO_ERROR;
1109 cnv = ucnv_open(0, &errorCode);
1110 if(cnv != 0) {
1111 // ok
1112 ucnv_close(cnv);
1113 } else {
1114 fprintf(stdout,
1115 "*** %s! The default converter [%s] cannot be opened.\n"
1116 "*** Check the ICU_DATA environment variable and\n"
1117 "*** check that the data files are present.\n",
1118 warnOrErr, ucnv_getDefaultName());
1119 if(!warnOnMissingData) {
1120 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1121 return 1;
1122 }
1123 }
1124
1125 // try more data
1126 cnv = ucnv_open(TRY_CNV_2, &errorCode);
1127 if(cnv != 0) {
1128 // ok
1129 ucnv_close(cnv);
1130 } else {
1131 fprintf(stdout,
1132 "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
1133 "*** Check the ICU_DATA environment variable and \n"
1134 "*** check that the data files are present.\n", warnOrErr);
1135 if(!warnOnMissingData) {
1136 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1137 return 1;
1138 }
1139 }
1140
1141 UResourceBundle *rb = ures_open(0, "en", &errorCode);
1142 ures_close(rb);
1143 if(U_FAILURE(errorCode)) {
1144 fprintf(stdout,
1145 "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
1146 "*** Check the ICU_DATA environment variable and \n"
1147 "*** check that the data files are present.\n", warnOrErr);
1148 if(!warnOnMissingData) {
1149 fprintf(stdout, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
1150 return 1;
1151 }
1152 }
1153
1154 Locale originalLocale; // Save the default locale for comparison later on.
1155
1156 /* TODO: Add option to call u_cleanup and rerun tests. */
1157 if (all) {
1158 major.runTest();
1159 if (leaks) {
1160 major.run_phase2( NULL, NULL );
1161 }
1162 }else{
1163 for (int i = 1; i < argc; ++i) {
1164 if (argv[i][0] != '-') {
1165 char* name = argv[i];
1166 fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
1167 char* parameter = strchr( name, '@' );
1168 if (parameter) {
1169 *parameter = 0;
1170 parameter += 1;
1171 }
1172 execCount = 0;
1173 UBool res = major.runTest( name, parameter );
1174 if (leaks && res) {
1175 major.run_phase2( name, parameter );
1176 }
1177 if (!res || (execCount <= 0)) {
1178 fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
1179 all_tests_exist = FALSE;
1180 }
1181 }
1182 }
1183 }
1184
1185 #if !UCONFIG_NO_FORMATTING
1186 CalendarTimeZoneTest::cleanup();
1187 #endif
1188
1189 free(_testDataPath);
1190 _testDataPath = 0;
1191
1192 Locale lastDefaultLocale;
1193 if (originalLocale != lastDefaultLocale) {
1194 major.errln("FAILURE: A test changed the default locale without resetting it.");
1195 }
1196
1197 fprintf(stdout, "\n--------------------------------------\n");
1198 if (major.getErrors() == 0) {
1199 /* Call it twice to make sure that the defaults were reset. */
1200 /* Call it before the OK message to verify proper cleanup. */
1201 u_cleanup();
1202 u_cleanup();
1203
1204 fprintf(stdout, "OK: All tests passed without error.\n");
1205
1206 if (major.getDataErrors() != 0) {
1207 fprintf(stdout, "\t*WARNING* some data-loading errors were ignored by the -w option.\n");
1208 }
1209 }else{
1210 fprintf(stdout, "Errors in total: %ld.\n", (long)major.getErrors());
1211 major.printErrors();
1212
1213
1214 if (major.getDataErrors() != 0) {
1215 fprintf(stdout, "\t*Note* some errors are data-loading related. If the data used is not the \n"
1216 "\tstock ICU data (i.e some have been added or removed), consider using\n"
1217 "\tthe '-w' option to turn these errors into warnings.\n");
1218 }
1219
1220 /* Call afterwards to display errors. */
1221 u_cleanup();
1222 }
1223
1224 fprintf(stdout, "--------------------------------------\n");
1225
1226 if (execCount <= 0) {
1227 fprintf(stdout, "***** Not all called tests actually exist! *****\n");
1228 }
1229 endTime = uprv_getUTCtime();
1230 diffTime = (int32_t)(endTime - startTime);
1231 printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1232 (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1233 (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1234 (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1235 (int)(diffTime%U_MILLIS_PER_SECOND));
1236 return major.getErrors();
1237 }
1238
loadTestData(UErrorCode & err)1239 const char* IntlTest::loadTestData(UErrorCode& err){
1240 if( _testDataPath == NULL){
1241 const char* directory=NULL;
1242 UResourceBundle* test =NULL;
1243 char* tdpath=NULL;
1244 const char* tdrelativepath;
1245
1246 #if defined (U_TOPBUILDDIR)
1247 tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1248 directory = U_TOPBUILDDIR;
1249 #else
1250 tdrelativepath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
1251 directory = pathToDataDirectory();
1252 #endif
1253
1254 tdpath = (char*) malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 100));
1255
1256
1257 /* u_getDataDirectory shoul return \source\data ... set the
1258 * directory to ..\source\data\..\test\testdata\out\testdata
1259 */
1260 strcpy(tdpath, directory);
1261 strcat(tdpath, tdrelativepath);
1262 strcat(tdpath,"testdata");
1263
1264 test=ures_open(tdpath, "testtypes", &err);
1265
1266 if(U_FAILURE(err)){
1267 err = U_FILE_ACCESS_ERROR;
1268 it_errln((UnicodeString)"Could not load testtypes.res in testdata bundle with path " + tdpath + (UnicodeString)" - " + u_errorName(err));
1269 return "";
1270 }
1271 ures_close(test);
1272 _testDataPath = tdpath;
1273 return _testDataPath;
1274 }
1275 return _testDataPath;
1276 }
1277
getTestDataPath(UErrorCode & err)1278 const char* IntlTest::getTestDataPath(UErrorCode& err) {
1279 return loadTestData(err);
1280 }
1281
1282 /* Returns the path to icu/source/test/testdata/ */
getSourceTestData(UErrorCode &)1283 const char *IntlTest::getSourceTestData(UErrorCode& /*err*/) {
1284 const char *srcDataDir = NULL;
1285 #ifdef U_TOPSRCDIR
1286 srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1287 #else
1288 srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1289 FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
1290 if (f) {
1291 /* We're in icu/source/test/intltest/ */
1292 fclose(f);
1293 }
1294 else {
1295 /* We're in icu/source/test/intltest/(Debug|Release) */
1296 srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
1297 }
1298 #endif
1299 return srcDataDir;
1300 }
1301
1302 const char* IntlTest::fgDataDir = NULL;
1303
1304 /* returns the path to icu/source/data */
pathToDataDirectory()1305 const char * IntlTest::pathToDataDirectory()
1306 {
1307
1308 if(fgDataDir != NULL) {
1309 return fgDataDir;
1310 }
1311
1312 /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
1313 // to point to the top of the build hierarchy, which may or
1314 // may not be the same as the source directory, depending on
1315 // the configure options used. At any rate,
1316 // set the data path to the built data from this directory.
1317 // The value is complete with quotes, so it can be used
1318 // as-is as a string constant.
1319 */
1320 #if defined (U_TOPSRCDIR)
1321 {
1322 fgDataDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1323 }
1324 #else
1325
1326 /* On Windows, the file name obtained from __FILE__ includes a full path.
1327 * This file is "wherever\icu\source\test\cintltst\cintltst.c"
1328 * Change to "wherever\icu\source\data"
1329 */
1330 {
1331 static char p[sizeof(__FILE__) + 10];
1332 char *pBackSlash;
1333 int i;
1334
1335 strcpy(p, __FILE__);
1336 /* We want to back over three '\' chars. */
1337 /* Only Windows should end up here, so looking for '\' is safe. */
1338 for (i=1; i<=3; i++) {
1339 pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1340 if (pBackSlash != NULL) {
1341 *pBackSlash = 0; /* Truncate the string at the '\' */
1342 }
1343 }
1344
1345 if (pBackSlash != NULL) {
1346 /* We found and truncated three names from the path.
1347 * Now append "source\data" and set the environment
1348 */
1349 strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
1350 fgDataDir = p;
1351 }
1352 else {
1353 /* __FILE__ on MSVC7 does not contain the directory */
1354 FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1355 if (file) {
1356 fclose(file);
1357 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1358 }
1359 else {
1360 fgDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
1361 }
1362 }
1363 }
1364 #endif
1365
1366 return fgDataDir;
1367
1368 }
1369
1370 /*
1371 * This is a variant of cintltst/ccolltst.c:CharsToUChars().
1372 * It converts a character string into a UnicodeString, with
1373 * unescaping \u sequences.
1374 */
CharsToUnicodeString(const char * chars)1375 UnicodeString CharsToUnicodeString(const char* chars)
1376 {
1377 UnicodeString str(chars, ""); // Invariant conversion
1378 return str.unescape();
1379 }
1380
ctou(const char * chars)1381 UnicodeString ctou(const char* chars) {
1382 return CharsToUnicodeString(chars);
1383 }
1384
1385 #define RAND_M (714025)
1386 #define RAND_IA (1366)
1387 #define RAND_IC (150889)
1388
1389 static int32_t RAND_SEED;
1390
1391 /**
1392 * Returns a uniform random value x, with 0.0 <= x < 1.0. Use
1393 * with care: Does not return all possible values; returns one of
1394 * 714,025 values, uniformly spaced. However, the period is
1395 * effectively infinite. See: Numerical Recipes, section 7.1.
1396 *
1397 * @param seedp pointer to seed. Set *seedp to any negative value
1398 * to restart the sequence.
1399 */
random(int32_t * seedp)1400 float IntlTest::random(int32_t* seedp) {
1401 static int32_t iy, ir[98];
1402 static UBool first=TRUE;
1403 int32_t j;
1404 if (*seedp < 0 || first) {
1405 first = FALSE;
1406 if ((*seedp=(RAND_IC-(*seedp)) % RAND_M) < 0) *seedp = -(*seedp);
1407 for (j=1;j<=97;++j) {
1408 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1409 ir[j]=(*seedp);
1410 }
1411 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1412 iy=(*seedp);
1413 }
1414 j=(int32_t)(1 + 97.0*iy/RAND_M);
1415 U_ASSERT(j>=1 && j<=97);
1416 iy=ir[j];
1417 *seedp=(RAND_IA*(*seedp)+RAND_IC) % RAND_M;
1418 ir[j]=(*seedp);
1419 return (float) iy/RAND_M;
1420 }
1421
1422 /**
1423 * Convenience method using a global seed.
1424 */
random()1425 float IntlTest::random() {
1426 return random(&RAND_SEED);
1427 }
1428
toHex(int32_t i)1429 static inline UChar toHex(int32_t i) {
1430 return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10)));
1431 }
1432
escape(const UnicodeString & s,UnicodeString & result)1433 static UnicodeString& escape(const UnicodeString& s, UnicodeString& result) {
1434 for (int32_t i=0; i<s.length(); ++i) {
1435 UChar c = s[i];
1436 if (c <= (UChar)0x7F) {
1437 result += c;
1438 } else {
1439 result += (UChar)0x5c;
1440 result += (UChar)0x75;
1441 result += toHex((c >> 12) & 0xF);
1442 result += toHex((c >> 8) & 0xF);
1443 result += toHex((c >> 4) & 0xF);
1444 result += toHex( c & 0xF);
1445 }
1446 }
1447 return result;
1448 }
1449
1450 #define VERBOSE_ASSERTIONS
1451
assertTrue(const char * message,UBool condition,UBool quiet)1452 UBool IntlTest::assertTrue(const char* message, UBool condition, UBool quiet) {
1453 if (!condition) {
1454 errln("FAIL: assertTrue() failed: %s", message);
1455 } else if (!quiet) {
1456 logln("Ok: %s", message);
1457 }
1458 return condition;
1459 }
1460
assertFalse(const char * message,UBool condition,UBool quiet)1461 UBool IntlTest::assertFalse(const char* message, UBool condition, UBool quiet) {
1462 if (condition) {
1463 errln("FAIL: assertFalse() failed: %s", message);
1464 } else if (!quiet) {
1465 logln("Ok: %s", message);
1466 }
1467 return !condition;
1468 }
1469
assertSuccess(const char * message,UErrorCode ec)1470 UBool IntlTest::assertSuccess(const char* message, UErrorCode ec) {
1471 if (U_FAILURE(ec)) {
1472 errln("FAIL: %s (%s)", message, u_errorName(ec));
1473 return FALSE;
1474 }
1475 return TRUE;
1476 }
1477
assertEquals(const char * message,const UnicodeString & expected,const UnicodeString & actual)1478 UBool IntlTest::assertEquals(const char* message,
1479 const UnicodeString& expected,
1480 const UnicodeString& actual) {
1481 if (expected != actual) {
1482 errln((UnicodeString)"FAIL: " + message + "; got " +
1483 prettify(actual) +
1484 "; expected " + prettify(expected));
1485 return FALSE;
1486 }
1487 #ifdef VERBOSE_ASSERTIONS
1488 else {
1489 logln((UnicodeString)"Ok: " + message + "; got " + prettify(actual));
1490 }
1491 #endif
1492 return TRUE;
1493 }
1494
assertEquals(const char * message,const char * expected,const char * actual)1495 UBool IntlTest::assertEquals(const char* message,
1496 const char* expected,
1497 const char* actual) {
1498 if (uprv_strcmp(expected, actual) != 0) {
1499 errln((UnicodeString)"FAIL: " + message + "; got \"" +
1500 actual +
1501 "\"; expected \"" + expected + "\"");
1502 return FALSE;
1503 }
1504 #ifdef VERBOSE_ASSERTIONS
1505 else {
1506 logln((UnicodeString)"Ok: " + message + "; got \"" + actual + "\"");
1507 }
1508 #endif
1509 return TRUE;
1510 }
1511
1512 #if !UCONFIG_NO_FORMATTING
assertEquals(const char * message,const Formattable & expected,const Formattable & actual)1513 UBool IntlTest::assertEquals(const char* message,
1514 const Formattable& expected,
1515 const Formattable& actual) {
1516 if (expected != actual) {
1517 errln((UnicodeString)"FAIL: " + message + "; got " +
1518 toString(actual) +
1519 "; expected " + toString(expected));
1520 return FALSE;
1521 }
1522 #ifdef VERBOSE_ASSERTIONS
1523 else {
1524 logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
1525 }
1526 #endif
1527 return TRUE;
1528 }
1529 #endif
1530
1531 static char ASSERT_BUF[256];
1532
extractToAssertBuf(const UnicodeString & message)1533 static const char* extractToAssertBuf(const UnicodeString& message) {
1534 UnicodeString buf;
1535 escape(message, buf);
1536 buf.extract(0, 0x7FFFFFFF, ASSERT_BUF, sizeof(ASSERT_BUF)-1, 0);
1537 ASSERT_BUF[sizeof(ASSERT_BUF)-1] = 0;
1538 return ASSERT_BUF;
1539 }
1540
assertTrue(const UnicodeString & message,UBool condition,UBool quiet)1541 UBool IntlTest::assertTrue(const UnicodeString& message, UBool condition, UBool quiet) {
1542 return assertTrue(extractToAssertBuf(message), condition, quiet);
1543 }
1544
assertFalse(const UnicodeString & message,UBool condition,UBool quiet)1545 UBool IntlTest::assertFalse(const UnicodeString& message, UBool condition, UBool quiet) {
1546 return assertFalse(extractToAssertBuf(message), condition, quiet);
1547 }
1548
assertSuccess(const UnicodeString & message,UErrorCode ec)1549 UBool IntlTest::assertSuccess(const UnicodeString& message, UErrorCode ec) {
1550 return assertSuccess(extractToAssertBuf(message), ec);
1551 }
1552
assertEquals(const UnicodeString & message,const UnicodeString & expected,const UnicodeString & actual)1553 UBool IntlTest::assertEquals(const UnicodeString& message,
1554 const UnicodeString& expected,
1555 const UnicodeString& actual) {
1556 return assertEquals(extractToAssertBuf(message), expected, actual);
1557 }
1558
assertEquals(const UnicodeString & message,const char * expected,const char * actual)1559 UBool IntlTest::assertEquals(const UnicodeString& message,
1560 const char* expected,
1561 const char* actual) {
1562 return assertEquals(extractToAssertBuf(message), expected, actual);
1563 }
1564 //--------------------------------------------------------------------
1565 // Time bomb - allows temporary behavior that expires at a given
1566 // release
1567 //--------------------------------------------------------------------
1568
isICUVersionAtLeast(const UVersionInfo x)1569 UBool IntlTest::isICUVersionAtLeast(const UVersionInfo x) {
1570 UVersionInfo v;
1571 u_getVersion(v);
1572 return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0);
1573 }
1574
1575 #if !UCONFIG_NO_FORMATTING
assertEquals(const UnicodeString & message,const Formattable & expected,const Formattable & actual)1576 UBool IntlTest::assertEquals(const UnicodeString& message,
1577 const Formattable& expected,
1578 const Formattable& actual) {
1579 return assertEquals(extractToAssertBuf(message), expected, actual);
1580 }
1581 #endif
1582
1583 /*
1584 * Hey, Emacs, please set the following:
1585 *
1586 * Local Variables:
1587 * indent-tabs-mode: nil
1588 * End:
1589 *
1590 */
1591