home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / tstnorm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-07  |  15.0 KB  |  381 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. #ifndef _TSTNORM
  15. #include "tstnorm.h"
  16. #endif
  17.  
  18.  
  19. #define ARRAY_LENGTH(array) (sizeof (array) / sizeof (*array))
  20.  
  21. static UErrorCode status = U_ZERO_ERROR;
  22.  
  23. /**
  24.  * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
  25.  */
  26. static UnicodeString str(const char *input)
  27. {
  28.   static const UnicodeString digitString1("0123456789ABCDEF");
  29.   static const UnicodeString digitString2("0123456789abcdef");
  30.   
  31.   UnicodeString result(input);
  32.   int index = 0;
  33.   
  34.   while ((index = result.indexOf("\\u")) != -1)
  35.     {
  36.       if (index + 6 <= result.size())
  37.     {
  38.       UChar c = 0;
  39.       for (int i = index + 2; i < index + 6; i++) {
  40.         UTextOffset value = digitString1.indexOf(result[i]);
  41.         
  42.         if (value == -1) {
  43.           value = digitString2.indexOf(result[i]);
  44.         }
  45.         c = (UChar)(c * 16 + value);
  46.       }
  47.       UnicodeString replace;
  48.       replace += c;
  49.       result.replace(index, 6, replace);
  50.     }
  51.       index += 1;
  52.     }
  53.  
  54.   return result;
  55. }
  56.  
  57.  
  58. UnicodeString BasicNormalizerTest::canonTests[23][3];
  59.  
  60. UnicodeString BasicNormalizerTest::compatTests[11][3];
  61.  
  62. BasicNormalizerTest::BasicNormalizerTest()
  63. {
  64.   // canonTest
  65.   // Input                    Decomposed                    Composed
  66.  
  67.     canonTests[0][0] = str("cat");  canonTests[0][1] = str("cat"); canonTests[0][2] =  str("cat");
  68.  
  69.     canonTests[1][0] = str("\\u00e0ardvark");    canonTests[1][1] = str("a\\u0300ardvark");  canonTests[1][2] = str("\\u00e0ardvark"); 
  70.  
  71.     canonTests[2][0] = str("\\u1e0a"); canonTests[2][1] = str("D\\u0307"); canonTests[2][2] = str("\\u1e0a");                 // D-dot_above
  72.  
  73.     canonTests[3][0] = str("D\\u0307");  canonTests[3][1] = str("D\\u0307"); canonTests[3][2] = str("\\u1e0a");            // D dot_above
  74.  
  75.     canonTests[4][0] = str("\\u1e0c\\u0307"); canonTests[4][1] = str("D\\u0323\\u0307");  canonTests[4][2] = str("\\u1e0c\\u0307");         // D-dot_below dot_above
  76.  
  77.     canonTests[5][0] = str("\\u1e0a\\u0323"); canonTests[5][1] = str("D\\u0323\\u0307");  canonTests[5][2] = str("\\u1e0c\\u0307");        // D-dot_above dot_below 
  78.  
  79.     canonTests[6][0] = str("D\\u0307\\u0323"); canonTests[6][1] = str("D\\u0323\\u0307");  canonTests[6][2] = str("\\u1e0c\\u0307");         // D dot_below dot_above 
  80.  
  81.     canonTests[7][0] = str("\\u1e10\\u0307\\u0323");  canonTests[7][1] = str("D\\u0327\\u0323\\u0307"); canonTests[7][2] = str("\\u1e10\\u0323\\u0307");     // D dot_below cedilla dot_above
  82.  
  83.     canonTests[8][0] = str("D\\u0307\\u0328\\u0323"); canonTests[8][1] = str("D\\u0328\\u0323\\u0307"); canonTests[8][2] = str("\\u1e0c\\u0328\\u0307");     // D dot_above ogonek dot_below
  84.  
  85.     canonTests[9][0] = str("\\u1E14"); canonTests[9][1] = str("E\\u0304\\u0300"); canonTests[9][2] = str("\\u1E14");         // E-macron-grave
  86.  
  87.     canonTests[10][0] = str("\\u0112\\u0300"); canonTests[10][1] = str("E\\u0304\\u0300");  canonTests[10][2] = str("\\u1E14");            // E-macron + grave
  88.  
  89.     canonTests[11][0] = str("\\u00c8\\u0304"); canonTests[11][1] = str("E\\u0300\\u0304");  canonTests[11][2] = str("\\u00c8\\u0304");         // E-grave + macron
  90.   
  91.     canonTests[12][0] = str("\\u212b"); canonTests[12][1] = str("A\\u030a"); canonTests[12][2] = str("\\u00c5");             // angstrom_sign
  92.  
  93.     canonTests[13][0] = str("\\u00c5");      canonTests[13][1] = str("A\\u030a");  canonTests[13][2] = str("\\u00c5");            // A-ring
  94.   
  95.     canonTests[14][0] = str("Äffin");  canonTests[14][1] = str("A\\u0308ffin");  canonTests[14][2] = str("Äffin");
  96.  
  97.     canonTests[15][0] = str("Ä\\uFB03n"); canonTests[15][1] = str("A\\u0308\\uFB03n"); canonTests[15][2] = str("Ä\\uFB03n");
  98.   
  99.     canonTests[16][0] = str("Henry IV"); canonTests[16][1] = str("Henry IV"); canonTests[16][2] = str("Henry IV");
  100.  
  101.     canonTests[17][0] = str("Henry \\u2163");  canonTests[17][1] = str("Henry \\u2163");  canonTests[17][2] = str("Henry \\u2163");
  102.   
  103.     canonTests[18][0] = str("\\u30AC");  canonTests[18][1] = str("\\u30AB\\u3099");  canonTests[18][2] = str("\\u30AC");              // ga (Katakana)
  104.  
  105.     canonTests[19][0] = str("\\u30AB\\u3099"); canonTests[19][1] = str("\\u30AB\\u3099");  canonTests[19][2] = str("\\u30AC");            // ka + ten
  106.  
  107.     canonTests[20][0] = str("\\uFF76\\uFF9E"); canonTests[20][1] = str("\\uFF76\\uFF9E");  canonTests[20][2] = str("\\uFF76\\uFF9E");       // hw_ka + hw_ten
  108.  
  109.     canonTests[21][0] = str("\\u30AB\\uFF9E"); canonTests[21][1] = str("\\u30AB\\uFF9E");  canonTests[21][2] = str("\\u30AB\\uFF9E");         // ka + hw_ten
  110.  
  111.     canonTests[22][0] = str("\\uFF76\\u3099"); canonTests[22][1] = str("\\uFF76\\u3099");  canonTests[22][2] = str("\\uFF76\\u3099");         // hw_ka + ten
  112.  
  113.     /* compatTest */
  114.   // Input                        Decomposed                        Composed
  115.   compatTests[0][0] = str("cat"); compatTests[0][1] = str("cat"); compatTests[0][2] = str("cat") ;
  116.   
  117.   compatTests[1][0] = str("\\uFB4f");  compatTests[1][1] = str("\\u05D0\\u05DC"); compatTests[1][2] = str("\\u05D0\\u05DC");  // Alef-Lamed vs. Alef, Lamed
  118.   
  119.   compatTests[2][0] = str("Äffin"); compatTests[2][1] = str("A\\u0308ffin"); compatTests[2][2] = str("Äffin") ;
  120.  
  121.   compatTests[3][0] = str("Ä\\uFB03n"); compatTests[3][1] = str("A\\u0308ffin"); compatTests[3][2] = str("Äffin") ; // ffi ligature -> f + f + i
  122.   
  123.   compatTests[4][0] = str("Henry IV"); compatTests[4][1] = str("Henry IV"); compatTests[4][2] = str("Henry IV") ;
  124.  
  125.   compatTests[5][0] = str("Henry \\u2163"); compatTests[5][1] = str("Henry IV");  compatTests[5][2] = str("Henry IV") ;
  126.   
  127.   compatTests[6][0] = str("\\u30AC"); compatTests[6][1] = str("\\u30AB\\u3099"); compatTests[6][2] = str("\\u30AC") ; // ga (Katakana)
  128.  
  129.   compatTests[7][0] = str("\\u30AB\\u3099"); compatTests[7][1] = str("\\u30AB\\u3099"); compatTests[7][2] = str("\\u30AC") ; // ka + ten
  130.   
  131.   compatTests[8][0] = str("\\uFF76\\u3099"); compatTests[8][1] = str("\\u30AB\\u3099"); compatTests[8][2] = str("\\u30AC") ; // hw_ka + ten
  132.   
  133.   /* These two are broken in Unicode 2.1.2 but fixed in 2.1.5 and later */
  134.   compatTests[9][0] = str("\\uFF76\\uFF9E"); compatTests[9][1] = str("\\u30AB\\u3099"); compatTests[9][2] = str("\\u30AC") ; // hw_ka + hw_ten
  135.  
  136.   compatTests[10][0] = str("\\u30AB\\uFF9E"); compatTests[10][1] = str("\\u30AB\\u3099"); compatTests[10][2] = str("\\u30AC") ; // ka + hw_ten
  137.  
  138.   /* Hangul Canonical */
  139.   // Input                        Decomposed                        Composed
  140.   hangulCanon[0][0] = str("\\ud4db"); hangulCanon[0][1] = str("\\u1111\\u1171\\u11b6"); hangulCanon[0][2] = str("\\ud4db") ;
  141.  
  142.   hangulCanon[1][0] = str("\\u1111\\u1171\\u11b6"), hangulCanon[1][1] = str("\\u1111\\u1171\\u11b6"),   hangulCanon[1][2] = str("\\ud4db");
  143.  
  144.   /* Hangul Compatible */
  145.   // Input            Decomposed                                    Composed
  146.   hangulCompat[0][0] = str("\\ud4db"); hangulCompat[0][1] = str("\\u1111\\u116e\\u1175\\u11af\\u11c2"); hangulCompat[0][2] = str("\\ud478\\u1175\\u11af\\u11c2");
  147. }
  148.  
  149. BasicNormalizerTest::~BasicNormalizerTest()
  150. {
  151. }
  152.  
  153. void BasicNormalizerTest::TestPrevious() 
  154. {
  155.   Normalizer* norm = new Normalizer("", Normalizer::DECOMP, 0);
  156.   
  157.   logln("testing decomp...");
  158.   int i;
  159.   for (i = 0; i < ARRAY_LENGTH(canonTests); i++) {
  160.     backAndForth(norm, canonTests[i][0]);
  161.   }
  162.   
  163.   logln("testing compose...");
  164.   norm->setMode(Normalizer::COMPOSE);
  165.   for (i = 0; i < ARRAY_LENGTH(canonTests); i++) {
  166.     backAndForth(norm, canonTests[i][0]);
  167.   }
  168. }
  169.  
  170. void BasicNormalizerTest::TestDecomp() 
  171. {
  172.   Normalizer* norm = new Normalizer("", Normalizer::DECOMP, 0);
  173.   iterateTest(norm, canonTests, ARRAY_LENGTH(canonTests), 1);
  174.   
  175.   staticTest(Normalizer::DECOMP, 0, canonTests, ARRAY_LENGTH(canonTests), 1);
  176. }
  177.  
  178. void BasicNormalizerTest::TestCompatDecomp() 
  179. {
  180.   Normalizer* norm = new Normalizer("", Normalizer::DECOMP_COMPAT, 0);
  181.   iterateTest(norm, compatTests, ARRAY_LENGTH(compatTests), 1);
  182.   
  183.   staticTest(Normalizer::DECOMP_COMPAT, 0, 
  184.          compatTests, ARRAY_LENGTH(compatTests), 1);
  185. }
  186.  
  187. void BasicNormalizerTest::TestCanonCompose() 
  188. {
  189.   Normalizer* norm = new Normalizer("", Normalizer::COMPOSE, 0);
  190.   iterateTest(norm, canonTests, ARRAY_LENGTH(canonTests), 2);
  191.   
  192.   staticTest(Normalizer::COMPOSE, 0, canonTests,
  193.          ARRAY_LENGTH(canonTests), 2);
  194. }
  195.  
  196. void BasicNormalizerTest::TestCompatCompose() 
  197. {
  198.   Normalizer* norm = new Normalizer("", Normalizer::COMPOSE_COMPAT, 0);
  199.   iterateTest(norm, compatTests, ARRAY_LENGTH(compatTests), 2);
  200.   
  201.   staticTest(Normalizer::COMPOSE_COMPAT, 0, 
  202.          compatTests, ARRAY_LENGTH(compatTests), 2);
  203. }
  204.  
  205.  
  206. //-------------------------------------------------------------------------------
  207.  
  208. UnicodeString BasicNormalizerTest::hangulCanon[2][3];
  209.  
  210. UnicodeString BasicNormalizerTest::hangulCompat[1][3];
  211.  
  212. void BasicNormalizerTest::TestHangulCompose() 
  213. {
  214.   // Make sure that the static composition methods work
  215.   logln("Canonical composition...");
  216.   staticTest(Normalizer::COMPOSE, 0,                    hangulCanon,  ARRAY_LENGTH(hangulCanon),  2);
  217.   logln("Compatibility composition...");
  218.   staticTest(Normalizer::COMPOSE_COMPAT, 0,         hangulCompat, ARRAY_LENGTH(hangulCompat), 2);
  219.   
  220.   // Now try iterative composition....
  221.   logln("Static composition...");
  222.   Normalizer* norm = new Normalizer("", Normalizer::COMPOSE, 0);
  223.   iterateTest(norm, hangulCanon, ARRAY_LENGTH(hangulCanon), 2);
  224.   norm->setMode(Normalizer::COMPOSE_COMPAT);
  225.   iterateTest(norm, hangulCompat, ARRAY_LENGTH(hangulCompat), 2);
  226.   
  227.   // And finally, make sure you can do it in reverse too
  228.   logln("Reverse iteration...");
  229.   norm->setMode(Normalizer::COMPOSE);
  230.   for (int i = 0; i < ARRAY_LENGTH(hangulCanon); i++) {
  231.     backAndForth(norm, hangulCanon[i][0]);
  232.   }
  233. }
  234.  
  235. void BasicNormalizerTest::TestHangulDecomp() 
  236. {
  237.   // Make sure that the static decomposition methods work
  238.   logln("Canonical decomposition...");
  239.   staticTest(Normalizer::DECOMP, 0,                     hangulCanon,  ARRAY_LENGTH(hangulCanon),  1);
  240.   logln("Compatibility decomposition...");
  241.   staticTest(Normalizer::DECOMP_COMPAT, 0,         hangulCompat, ARRAY_LENGTH(hangulCompat), 1);
  242.   
  243.   // Now the iterative decomposition methods...
  244.   logln("Iterative decomposition...");
  245.   Normalizer* norm = new Normalizer("", Normalizer::DECOMP, 0);
  246.   iterateTest(norm, hangulCanon, ARRAY_LENGTH(hangulCanon), 1);
  247.   norm->setMode(Normalizer::DECOMP_COMPAT);
  248.   iterateTest(norm, hangulCompat, ARRAY_LENGTH(hangulCompat), 1);
  249.   
  250.   // And finally, make sure you can do it in reverse too
  251.   logln("Reverse iteration...");
  252.   norm->setMode(Normalizer::DECOMP);
  253.   for (int i = 0; i < ARRAY_LENGTH(hangulCanon); i++) {
  254.     backAndForth(norm, hangulCanon[i][0]);
  255.   }
  256. }
  257.  
  258.  
  259. //------------------------------------------------------------------------
  260. // Internal utilities
  261. //
  262.  
  263. UnicodeString BasicNormalizerTest::hex(UChar ch) {
  264.     UnicodeString result;
  265.     return appendHex(ch, 4, result);
  266. }
  267.  
  268. UnicodeString BasicNormalizerTest::hex(const UnicodeString& s) {
  269.     UnicodeString result;
  270.     for (int i = 0; i < s.size(); ++i) {
  271.         if (i != 0) result += ',';
  272.         appendHex(s[i], 4, result);
  273.     }
  274.     return result;
  275. }
  276.  
  277.  
  278. inline static void insert(UnicodeString& dest, int pos, UChar ch)
  279. {
  280.     dest.replace(pos, 0, &ch, 1);
  281. }
  282.  
  283. void BasicNormalizerTest::backAndForth(Normalizer* iter, const UnicodeString& input)
  284. {
  285.     UChar ch;
  286.     iter->setText(input, status);
  287.  
  288.     // Run through the iterator forwards and stick it into a StringBuffer
  289.     UnicodeString forward;
  290.     for (ch = iter->first(); ch != iter->DONE; ch = iter->next()) {
  291.         forward += ch;
  292.     }
  293.  
  294.     // Now do it backwards
  295.     UnicodeString reverse;
  296.     for (ch = iter->last(); ch != iter->DONE; ch = iter->previous()) {
  297.         insert(reverse, 0, ch);
  298.     }
  299.     
  300.     if (forward != reverse) {
  301.         errln("Forward/reverse mismatch for input " + hex(input)
  302.               + ", forward: " + hex(forward) + ", backward: " + hex(reverse));
  303.     }
  304. }
  305.  
  306. void BasicNormalizerTest::staticTest(Normalizer::EMode mode, int options,
  307.                      UnicodeString tests[][3], int length,
  308.                      int outCol)
  309. {
  310.     for (int i = 0; i < length; i++)
  311.     {
  312.         UnicodeString& input = tests[i][0];
  313.         UnicodeString& expect = tests[i][outCol];
  314.         
  315.         logln("Normalizing '" + input + "' (" + hex(input) + ")" );
  316.         
  317.         UnicodeString output;
  318.         Normalizer::normalize(input, mode, options, output, status);
  319.         
  320.         if (output != expect) {
  321.             errln(UnicodeString("ERROR: case ") + i + " normalized " + hex(input) + "\n"
  322.                 + "                expected " + hex(expect) + "\n"
  323.                 + "              static got " + hex(output) );
  324.         }
  325.     }
  326. }
  327.  
  328. void BasicNormalizerTest::iterateTest(Normalizer* iter,
  329.                                       UnicodeString tests[][3], int length,
  330.                                       int outCol)
  331. {
  332.     for (int i = 0; i < length; i++)
  333.     {
  334.         UnicodeString& input = tests[i][0];
  335.         UnicodeString& expect = tests[i][outCol];
  336.         
  337.         logln("Normalizing '" + input + "' (" + hex(input) + ")" );
  338.         
  339.         iter->setText(input, status);
  340.         assertEqual(input, expect, iter, UnicodeString("ERROR: case ") + i + " ");
  341.     }
  342. }
  343.  
  344. void BasicNormalizerTest::assertEqual(const UnicodeString&    input,
  345.                       const UnicodeString&    expected,
  346.                       Normalizer*        iter,
  347.                       const UnicodeString&    errPrefix)
  348. {
  349.     int index = 0;
  350.     UnicodeString result;
  351.  
  352.     for (UChar ch = iter->first(); ch != iter->DONE; ch = iter->next()) {
  353.         result += ch;
  354.     }
  355.     if (result != expected) {
  356.         errln(errPrefix + "normalized " + hex(input) + "\n"
  357.             + "                expected " + hex(expected) + "\n"
  358.             + "             iterate got " + hex(result) );
  359.     }
  360. }
  361.  
  362. void BasicNormalizerTest::runIndexedTest(int32_t index, bool_t exec, char* &name, char* par)
  363. {
  364.     if (exec)
  365.     {
  366.         logln("Collation Regression Tests: ");
  367.     }
  368.  
  369.     switch (index)
  370.     {
  371.         case  0: name = "TestDecomp";            if (exec) TestDecomp(); break;
  372.         case  1: name = "TestCompatDecomp";        if (exec) TestCompatDecomp(); break;
  373.         case  2: name = "TestCanonCompose";        if (exec) TestCanonCompose(); break;
  374.         case  3: name = "TestCompatCompose";    if (exec) TestCompatCompose(); break;
  375.         case  4: name = "TestPrevious";            if (exec) TestPrevious(); break;
  376.         case  5: name = "TestHangulDecomp";        if (exec) TestHangulDecomp(); break;
  377.         case  6: name = "TestHangulCompose";    if (exec) TestHangulCompose(); break;
  378.         default: name = ""; break;
  379.     }
  380. }
  381.