home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / intltest.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  23.9 KB  |  907 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright Taligent, Inc.,  1997                                       *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1998     *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  10. *                                                                             *
  11. *******************************************************************************
  12. */
  13.  
  14. /*
  15.  * IntlTest in Java is Copyright (c) 1997 Sun Microsystems, Inc. 
  16.  * All Rights Reserved.
  17.  */ 
  18.  
  19. /**
  20.  * IntlTest is a base class for tests.
  21.  * It is modelled according to, but not exactly similar to, 
  22.  *    JavaSoft's test class with the same name.
  23.  */
  24.  
  25.  
  26. #include <limits.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <iostream.h>
  31. #include <assert.h>
  32.  
  33. #include "utypes.h"
  34. #include "unistr.h"
  35. #include "coll.h"
  36. #include "smpdtfmt.h"
  37.  
  38. #include "intltest.h"
  39. #include "itmajor.h"
  40.  
  41. #ifdef XP_MAC
  42. #include <console.h>
  43. #include "Files.h"
  44. #endif
  45. static char* _testDirectory=NULL;
  46. //-----------------------------------------------------------------------------
  47. //convenience classes to ease porting code that uses the Java
  48. //string-concatenation operator (moved from findword test by rtg)
  49.  
  50. // [LIU] Just to get things working
  51. UnicodeString
  52. UCharToUnicodeString(UChar c)
  53. { return UnicodeString(c); }
  54.  
  55. // [LIU] Just to get things working
  56. UnicodeString 
  57. operator+(const UnicodeString& left, 
  58.       const UnicodeString& right)
  59. {
  60.   UnicodeString str(left);
  61.   str += right;
  62.   return str;
  63. }
  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, "%d", 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, "%u", num);
  87.   assert(danger == 'p');
  88.   
  89.   return left + buffer;
  90. }
  91.  
  92. // [LIU] Just to get things working
  93. UnicodeString
  94. operator+(const UnicodeString& left, 
  95.       double num)
  96. {
  97.   char buffer[64];   // was 32, made it arbitrarily bigger (rtg)
  98.   char danger = 'p'; // guard against overrunning the buffer (rtg)
  99.   
  100.   sprintf(buffer, "%.30g", num); // nos changed from 99 to 30
  101.   assert(danger == 'p');
  102.   
  103.   return left + buffer;
  104. }
  105.  
  106. /**
  107.  * Originally coded this as operator+, but that makes the expression
  108.  * + char* ambiguous. - liu
  109.  */
  110. UnicodeString toString(const Formattable& f) {
  111.     UnicodeString s;
  112.     switch (f.getType()) {
  113.     case Formattable::kDate:
  114.         {
  115.             UErrorCode status = U_ZERO_ERROR;
  116.             SimpleDateFormat fmt(status);
  117.             if (U_SUCCESS(status)) {
  118.                 FieldPosition pos;
  119.                 fmt.format(f.getDate(), s, pos);
  120.                 s.insert(0, "[Date:");
  121.                 s.insert(s.length(), ']');
  122.             } else {
  123.                 s = UnicodeString("[Error creating date format]");
  124.             }
  125.         }
  126.         break;
  127.     case Formattable::kDouble:
  128.         s = UnicodeString("[Double:") + f.getDouble() + "]";
  129.         break;
  130.     case Formattable::kLong:
  131.         s = UnicodeString("[Long:") + f.getLong() + "]";
  132.         break;
  133.     case Formattable::kString:
  134.         f.getString(s);
  135.         s.insert(0, "[String:");
  136.         s.insert(s.length(), ']');
  137.         break;
  138.     case Formattable::kArray:
  139.         {
  140.             int32_t i, n;
  141.             const Formattable* array = f.getArray(n);
  142.             s.insert(0, UnicodeString("[Array:"));
  143.             UnicodeString delim(", ");
  144.             for (i=0; i<n; ++i) {
  145.                 if (i > 0) {
  146.                     s.append(delim);
  147.                 }
  148.                 s = s + toString(array[i]);
  149.             }
  150.             s.append(UChar(']'));
  151.         }
  152.         break;
  153.     }
  154.     return s;
  155. }
  156.  
  157. // stephen - cleaned up 05/05/99
  158. UnicodeString operator+(const UnicodeString& left, char num)  
  159. { return left + (long)num; }
  160. UnicodeString operator+(const UnicodeString& left, short num)  
  161. { return left + (long)num; }
  162. UnicodeString operator+(const UnicodeString& left, int num)      
  163. { return left + (long)num; }
  164. UnicodeString operator+(const UnicodeString& left, unsigned char num)  
  165. { return left + (unsigned long)num; }
  166. UnicodeString operator+(const UnicodeString& left, unsigned short num)  
  167. { return left + (unsigned long)num; }
  168. UnicodeString operator+(const UnicodeString& left, unsigned int num)      
  169. { return left + (unsigned long)num; }
  170. UnicodeString operator+(const UnicodeString& left, float num)      
  171. { return left + (double)num; }
  172.  
  173. //------------------  
  174.  
  175. // used for collation result reporting, defined here for convenience
  176. // (maybe moved later)
  177. void 
  178. IntlTest::reportCResult( UnicodeString &source, UnicodeString &target,
  179.              CollationKey &sourceKey, CollationKey &targetKey,
  180.              Collator::EComparisonResult compareResult,
  181.              Collator::EComparisonResult keyResult,
  182.                          Collator::EComparisonResult expectedResult )
  183. {
  184.   if (expectedResult < -1 || expectedResult > 1)
  185.     {
  186.       errln("***** invalid call to reportCResult ****");
  187.       return;
  188.     }
  189.   
  190.   if (compareResult != expectedResult)
  191.     {
  192.       UnicodeString msg1("compare("), msg2(", "), msg3(") returned "), msg4("; expected ");
  193.       UnicodeString prettySource, prettyTarget, sExpect, sResult;
  194.       
  195.       prettify(source, prettySource);
  196.       prettify(target, prettyTarget);
  197.       appendCompareResult(compareResult, sResult);
  198.       appendCompareResult(expectedResult, sExpect);
  199.       
  200.       errln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult + msg4 + sExpect);
  201.     }
  202.   
  203.   if (keyResult != expectedResult)
  204.     {
  205.       UnicodeString msg1("key("), msg2(").compareTo(key("), msg3(")) returned "), msg4("; expected ");
  206.       UnicodeString prettySource, prettyTarget, sExpect, sResult;
  207.       
  208.       prettify(source, prettySource);
  209.       prettify(target, prettyTarget);
  210.       appendCompareResult(keyResult, sResult);
  211.       appendCompareResult(expectedResult, sExpect);
  212.       
  213.       errln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult + msg4 + sExpect);
  214.       
  215.       msg1 = "  ";
  216.       msg2 = " vs. ";
  217.       
  218.       prettify(sourceKey, prettySource);
  219.       prettify(targetKey, prettyTarget);
  220.       
  221.       errln(msg1 + prettySource + msg2 + prettyTarget);
  222.     }
  223. }
  224.  
  225. // Append a hex string to the target
  226. UnicodeString& 
  227. IntlTest::appendHex(uint32_t number, 
  228.             int8_t digits, 
  229.             UnicodeString& target)
  230. {
  231.   static const UnicodeString digitString("0123456789ABCDEF");
  232.  
  233.   switch (digits)
  234.     {
  235.     case 8:
  236.       target += digitString[(number >> 28) & 0xF];
  237.  
  238.     case 7:
  239.       target += digitString[(number >> 24) & 0xF];
  240.  
  241.     case 6:
  242.       target += digitString[(number >> 20) & 0xF];
  243.  
  244.     case 5:
  245.       target += digitString[(number >> 16) & 0xF];
  246.  
  247.     case 4:
  248.       target += digitString[(number >> 12) & 0xF];
  249.  
  250.     case 3:
  251.       target += digitString[(number >>  8) & 0xF];
  252.  
  253.     case 2:
  254.       target += digitString[(number >>  4) & 0xF];
  255.  
  256.     case 1:
  257.       target += digitString[(number >>  0) & 0xF];
  258.       break;
  259.     
  260.     default:
  261.       target += "**";
  262.     }
  263.  
  264.   return target;
  265. }
  266.  
  267. UnicodeString& 
  268. IntlTest::appendCompareResult(Collator::EComparisonResult result, 
  269.                   UnicodeString& target)
  270. {
  271.   if (result == Collator::LESS)
  272.     {
  273.       target += "LESS";
  274.     }
  275.   else if (result == Collator::EQUAL)
  276.     {
  277.       target += "EQUAL";
  278.     }
  279.   else if (result == Collator::GREATER)
  280.     {
  281.       target += "GREATER";
  282.     }
  283.   else
  284.     {
  285.       UnicodeString huh = "?";
  286.  
  287.       target += (huh + (int32_t)result);
  288.     }
  289.  
  290.   return target;
  291. }
  292.  
  293. // Replace nonprintable characters with unicode escapes
  294. UnicodeString& 
  295. IntlTest::prettify(const UnicodeString &source, 
  296.            UnicodeString &target)
  297. {
  298.   int32_t i;
  299.   
  300.   target.remove();
  301.   target += "\"";
  302.   
  303.   for (i = 0; i < source.size(); i += 1)
  304.     {
  305.       UChar ch = source[i];
  306.  
  307.       if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| ch > 0x7E)
  308.     {
  309.       target += "\\u";
  310.       appendHex(ch, 4, target);
  311.         }
  312.       else
  313.     {
  314.       target += ch;
  315.         }
  316.     }
  317.  
  318.   target += "\"";
  319.  
  320.   return target;
  321. }
  322.  
  323. // Produce a printable representation of a CollationKey
  324. UnicodeString &IntlTest::prettify(const CollationKey &source, UnicodeString &target)
  325. {
  326.     int32_t i, byteCount;
  327.     const uint8_t *bytes = source.getByteArray(byteCount);
  328.  
  329.     target.remove();
  330.     target += "[";
  331.  
  332.     for (i = 0; i < byteCount; i += 1)
  333.     {
  334.         appendHex(bytes[i], 2, target);
  335.         target += " ";
  336.     }
  337.  
  338.     target += "]";
  339.  
  340.     return target;
  341. }
  342.  
  343. void
  344. IntlTest::pathnameInContext( char* fullname, int32_t maxsize, const char* relPath ) //nosmac
  345. {
  346.     char* mainDir;
  347.     char  sepChar;
  348.     const char inpSepChar = '|';
  349.     
  350.     #if defined(_WIN32) || defined(WIN32) || defined(__OS2__) || defined(OS2)
  351.         char mainDirBuffer[200];
  352.         mainDir = getenv("ICU_DATA");
  353.         if(mainDir!=NULL) {
  354.             strcpy(mainDirBuffer, mainDir);
  355.             strcat(mainDirBuffer, "..\\..");
  356.         } else {
  357.             mainDirBuffer[0]='\0';
  358.         }
  359.         mainDir=mainDirBuffer;
  360.         sepChar = '\\';
  361.     #elif defined(_AIX) || defined(SOLARIS) || defined(LINUX) || defined(HPUX)
  362.         mainDir = getenv("HOME");
  363.         sepChar = '/';
  364.     #elif defined(XP_MAC)
  365.         Str255 volName;
  366.         int16_t volNum;
  367.         OSErr err = GetVol( volName, &volNum );
  368.         if (err != noErr) volName[0] = 0;
  369.         mainDir = (char*) &(volName[1]);
  370.         mainDir[volName[0]] = 0;
  371.         sepChar = ':';
  372.     #else
  373.         mainDir = "";
  374.         sepChar = '\\';
  375.     #endif
  376.     char sepString[] = { sepChar, 0 };
  377.     
  378.     if (relPath[0] == '|') relPath++;
  379.     int32_t lenMainDir = strlen( mainDir );
  380.     int32_t lenRelPath = strlen( relPath );
  381.     if (maxsize < lenMainDir + lenRelPath + 2) { fullname[0] = 0; return; }
  382.     strcpy( fullname, mainDir );
  383.     strcat( fullname, sepString );
  384.     strcat( fullname, relPath );
  385.     char* tmp = strchr( fullname, inpSepChar );
  386.     while (tmp) {
  387.         *tmp = sepChar;
  388.         tmp = strchr( tmp+1, inpSepChar );
  389.     }
  390.  
  391. }
  392.  
  393. /**
  394.  * Functions to get and set the directory containing the Test files.
  395.  */
  396.  
  397. const char*
  398. IntlTest::getTestDirectory()
  399. {
  400.        if (_testDirectory == NULL) 
  401.     {
  402.       setTestDirectory("icu|source|test|testdata|");
  403.     }
  404.     return _testDirectory;
  405. }
  406.  
  407. void
  408. IntlTest::setTestDirectory(const char* newDir) 
  409. {
  410.     char newTestDir[256];
  411.     IntlTest::pathnameInContext(newTestDir, sizeof(newTestDir), newDir); 
  412.     if(_testDirectory != NULL)
  413.         free(_testDirectory);
  414.     _testDirectory = (char*) malloc(sizeof(char) * (strlen(newTestDir) + 1));
  415.     strcpy(_testDirectory, newTestDir);
  416. }
  417.  
  418. //--------------------------------------------------------------------------------------
  419.  
  420. static const int32_t indentLevel_offset = 3;
  421. static const char delim = '/';
  422.  
  423. IntlTest* IntlTest::gTest = NULL;
  424.  
  425. static int32_t execCount = 0;
  426.  
  427. void it_log( UnicodeString message )
  428. {
  429.     if (IntlTest::gTest) IntlTest::gTest->log( message );
  430. }
  431.     
  432. void it_logln( UnicodeString message )
  433. {
  434.     if (IntlTest::gTest) IntlTest::gTest->logln( message );
  435. }
  436.     
  437. void it_logln( void )
  438. {
  439.     if (IntlTest::gTest) IntlTest::gTest->logln();
  440. }
  441.     
  442. void it_err()
  443. {
  444.     if (IntlTest::gTest) IntlTest::gTest->err();
  445. }
  446.         
  447. void it_err( UnicodeString message )
  448. {
  449.     if (IntlTest::gTest) IntlTest::gTest->err( message );
  450. }
  451.     
  452. void it_errln( UnicodeString message )
  453. {
  454.     if (IntlTest::gTest) IntlTest::gTest->errln( message );
  455. }
  456.  
  457. IntlTest& operator<<(IntlTest& test, const UnicodeString&   string)
  458. {
  459.     if (&test == NULL) return *((IntlTest*) NULL);
  460.     test.log( string );
  461.     return test;
  462. }
  463.  
  464. IntlTest& operator<<(IntlTest& test, const char*    string)
  465. {
  466.     if (&test == NULL) return *((IntlTest*) NULL);
  467.     test.log( string );
  468.     return test;
  469. }
  470.  
  471. IntlTest& operator<<(IntlTest& test, const int32_t num)
  472. {
  473.     if (&test == NULL) return *((IntlTest*) NULL);
  474.     char convert[20];
  475.     sprintf( convert, "%li", num );
  476.     test.log( convert );
  477.     return test;
  478. }
  479.  
  480. //inline _CRTIMP ostream& __cdecl endl(ostream& _outs) { return _outs << '\n' << flush; }
  481. //inline ostream& ostream::operator<<(ostream& (__cdecl * _f)(ostream&)) { (*_f)(*this); return *this; }
  482.  
  483. IntlTest& endl( IntlTest& test )
  484. {
  485.     test.logln();
  486.     return test;
  487. }
  488.  
  489. IntlTest& operator<<(IntlTest& test,  IntlTest& ( * _f)(IntlTest&))
  490. {
  491.     (*_f)(test);
  492.     return test;
  493. }
  494.  
  495.  
  496. IntlTest::IntlTest()
  497. {
  498.     caller = NULL;
  499.     path = NULL;
  500.     LL_linestart = TRUE;
  501.     errorCount = 0;
  502.     verbose = FALSE;
  503.     no_err_msg = FALSE;
  504.     quick = FALSE;
  505.     leaks = FALSE;
  506.     testout = &cout;
  507.     LL_indentlevel = indentLevel_offset;
  508. }
  509.  
  510. void IntlTest::setCaller( IntlTest* callingTest )
  511. {
  512.     caller = callingTest;
  513.     if (caller) {
  514.         verbose = caller->verbose;
  515.         no_err_msg = caller->no_err_msg;
  516.         quick = caller->quick;
  517.         testout = caller->testout;
  518.         LL_indentlevel = caller->LL_indentlevel + indentLevel_offset;
  519.     }
  520. }
  521.  
  522. bool_t IntlTest::callTest( IntlTest& testToBeCalled, char* par )
  523. {
  524.     execCount--; // correct a previously assumed test-exec, as this only calls a subtest
  525.     testToBeCalled.setCaller( this );
  526.     return testToBeCalled.runTest( path, par );
  527. }
  528.  
  529. void IntlTest::setPath( char* path )
  530. {
  531.     this->path = path;
  532. }
  533.  
  534. bool_t IntlTest::setVerbose( bool_t verbose )
  535. {
  536.     bool_t rval = this->verbose;
  537.     this->verbose = verbose;
  538.     return rval;
  539. }
  540.  
  541. bool_t IntlTest::setNoErrMsg( bool_t no_err_msg )
  542. {
  543.     bool_t rval = this->no_err_msg;
  544.     this->no_err_msg = no_err_msg;
  545.     return rval;
  546. }
  547.  
  548. bool_t IntlTest::setQuick( bool_t quick )
  549. {
  550.     bool_t rval = this->quick;
  551.     this->quick = quick;
  552.     return rval;
  553. }
  554.  
  555. bool_t IntlTest::setLeaks( bool_t leaks )
  556. {
  557.     bool_t rval = this->leaks;
  558.     this->leaks = leaks;
  559.     return rval;
  560. }
  561.  
  562. int32_t IntlTest::getErrors( void )
  563. {
  564.     return errorCount;
  565. }
  566.  
  567. bool_t IntlTest::runTest( char* name, char* par )
  568. {
  569.     bool_t rval;
  570.     char* pos = NULL;
  571.  
  572.     if (name) pos = strchr( name, delim ); // check if name contains path (by looking for '/')
  573.     if (pos) {
  574.         path = pos+1;   // store subpath for calling subtest
  575.         *pos = 0;       // split into two strings
  576.     }else{
  577.         path = NULL;
  578.     }
  579.  
  580.     if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
  581.         rval = runTestLoop( NULL, NULL );
  582.  
  583.     }else if (strcmp( name, "LIST" ) == 0) {
  584.         this->usage();
  585.         rval = TRUE;
  586.  
  587.     }else{
  588.         rval = runTestLoop( name, par );
  589.     }
  590.  
  591.     if (pos) *pos = delim;  // restore original value at pos
  592.     return rval;
  593. }
  594.  
  595. // call individual tests, to be overriden to call implementations
  596. void IntlTest::runIndexedTest( int32_t index, bool_t exec, char* &name, char* par )
  597. {
  598.     // to be overriden by a method like:
  599.     /*
  600.     switch (index) {
  601.         case 0: name = "First Test"; if (exec) FirstTest( par ); break;
  602.         case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
  603.         default: name = ""; break;
  604.     }
  605.     */
  606.     this->errln("*** runIndexedTest needs to be overriden! ***");
  607.     name = ""; exec = exec; index = index; par = par;
  608. }
  609.  
  610.  
  611. bool_t IntlTest::runTestLoop( char* testname, char* par )
  612. {
  613.     int32_t    index = 0;
  614.     char*   name;
  615.     bool_t  run_this_test;
  616.     int32_t    lastErrorCount;
  617.     bool_t  rval = FALSE;
  618.     
  619.     IntlTest* saveTest = gTest;
  620.     gTest = this;
  621.     do {
  622.         this->runIndexedTest( index, FALSE, name );
  623.         if (!name || (name[0] == 0)) break;
  624.         if (!testname) {
  625.             run_this_test = TRUE;
  626.         }else{
  627.             run_this_test = (bool_t) (strcmp( name, testname ) == 0);
  628.         }
  629.         if (run_this_test) {
  630.             lastErrorCount = errorCount;
  631.             execCount++;
  632.             this->runIndexedTest( index, TRUE, name, par );
  633.             rval = TRUE; // at least one test has been called
  634.             char msg[256];
  635.             if (lastErrorCount == errorCount) {
  636.                 sprintf( msg, "---OK:   %s", name );
  637.             }else{
  638.                 sprintf( msg, "---ERRORS (%li) in %s", (errorCount-lastErrorCount), name );
  639.             }
  640.             LL_indentlevel -= 3;
  641.             LL_message( "", TRUE); 
  642.             LL_message( msg, TRUE); 
  643.             LL_message( "", TRUE);
  644.             LL_indentlevel += 3;
  645.         }
  646.         index++;
  647.     }while(name);
  648.  
  649.     gTest = saveTest;
  650.     return rval;
  651. }
  652.  
  653.  
  654. /**
  655. * Adds given string to the log if we are in verbose mode.
  656. */
  657. void IntlTest::log( UnicodeString message )
  658. {
  659.     if( verbose ) {
  660.         LL_message( message, FALSE );
  661.     }
  662. }
  663.  
  664. /**
  665. * Adds given string to the log if we are in verbose mode. Adds a new line to
  666. * the given message.
  667. */
  668. void IntlTest::logln( UnicodeString message )
  669. {
  670.     if( verbose ) {
  671.         LL_message( message, TRUE );
  672.     }
  673. }
  674.  
  675. void IntlTest::logln( void )
  676. {
  677.     if( verbose ) {
  678.         LL_message( "", TRUE );
  679.     }
  680. }
  681.  
  682. int32_t IntlTest::IncErrorCount( void )
  683. {
  684.     errorCount++;
  685.     if (caller) caller->IncErrorCount();
  686.     return errorCount;
  687. }
  688.  
  689. void IntlTest::err() {
  690.     IncErrorCount();
  691. }
  692.     
  693. void IntlTest::err( UnicodeString message )
  694. {
  695.     IncErrorCount();
  696.     if (!no_err_msg) LL_message( message, FALSE );
  697. }
  698.  
  699. void IntlTest::errln( UnicodeString message )
  700. {
  701.     IncErrorCount();
  702.     if (!no_err_msg) LL_message( message, TRUE );
  703. }
  704.  
  705. void IntlTest::LL_message( UnicodeString message, bool_t newline )
  706. {
  707.     UChar     c;
  708.  
  709.     ostream&    stream = *testout;
  710.     int32_t        saveFlags = stream.flags();
  711.     stream << hex;
  712.  
  713.     int32_t len = message.size();
  714.     UTextOffset pos = 0;
  715.     bool_t gen = FALSE;
  716.     do{
  717.         if (LL_linestart) {
  718.             stream << '\n';
  719.             for (int32_t i = 0; i < LL_indentlevel; i++) stream << ' ';
  720.             gen = TRUE;
  721.             LL_linestart = FALSE;
  722.         }
  723.         if (pos >= len) break;
  724.  
  725.         c = message[pos++];
  726.         if (c >= ' ' && c <= '~') {
  727.             stream << (char)c;
  728.             gen = TRUE;
  729.         }else if (c == '\n') {
  730.             LL_linestart = TRUE;
  731.         }else if (c == 9) {         // tab
  732.             stream << "   ";
  733.             gen = TRUE;
  734.         }else{
  735.             stream << "[$" << c << "]";
  736.             gen = TRUE;
  737.         }
  738.     }while (pos < len);
  739.  
  740.     if (gen) stream.flush();
  741.     stream.setf(saveFlags & ios::basefield, ios::basefield);
  742.     if (newline) LL_linestart = TRUE;
  743. }
  744.  
  745. /**
  746. * Print a usage message for this test class.
  747. */
  748. void IntlTest::usage( void )
  749. {
  750.     bool_t save_verbose = setVerbose( TRUE );
  751.     logln("Test names:");
  752.     logln("-----------");
  753.  
  754.     int32_t index = 0;
  755.     char* name = NULL;
  756.     do{
  757.         this->runIndexedTest( index, FALSE, name );
  758.         if (!name) break;
  759.         logln(name);
  760.         index++;
  761.     }while (name && (name[0] != 0));
  762.     setVerbose( save_verbose );
  763. }
  764.  
  765.  
  766. // memory leak reporting software will be able to take advantage of the testsuite 
  767. // being run a second time local to a specific method in order to report only actual leaks
  768. bool_t
  769. IntlTest::run_phase2( char* name, char* par ) // supports reporting memory leaks
  770. {
  771.     UnicodeString* strLeak = new UnicodeString("forced leak"); // for verifying purify filter
  772.     return this->runTest( name, par );
  773. }
  774.  
  775.  
  776. int
  777. main(int argc, char* argv[])
  778. {
  779.  
  780. #ifdef XP_MAC
  781.     argc = ccommand( &argv );
  782. #endif
  783.  
  784.     bool_t syntax = FALSE;
  785.     bool_t all = TRUE;
  786.     bool_t verbose = FALSE;
  787.     bool_t no_err_msg = FALSE;
  788.     bool_t quick = TRUE;
  789.     bool_t name = FALSE;
  790.     bool_t leaks = FALSE;
  791.  
  792.     for (int i = 1; i < argc; ++i) {
  793.         if (argv[i][0] == '-') {
  794.             const char* str = argv[i] + 1;
  795.             if (strcmp("verbose", str) == 0)
  796.                 verbose = TRUE;
  797.             else if (strcmp("v", str) == 0)
  798.                 verbose = TRUE;
  799.             else if (strcmp("noerrormsg", str) == 0)
  800.                 no_err_msg = TRUE;
  801.             else if (strcmp("n", str) == 0)
  802.                 no_err_msg = TRUE;
  803.             else if (strcmp("exhaustive", str) == 0)
  804.                 quick = FALSE;
  805.             else if (strcmp("e", str) == 0)
  806.                 quick = FALSE;
  807.             else if (strcmp("all", str) == 0)
  808.                 all = TRUE;
  809.             else if (strcmp("a", str) == 0)
  810.                 all = TRUE;
  811.             else if (strcmp("leaks", str) == 0)
  812.                 leaks = TRUE;
  813.             else if (strcmp("l", str) == 0)
  814.                 leaks = TRUE;
  815.             else {
  816.                 syntax = TRUE;
  817.             }
  818.         }else{
  819.             name = TRUE;
  820.             all = FALSE;
  821.         }
  822.     }
  823.  
  824.     if (all && name) syntax = TRUE;
  825.     if (!all && !name) syntax = TRUE;
  826.  
  827.     if (syntax) {
  828.         cout << "### Syntax:\n"
  829.                 "### IntlTest [-option1 -option2 ...] [testname1 testname2 ...] \n"
  830.                 "### where options are: verbose (v), all (a), noerrormsg (n), \n"
  831.                 "### exhaustive (e) and leaks (l). \n"
  832.                 "### (Specify either -all (shortcut -a) or a test name). \n"
  833.                 "### -all will run all of the tests.\n"
  834.                 "### \n"
  835.                 "### To get a list of the test names type: intltest LIST \n"
  836.                 "### To run just the utility tests type: intltest utility \n"
  837.                 "### \n"
  838.                 "### Test names can be nested using slashes (\"testA/subtest1\") \n"
  839.                 "### For example to list the utility tests type: intltest utility/LIST \n"
  840.                 "### To run just the Locale test type: intltest utility/LocaleTest \n"
  841.                 "### \n"
  842.                 "### A parameter can be specified for a test by appending '@' and the value \n"
  843.                 "### to the testname. \n\n";
  844.         return 1;
  845.     }
  846.  
  847.     bool_t all_tests_exist = TRUE;
  848.     MajorTestLevel major;
  849.     major.setVerbose( verbose );
  850.     major.setNoErrMsg( no_err_msg );
  851.     major.setQuick( quick );
  852.     major.setLeaks( leaks );
  853.     cout << "-----------------------------------------------" << endl;
  854.     cout << " IntlTest Test Suite for                       " << endl;
  855.     cout << "   International Classes for Unicode           " << endl;
  856.     cout << "-----------------------------------------------" << endl;
  857.     cout << " Options:                                       " << endl;
  858.     cout << "   all (a)               : " << (all?        "On" : "Off") << endl;
  859.     cout << "   Verbose (v)           : " << (verbose?    "On" : "Off") << endl;
  860.     cout << "   No error messages (n) : " << (no_err_msg? "On" : "Off") << endl;
  861.     cout << "   Exhaustive (e)        : " << (!quick?     "On" : "Off") << endl;
  862.     cout << "   Leaks (l)             : " << (leaks?      "On" : "Off") << endl;
  863.     cout << "-----------------------------------------------" << endl << endl;
  864.  
  865.     if (all) {
  866.         major.runTest();
  867.         if (leaks) {
  868.             major.run_phase2( NULL, NULL );    
  869.         }
  870.     }else{
  871.         for (int i = 1; i < argc; ++i) {
  872.             if (argv[i][0] != '-') {
  873.                 char* name = argv[i];
  874.                 cout << "\n=== Handling test: " << name << ": ===\n";
  875.                 char* parameter = strchr( name, '@' );
  876.                 if (parameter) {
  877.                     *parameter = 0;
  878.                     parameter += 1;
  879.                 }
  880.                 execCount = 0;
  881.                 bool_t res = major.runTest( name, parameter );
  882.                 if (leaks && res) {
  883.                     major.run_phase2( name, parameter );
  884.                 }
  885.                 if (!res || (execCount <= 0)) {
  886.                     cout << "\n---ERROR: Test doesn't exist: " << name << " !\n";
  887.                     all_tests_exist = FALSE;
  888.                 }
  889.             }
  890.         }
  891.     }
  892.     cout << "\n--------------------------------------\n";
  893.     if (major.getErrors() == 0) {
  894.         cout << "OK: All tests passed without error.\n";
  895.     }else{
  896.         cout << "Errors in total: " << major.getErrors() << ".\n";
  897.     }
  898.  
  899.     cout << "--------------------------------------\n";
  900.  
  901.     if (execCount <= 0) {
  902.         cout << "***** Not all called tests actually exist! *****\n";
  903.     }
  904.  
  905.     return major.getErrors();
  906. }
  907.