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

  1. /*
  2. ********************************************************************
  3. * COPYRIGHT: 
  4. * (C) Copyright Taligent, Inc., 1997
  5. * (C) Copyright International Business Machines Corporation, 1997 - 1998
  6. * Licensed Material - Program-Property of IBM - All Rights Reserved. 
  7. * US Government Users Restricted Rights - Use, duplication, or disclosure 
  8. * restricted by GSA ADP Schedule Contract with IBM Corp. 
  9. *
  10. ********************************************************************
  11. */
  12.  
  13. #ifndef _COLL
  14. #include "coll.h"
  15. #endif
  16.  
  17. #ifndef _TBLCOLL
  18. #include "tblcoll.h"
  19. #endif
  20.  
  21. #ifndef _UNISTR
  22. #include "unistr.h"
  23. #endif
  24.  
  25. #ifndef _SORTKEY
  26. #include "sortkey.h"
  27. #endif
  28.  
  29. #ifndef _REGCOLL
  30. #include "regcoll.h"
  31. #endif
  32.  
  33. #define ARRAY_LENGTH(array) (sizeof array / sizeof array[0])
  34.  
  35. static UErrorCode status = U_ZERO_ERROR;
  36.  
  37. const UnicodeString CollationRegressionTest::test1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?";
  38. const UnicodeString CollationRegressionTest::test2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?";
  39. const UChar chars3[] = {'a', 0x00FC, 'b', 'e', 'c', 'k', ' ', 'G', 'r', 0x00F6, 0x00DF, 'e', ' ', 'L', 0x00FC, 'b', 'c', 'k', 0};
  40. const UnicodeString CollationRegressionTest::test3(chars3);
  41.  
  42. CollationRegressionTest::CollationRegressionTest()
  43. {
  44.     en_us = (RuleBasedCollator *)Collator::createInstance(Locale::US, status);
  45. }
  46.  
  47. CollationRegressionTest::~CollationRegressionTest()
  48. {
  49.     delete en_us;
  50. }
  51.  
  52.  
  53.     // @bug 4048446
  54. //
  55. // CollationElementIterator.reset() doesn't work
  56. //
  57. void CollationRegressionTest::Test4048446(char *par)
  58. {
  59.     CollationElementIterator *i1 = en_us->createCollationElementIterator(test1);
  60.     CollationElementIterator *i2 = en_us->createCollationElementIterator(test1);
  61.     UErrorCode status = U_ZERO_ERROR;
  62.  
  63.     if (i1 == NULL|| i2 == NULL)
  64.     {
  65.         errln("Could not create CollationElementIterator's");
  66.         delete i1;
  67.         delete i2;
  68.         return;
  69.     }
  70.  
  71.     while (i1->next(status) != CollationElementIterator::NULLORDER)
  72.     {
  73.         if (U_FAILURE(status))
  74.         {
  75.             errln("error calling next()");
  76.  
  77.             delete i1;
  78.             delete i2;
  79.             return;
  80.         }
  81.     }
  82.  
  83.     i1->reset();
  84.  
  85.     assertEqual(*i1, *i2);
  86.  
  87.     delete i1;
  88.     delete i2;
  89. }
  90.  
  91. // @bug 4051866
  92. //
  93. // Collator -> rules -> Collator round-trip broken for expanding characters
  94. //
  95. void CollationRegressionTest::Test4051866(char *par)
  96. {
  97. /*
  98.     RuleBasedCollator c1 = new RuleBasedCollator("< o "
  99.                                                 +"& oe ,o\u3080"
  100.                                                 +"& oe ,\u1530 ,O"
  101.                                                 +"& OE ,O\u3080"
  102.                                                 +"& OE ,\u1520"
  103.                                                 +"< p ,P");
  104. */
  105.  
  106.     UnicodeString rules;
  107.     UErrorCode status = U_ZERO_ERROR;
  108.  
  109.     rules += "< o ";
  110.     rules += "& oe ,o";
  111.     rules += (UChar)0x3080;
  112.     rules += "& oe ,";
  113.     rules += (UChar)0x1530;
  114.     rules += " ,O";
  115.     rules += "& OE ,O";
  116.     rules += (UChar)0x3080;
  117.     rules += "& OE ,";
  118.     rules += (UChar)0x1520;
  119.     rules += "< p ,P";
  120.  
  121.     // Build a collator containing expanding characters
  122.     RuleBasedCollator *c1 = new RuleBasedCollator(rules, status);
  123.  
  124.     // Build another using the rules from  the first
  125.     RuleBasedCollator *c2 = new RuleBasedCollator(c1->getRules(), status);
  126.  
  127.     // Make sure they're the same
  128.     if (!(c1->getRules() == c2->getRules()))
  129.     {
  130.         errln("Rules are not equal");
  131.     }
  132.  
  133.     delete c2;
  134.     delete c1;
  135. }
  136.  
  137. // @bug 4053636
  138. //
  139. // Collator thinks "black-bird" == "black"
  140. //
  141. void CollationRegressionTest::Test4053636(char *par)
  142. {
  143.     if (en_us->equals("black_bird", "black"))
  144.     {
  145.         errln("black-bird == black");
  146.     }
  147. }
  148.  
  149. // @bug 4054238
  150. //
  151. // CollationElementIterator will not work correctly if the associated
  152. // Collator object's mode is changed
  153. //
  154. void CollationRegressionTest::Test4054238(char *par)
  155. {
  156.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  157.  
  158.     // NOTE: The Java code uses en_us to create the CollationElementIterators
  159.     // but I'm pretty sure that's wrong, so I've changed this to use c.
  160.     c->setDecomposition(Normalizer::DECOMP);
  161.     CollationElementIterator *i1 = c->createCollationElementIterator(test3);
  162.  
  163.     c->setDecomposition(Normalizer::NO_OP);
  164.     CollationElementIterator *i2 = c->createCollationElementIterator(test3);
  165.  
  166.     // At this point, BOTH iterators should use NO_DECOMPOSITION, since the
  167.     // collator itself is in that mode
  168.     assertEqual(*i1, *i2);
  169.  
  170.     delete i2;
  171.     delete i1;
  172.     delete c;
  173. }
  174.  
  175. // @bug 4054734
  176. //
  177. // Collator::IDENTICAL documented but not implemented
  178. //
  179. void CollationRegressionTest::Test4054734(char *par)
  180. {
  181.     /*
  182.         Here's the original Java:
  183.  
  184.         String[] decomp = {
  185.             "\u0001",   "<",    "\u0002",
  186.             "\u0001",   "=",    "\u0001",
  187.             "A\u0001",  ">",    "~\u0002",      // Ensure A and ~ are not compared bitwise
  188.             "\u00C0",   "=",    "A\u0300"       // Decomp should make these equal
  189.         };
  190.  
  191.         String[] nodecomp = {
  192.             "\u00C0",   ">",    "A\u0300"       // A-grave vs. A combining-grave
  193.         };
  194.     */
  195.  
  196.     static const UChar decomp[][CollationRegressionTest::MAX_TOKEN_LEN] =
  197.     {
  198.         {0x0001, 0},      {'<', 0}, {0x0002, 0},
  199.         {0x0001, 0},      {'=', 0}, {0x0001, 0},
  200.         {'A', 0x0001, 0}, {'>', 0}, {'~', 0x0002, 0},
  201.         {0x00c0, 0},      {'=', 0}, {'A', 0x0300, 0}
  202.     };
  203.  
  204.     static const UChar nodecomp[][CollationRegressionTest::MAX_TOKEN_LEN] =
  205.     {
  206.         {0x00C0, 0},      {'>', 0}, {'A', 0x0300, 0}
  207.     };
  208.  
  209.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  210.  
  211.     c->setStrength(Collator::IDENTICAL);
  212.  
  213.     c->setDecomposition(Normalizer::DECOMP);
  214.     compareArray(*c, decomp, ARRAY_LENGTH(decomp));
  215.  
  216.     c->setDecomposition(Normalizer::NO_OP);
  217.     compareArray(*c, nodecomp, ARRAY_LENGTH(nodecomp));
  218.  
  219.     delete c;
  220. }
  221.  
  222. // @bug 4054736
  223. //
  224. // Full Decomposition mode not implemented
  225. //
  226. void CollationRegressionTest::Test4054736(char *par)
  227. {
  228.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  229.  
  230.     c->setDecomposition(Normalizer::DECOMP_COMPAT);
  231.  
  232.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  233.     {
  234.         {0xFB4F, 0}, {'=', 0}, {0x05D0, 0x05DC}  // Alef-Lamed vs. Alef, Lamed
  235.     };
  236.  
  237.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  238.  
  239.     delete c;
  240. }
  241.  
  242. // @bug 4058613
  243. //
  244. // Collator::createInstance() causes an ArrayIndexOutofBoundsException for Korean  
  245. //
  246. void CollationRegressionTest::Test4058613(char *par)
  247. {
  248.     // Creating a default collator doesn't work when Korean is the default
  249.     // locale
  250.     
  251.     Locale oldDefault = Locale::getDefault();
  252.     UErrorCode status = U_ZERO_ERROR;
  253.     
  254.     Locale::setDefault(Locale::KOREAN, status);
  255.  
  256.     if (U_FAILURE(status))
  257.     {
  258.         errln("Could not set default locale to Locale::KOREAN");
  259.         return;
  260.     }
  261.  
  262.     Collator *c = NULL;
  263.     
  264.     c = Collator::createInstance(status);
  265.  
  266.     if (c == NULL || U_FAILURE(status))
  267.     {
  268.         errln("Could not create a Korean collator");
  269.         Locale::setDefault(oldDefault, status);
  270.         delete c;
  271.         return;
  272.     }
  273.     
  274.     // Since the fix to this bug was to turn off decomposition for Korean collators,
  275.     // ensure that's what we got
  276.     if (c->getDecomposition() != Normalizer::NO_OP)
  277.     {
  278.       errln("Decomposition is not set to NO_DECOMPOSITION for Korean collator");
  279.     }
  280.  
  281.     delete c;
  282.  
  283.     Locale::setDefault(oldDefault, status);
  284. }
  285.  
  286. // @bug 4059820
  287. //
  288. // RuleBasedCollator.getRules does not return the exact pattern as input
  289. // for expanding character sequences
  290. //
  291. void CollationRegressionTest::Test4059820(char *par)
  292. {
  293.     UErrorCode status = U_ZERO_ERROR;
  294.  
  295.     RuleBasedCollator *c = NULL;
  296.     UnicodeString rules = "< a < b , c/a < d < z";
  297.     
  298.     c = new RuleBasedCollator(rules, status);
  299.  
  300.     if (c == NULL || U_FAILURE(status))
  301.     {
  302.         errln("Failure building a collator.");
  303.         delete c;
  304.         return;
  305.     }
  306.  
  307.     if ( c->getRules().indexOf("c/a") == -1)
  308.     {
  309.         errln("returned rules do not contain 'c/a'");
  310.     }
  311.  
  312.     delete c;
  313. }
  314.  
  315. // @bug 4060154
  316. //
  317. // MergeCollation::fixEntry broken for "& H < \u0131, \u0130, i, I"
  318. //
  319. void CollationRegressionTest::Test4060154(char *par)
  320. {
  321.     UErrorCode status = U_ZERO_ERROR;
  322.     UnicodeString rules;
  323.  
  324.     rules += "< g, G < h, H < i, I < j, J";
  325.     rules +=  " & H < ";
  326.     rules += (UChar)0x0131;
  327.     rules += ", ";
  328.     rules += (UChar)0x0130;
  329.     rules += ", i, I";
  330.  
  331.     RuleBasedCollator *c = NULL;
  332.     
  333.     c = new RuleBasedCollator(rules, status);
  334.  
  335.     if (c == NULL || U_FAILURE(status))
  336.     {
  337.         errln("failure building collator.");
  338.         delete c;
  339.         return;
  340.     }
  341.  
  342.     c->setDecomposition(Normalizer::DECOMP);
  343.  
  344.  /*
  345.     String[] tertiary = {
  346.         "A",        "<",    "B",
  347.         "H",        "<",    "\u0131",
  348.         "H",        "<",    "I",
  349.         "\u0131",   "<",    "\u0130",
  350.         "\u0130",   "<",    "i",
  351.         "\u0130",   ">",    "H",
  352.     };
  353. */
  354.  
  355.     static const UChar tertiary[][CollationRegressionTest::MAX_TOKEN_LEN] =
  356.     {
  357.         {'A', 0},    {'<', 0}, {'B', 0},
  358.         {'H', 0},    {'<', 0}, {0x0131, 0},
  359.         {'H', 0},    {'<', 0}, {'I', 0},
  360.         {0x0131, 0}, {'<', 0}, {0x0130, 0},
  361.         {0x0130, 0}, {'<', 0}, {'i', 0},
  362.         {0x0130, 0}, {'>', 0}, {'H', 0}
  363.     };
  364.  
  365.     c->setStrength(Collator::TERTIARY);
  366.     compareArray(*c, tertiary, ARRAY_LENGTH(tertiary));
  367.  
  368.     /*
  369.     String[] secondary = {
  370.         "H",        "<",    "I",
  371.         "\u0131",   "=",    "\u0130",
  372.     };
  373. */
  374.     static const UChar secondary[][CollationRegressionTest::MAX_TOKEN_LEN] =
  375.     {
  376.         {'H', 0},    {'<', 0}, {'I', 0},
  377.         {0x0131, 0}, {'=', 0}, {0x0130, 0}
  378.     };
  379.  
  380.     c->setStrength(Collator::PRIMARY);
  381.     compareArray(*c, secondary, ARRAY_LENGTH(secondary));
  382.  
  383.     delete c;
  384. };
  385.  
  386. // @bug 4062418
  387. //
  388. // Secondary/Tertiary comparison incorrect in French Secondary
  389. //
  390. void CollationRegressionTest::Test4062418(char *par)
  391. {
  392.     UErrorCode status = U_ZERO_ERROR;
  393.  
  394.     RuleBasedCollator *c = NULL;
  395.     
  396.     c = (RuleBasedCollator *) Collator::createInstance(Locale::FRANCE, status);
  397.  
  398.     if (c == NULL || U_FAILURE(status))
  399.     {
  400.         errln("Failed to create collator for Locale::FRANCE");
  401.         delete c;
  402.         return;
  403.     }
  404.  
  405.     c->setStrength(Collator::SECONDARY);
  406.  
  407. /*
  408.     String[] tests = {
  409.             "p\u00eache",    "<",    "p\u00e9ch\u00e9",    // Comparing accents from end, p\u00e9ch\u00e9 is greater
  410.     };
  411. */
  412.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  413.     {
  414.         {'p', 0x00EA, 'c', 'h', 'e', 0}, {'<', 0}, {'p', 0x00E9, 'c', 'h', 0x00E9, 0}
  415.     };
  416.  
  417.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  418.  
  419.     delete c;
  420. }
  421.  
  422. // @bug 4065540
  423. //
  424. // Collator::compare() method broken if either string contains spaces
  425. //
  426. void CollationRegressionTest::Test4065540(char *par)
  427. {
  428.     if (en_us->compare("abcd e", "abcd f") == 0)
  429.     {
  430.         errln("'abcd e' == 'abcd f'");
  431.     }
  432. }
  433.  
  434. // @bug 4066189
  435. //
  436. // Unicode characters need to be recursively decomposed to get the
  437. // correct result. For example,
  438. // u1EB1 -> \u0103 + \u0300 -> a + \u0306 + \u0300.
  439. //
  440. void CollationRegressionTest::Test4066189(char *par)
  441. {
  442.     static const UChar chars1[] = {0x1EB1, 0};
  443.     static const UChar chars2[] = {'a', 0x0306, 0x0300, 0};
  444.     const UnicodeString test1(chars1);
  445.     const UnicodeString test2(chars2);
  446.  
  447.     // NOTE: The java code used en_us to create the
  448.     // CollationElementIterator's. I'm pretty sure that
  449.     // was wrong, so I've change the code to use c1 and c2
  450.     RuleBasedCollator *c1 = (RuleBasedCollator *) en_us->clone();
  451.     c1->setDecomposition(Normalizer::DECOMP_COMPAT);
  452.     CollationElementIterator *i1 = c1->createCollationElementIterator(test1);
  453.  
  454.     RuleBasedCollator *c2 = (RuleBasedCollator *) en_us->clone();
  455.     c2->setDecomposition(Normalizer::NO_OP);
  456.     CollationElementIterator *i2 = c2->createCollationElementIterator(test2);
  457.  
  458.     assertEqual(*i1, *i2);
  459.  
  460.     delete i2;
  461.     delete c2;
  462.     delete i1;
  463.     delete c1;
  464. }
  465.  
  466. // @bug 4066696
  467. //
  468. // French secondary collation checking at the end of compare iteration fails
  469. //
  470. void CollationRegressionTest::Test4066696(char *par)
  471. {
  472.     UErrorCode status = U_ZERO_ERROR;
  473.     RuleBasedCollator *c = NULL;
  474.     
  475.     c = (RuleBasedCollator *)Collator::createInstance(Locale::FRANCE, status);
  476.  
  477.     if (c == NULL || U_FAILURE(status))
  478.     {
  479.         errln("Failure creating collator for Locale::FRANCE");
  480.         delete c;
  481.         return;
  482.     }
  483.  
  484.     c->setStrength(Collator::SECONDARY);
  485.  
  486. /*
  487.     String[] tests = {
  488.         "\u00e0",   "<",     "\u01fa",       // a-grave <  A-ring-acute
  489.     };
  490. */
  491.  
  492.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  493.     {
  494.         {0x00E0, 0}, {'<', 0}, {0x01FA, 0}
  495.     };
  496.  
  497.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  498.  
  499.     delete c;
  500. }
  501.  
  502. // @bug 4076676
  503. //
  504. // Bad canonicalization of same-class combining characters
  505. //
  506. void CollationRegressionTest::Test4076676(char *par)
  507. {
  508.     // These combining characters are all in the same class, so they should not
  509.     // be reordered, and they should compare as unequal.
  510.     static const UChar s1[] = {'A', 0x0301, 0x0302, 0x0300, 0};
  511.     static const UChar s2[] = {'A', 0x0302, 0x0300, 0x0301, 0};
  512.  
  513.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  514.     c->setStrength(Collator::TERTIARY);
  515.  
  516.     if (c->compare(s1,s2) == 0)
  517.     {
  518.         errln("Same-class combining chars were reordered");
  519.     }
  520.  
  521.     delete c;
  522. }
  523.  
  524. // @bug 4079231
  525. //
  526. // RuleBasedCollator::operator==(NULL) throws NullPointerException
  527. //
  528. void CollationRegressionTest::Test4079231(char *par)
  529. {
  530.     // I don't think there's any way to write this test
  531.     // in C++. The following is equivalent to the Java,
  532.     // but doesn't compile 'cause NULL can't be converted
  533.     // to Collator&
  534.     //
  535.     // if (en_us->operator==(NULL))
  536.     // {
  537.     //     errln("en_us->operator==(NULL) returned TRUE");
  538.     // }
  539.  
  540.  /*
  541.    try {
  542.         if (en_us->equals(null)) {
  543.             errln("en_us->equals(null) returned true");
  544.         }
  545.     }
  546.     catch (Exception e) {
  547.         errln("en_us->equals(null) threw " + e.toString());
  548.     }
  549. */
  550. }
  551.  
  552. // @bug 4078588
  553. //
  554. // RuleBasedCollator breaks on "< a < bb" rule
  555. //
  556. void CollationRegressionTest::Test4078588(char *par)
  557. {
  558.     UErrorCode status = U_ZERO_ERROR;
  559.     RuleBasedCollator *rbc = new RuleBasedCollator("< a < bb", status);
  560.  
  561.     if (rbc == NULL || U_FAILURE(status))
  562.     {
  563.         errln("Failed to create RuleBasedCollator.");
  564.         delete rbc;
  565.         return;
  566.     }
  567.  
  568.     Collator::EComparisonResult result = rbc->compare("a","bb");
  569.  
  570.     if (result != Collator::LESS)
  571.     {
  572.         UnicodeString msg;
  573.  
  574.         msg += (UnicodeString)"Compare(a,bb) returned " + result;
  575.         msg += "; expected -1";
  576.  
  577.         errln(msg);
  578.     }
  579.  
  580.     delete rbc;
  581. }
  582.  
  583. // @bug 4081866
  584. //
  585. // Combining characters in different classes not reordered properly.
  586. //
  587. void CollationRegressionTest::Test4081866(char *par)
  588. {
  589.     // These combining characters are all in different classes,
  590.     // so they should be reordered and the strings should compare as equal.
  591.     static const UChar s1[] = {'A', 0x0300, 0x0316, 0x0327, 0x0315, 0};
  592.     static const UChar s2[] = {'A', 0x0327, 0x0316, 0x0315, 0x0300, 0};
  593.  
  594.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  595.     c->setStrength(Collator::TERTIARY);
  596.     
  597.     // Now that the default collators are set to NO_DECOMPOSITION
  598.     // (as a result of fixing bug 4114077), we must set it explicitly
  599.     // when we're testing reordering behavior.  -- lwerner, 5/5/98
  600.     c->setDecomposition(Normalizer::DECOMP);
  601.  
  602.     if (c->compare(s1,s2) != 0)
  603.     {
  604.         errln("Combining chars were not reordered");
  605.     }
  606.  
  607.     delete c;
  608. }
  609.  
  610. // @bug 4087241
  611. //
  612. // string comparison errors in Scandinavian collators
  613. //
  614. void CollationRegressionTest::Test4087241(char *par)
  615. {
  616.     UErrorCode status = U_ZERO_ERROR;
  617.     Locale da_DK("da", "DK");
  618.     RuleBasedCollator *c = NULL;
  619.     
  620.     c = (RuleBasedCollator *) Collator::createInstance(da_DK, status);
  621.  
  622.     if (c == NULL || U_FAILURE(status))
  623.     {
  624.         errln("Failed to create collator for da_DK locale");
  625.         delete c;
  626.         return;
  627.     }
  628.  
  629.     c->setStrength(Collator::SECONDARY);
  630.  
  631.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  632.     {
  633.         {'z', 0},          {'<', 0}, {0x00E6, 0},            // z        < ae
  634.         {'a', 0x0308, 0}, {'<', 0}, {'a', 0x030A, 0},      // a-unlaut < a-ring
  635.         {'Y', 0},          {'<', 0}, {'u', 0x0308, 0},      // Y        < u-umlaut
  636.     };
  637.  
  638.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  639.  
  640.     delete c;
  641. }
  642.  
  643. // @bug 4087243
  644. //
  645. // CollationKey takes ignorable strings into account when it shouldn't
  646. //
  647. void CollationRegressionTest::Test4087243(char *par)
  648. {
  649.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  650.     c->setStrength(Collator::TERTIARY);
  651.  
  652.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  653.     {
  654.         {'1', '2', '3', 0}, {'=', 0}, {'1', '2', '3', 0x0001, 0}    // 1 2 3  =  1 2 3 ctrl-A
  655.     };
  656.  
  657.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  658.  
  659.     delete c;
  660. }
  661.  
  662. // @bug 4092260
  663. //
  664. // Mu/micro conflict
  665. // Micro symbol and greek lowercase letter Mu should sort identically
  666. //
  667. void CollationRegressionTest::Test4092260(char *par)
  668. {
  669.     UErrorCode status = U_ZERO_ERROR;
  670.     Locale el("el", "");
  671.     Collator *c = NULL;
  672.     
  673.     c = Collator::createInstance(el, status);
  674.  
  675.     if (c == NULL || U_FAILURE(status))
  676.     {
  677.         errln("Failed to create collator for el locale.");
  678.         delete c;
  679.         return;
  680.     }
  681.  
  682.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  683.     {
  684.         {0x00B5, 0}, {'=', 0}, {0x03BC, 0}
  685.     };
  686.  
  687.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  688.  
  689.     delete c;
  690. }
  691.  
  692. // @bug 4095316
  693. //
  694. void CollationRegressionTest::Test4095316(char *par)
  695. {
  696.     UErrorCode status = U_ZERO_ERROR;
  697.     Locale el_GR("el", "GR");
  698.     Collator *c = Collator::createInstance(el_GR, status);
  699.  
  700.     if (c == NULL || U_FAILURE(status))
  701.     {
  702.         errln("Failed to create collator for el_GR locale");
  703.         delete c;
  704.         return;
  705.     }
  706.  
  707.     c->setStrength(Collator::TERTIARY);
  708.  
  709.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  710.     {
  711.         {0x03D4, 0}, {'=', 0}, {0x03AB, 0}
  712.     };
  713.  
  714.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  715.  
  716.     delete c;
  717. }
  718.  
  719. // @bug 4101940
  720. //
  721. void CollationRegressionTest::Test4101940(char *par)
  722. {
  723.     UErrorCode status = U_ZERO_ERROR;
  724.     RuleBasedCollator *c = NULL;
  725.     UnicodeString rules = "< a < b";
  726.     UnicodeString nothing = "";
  727.     
  728.     c = new RuleBasedCollator(rules, status);
  729.  
  730.     if (c == NULL || U_FAILURE(status))
  731.     {
  732.         errln("Failed to create RuleBasedCollator");
  733.         delete c;
  734.         return;
  735.     }
  736.  
  737.     CollationElementIterator *i = c->createCollationElementIterator(nothing);
  738.     i->reset();
  739.  
  740.     if (i->next(status) != CollationElementIterator::NULLORDER)
  741.     {
  742.         errln("next did not return NULLORDER");
  743.     }
  744.  
  745.     delete i;
  746.     delete c;
  747. }
  748.  
  749. // @bug 4103436
  750. //
  751. // Collator::compare not handling spaces properly
  752. //
  753. void CollationRegressionTest::Test4103436(char *par)
  754. {
  755.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  756.     c->setStrength(Collator::TERTIARY);
  757.  
  758.     static const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN] =
  759.     {
  760.         {'f', 'i', 'l', 'e', 0}, {'<', 0}, {'f', 'i', 'l', 'e', ' ', 'a', 'c', 'c', 'e', 's', 's', 0},
  761.         {'f', 'i', 'l', 'e', 0}, {'<', 0}, {'f', 'i', 'l', 'e', 'a', 'c', 'c', 'e', 's', 's', 0}
  762.     };
  763.  
  764.     compareArray(*c, tests, ARRAY_LENGTH(tests));
  765.  
  766.     delete c;
  767. }
  768.  
  769. // @bug 4114076
  770. //
  771. // Collation not Unicode conformant with Hangul syllables
  772. //
  773. void CollationRegressionTest::Test4114076(char *par)
  774. {
  775.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  776.     c->setStrength(Collator::TERTIARY);
  777.  
  778.     //
  779.     // With Canonical decomposition, Hangul syllables should get decomposed
  780.     // into Jamo, but Jamo characters should not be decomposed into
  781.     // conjoining Jamo
  782.     //
  783.     static const UChar test1[][CollationRegressionTest::MAX_TOKEN_LEN] =
  784.     {
  785.         {0xd4db, 0}, {'=', 0}, {0x1111, 0x1171, 0x11b6, 0}
  786.     };
  787.  
  788.     c->setDecomposition(Normalizer::DECOMP);
  789.     compareArray(*c, test1, ARRAY_LENGTH(test1));
  790.  
  791.     //
  792.     // With Full decomposition, it should go all the way down to
  793.     // conjoining Jamo characters.
  794.     //
  795.     static const UChar test2[][CollationRegressionTest::MAX_TOKEN_LEN] =
  796.     {
  797.         {0xd4db, 0}, {'=', 0}, {0x1111, 0x116e, 0x1175, 0x11af, 0x11c2, 0}
  798.     };
  799.  
  800.     c->setDecomposition(Normalizer::DECOMP_COMPAT);
  801.     compareArray(*c, test2, ARRAY_LENGTH(test2));
  802.  
  803.     delete c;
  804. }
  805.  
  806.  
  807. // @bug 4124632
  808. //
  809. // Collator::getCollationKey was hanging on certain character sequences
  810. //
  811. void CollationRegressionTest::Test4124632(char *par)
  812. {
  813.     UErrorCode status = U_ZERO_ERROR;
  814.     Collator *coll = NULL;
  815.     
  816.     coll = Collator::createInstance(Locale::JAPAN, status);
  817.     
  818.     if (coll == NULL || U_FAILURE(status))
  819.     {
  820.         errln("Failed to create collator for Locale::JAPAN");
  821.         delete coll;
  822.     }
  823.  
  824.     static const UChar test[] = {'A', 0x0308, 'b', 'c', 0};
  825.     CollationKey key;
  826.     
  827.     coll->getCollationKey(test, key, status);
  828.  
  829.     if (key.isBogus() || U_FAILURE(status))
  830.     {
  831.         errln("CollationKey creation failed.");
  832.     }
  833.  
  834.     delete coll;
  835. }
  836.  
  837. // @bug 4132736
  838. //
  839. // sort order of french words with multiple accents has errors
  840. //
  841. void CollationRegressionTest::Test4132736(char *par)
  842. {
  843.     UErrorCode status = U_ZERO_ERROR;
  844.  
  845.     Collator *c = NULL;
  846.     
  847.     c = Collator::createInstance(Locale::FRANCE, status);
  848.     
  849.     if (c == NULL || U_FAILURE(status))
  850.     {
  851.         errln("Failed to create a collator for Locale::FRANCE");
  852.         delete c;
  853.     }
  854.  
  855.     static const UChar test1[][CollationRegressionTest::MAX_TOKEN_LEN] =
  856.     {
  857.         {'e', 0x0300, 'e', 0x0301, 0}, {'<', 0}, {'e', 0x0301, 'e', 0x0300, 0},
  858.         {'e', 0x0300, 0x0301, 0},       {'>', 0}, {'e', 0x0301, 0x0300, 0}
  859.     };
  860.  
  861.     compareArray(*c, test1, ARRAY_LENGTH(test1));
  862.  
  863.     delete c;
  864. }
  865.  
  866. // @bug 4133509
  867. //
  868. // The sorting using java.text.CollationKey is not in the exact order
  869. //
  870. void CollationRegressionTest::Test4133509(char *par)
  871. {
  872.     static const UChar test1[][CollationRegressionTest::MAX_TOKEN_LEN] =
  873.     {
  874.         {'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', 0}, {'<', 0}, {'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', 'I', 'n', 'I', 'n', 'i', 't', 'i', 'a', 'l', 'i', 'z', 'e', 'r', 'E', 'r', 'r', 'o', 'r', 0},
  875.         {'G', 'r', 'a', 'p', 'h', 'i', 'c', 's', 0},      {'<', 0}, {'G', 'r', 'a', 'p', 'h', 'i', 'c', 's', 'E', 'n', 'v', 'i', 'r', 'o', 'n', 'm', 'e', 'n', 't', 0},
  876.         {'S', 't', 'r', 'i', 'n', 'g', 0},                  {'<', 0}, {'S', 't', 'r', 'i', 'n', 'g', 'B', 'u', 'f', 'f', 'e', 'r', 0}
  877.     };
  878.  
  879.     compareArray(*en_us, test1, ARRAY_LENGTH(test1));
  880. }
  881.  
  882. // @bug 4114077
  883. //
  884. // Collation with decomposition off doesn't work for Europe 
  885. //
  886. void CollationRegressionTest::Test4114077(char *par)
  887. {
  888.     // Ensure that we get the same results with decomposition off
  889.     // as we do with it on....
  890.     
  891.     RuleBasedCollator *c = (RuleBasedCollator *) en_us->clone();
  892.     c->setStrength(Collator::TERTIARY);
  893.     
  894.     static const UChar test1[][CollationRegressionTest::MAX_TOKEN_LEN] =
  895.     {
  896.         {0x00C0, 0},                     {'=', 0}, {'A', 0x0300, 0},            // Should be equivalent
  897.         {'p', 0x00ea, 'c', 'h', 'e', 0}, {'>', 0}, {'p', 0x00e9, 'c', 'h', 0x00e9, 0},
  898.         {0x0204, 0},                     {'=', 0}, {'E', 0x030F, 0},
  899.         {0x01fa, 0},                     {'=', 0}, {'A', 0x030a, 0x0301, 0},    // a-ring-acute -> a-ring, acute
  900.                                                 //   -> a, ring, acute
  901.         {'A', 0x0300, 0x0316, 0},         {'<', 0}, {'A', 0x0316, 0x0300, 0}        // No reordering --> unequal
  902.     };
  903.  
  904.     c->setDecomposition(Normalizer::NO_OP);
  905.     compareArray(*c, test1, ARRAY_LENGTH(test1));
  906.  
  907.     static const UChar test2[][CollationRegressionTest::MAX_TOKEN_LEN] =
  908.     {
  909.         {'A', 0x0300, 0x0316, 0}, {'=', 0}, {'A', 0x0316, 0x0300, 0}      // Reordering --> equal
  910.     };
  911.  
  912.     c->setDecomposition(Normalizer::DECOMP);
  913.     compareArray(*c, test2, ARRAY_LENGTH(test2));
  914.  
  915.     delete c;
  916. }
  917.  
  918. // @bug 4141640
  919. //
  920. // Support for Swedish gone in 1.1.6 (Can't create Swedish collator) 
  921. //
  922. void CollationRegressionTest::Test4141640(char *par)
  923. {
  924.     //
  925.     // Rather than just creating a Swedish collator, we might as well
  926.     // try to instantiate one for every locale available on the system
  927.     // in order to prevent this sort of bug from cropping up in the future
  928.     //
  929.     UErrorCode status = U_ZERO_ERROR;
  930.     int32_t i, localeCount;
  931.     const Locale *locales = Locale::getAvailableLocales(localeCount);
  932.     
  933.     for (i = 0; i < localeCount; i += 1)
  934.     {
  935.         Collator *c = NULL;
  936.         
  937.         c = Collator::createInstance(locales[i], status);
  938.  
  939.         if (c == NULL || U_FAILURE(status))
  940.         {
  941.             UnicodeString msg, localeName;
  942.  
  943.             msg += "Could not create collator for locale ";
  944.             msg += locales[i].getName(localeName);
  945.  
  946.             errln(msg);
  947.         }
  948.  
  949.         delete c;
  950.     }
  951. }
  952.  
  953. // @bug 4139572
  954. //
  955. // getCollationKey throws exception for spanish text 
  956. // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6
  957. //
  958. void CollationRegressionTest::Test4139572(char *par)
  959. {
  960.     //
  961.     // Code pasted straight from the bug report
  962.     // (and then translated to C++ ;-)
  963.     //
  964.     // create spanish locale and collator
  965.     UErrorCode status = U_ZERO_ERROR;
  966.     Locale l("es", "es");
  967.     Collator *col = NULL;
  968.     
  969.     col = Collator::createInstance(l, status);
  970.  
  971.     if (col == NULL || U_FAILURE(status))
  972.     {
  973.         errln("Failed to create a collator for es_es locale.");
  974.         delete col;
  975.         return;
  976.     }
  977.  
  978.     CollationKey key;
  979.  
  980.     // this spanish phrase kills it!
  981.     col->getCollationKey("Nombre De Objeto", key, status);
  982.  
  983.     if (key.isBogus() || U_FAILURE(status))
  984.     {
  985.         errln("Error creating CollationKey for \"Nombre De Ojbeto\"");
  986.     }
  987.  
  988.     delete col;
  989. }
  990.  
  991. class My4146160Collator : public RuleBasedCollator
  992. {
  993. public:
  994.     My4146160Collator(RuleBasedCollator &rbc, UErrorCode &status);
  995.     ~My4146160Collator();
  996.  
  997.     CollationElementIterator *createCollationElementIterator(const UnicodeString &text) const;
  998.  
  999.     CollationElementIterator *createCollationElementIterator(const CharacterIterator &text) const;
  1000.     
  1001.     static int32_t count;
  1002. };
  1003.  
  1004. int32_t My4146160Collator::count = 0;
  1005.  
  1006. My4146160Collator::My4146160Collator(RuleBasedCollator &rbc, UErrorCode &status)
  1007.   : RuleBasedCollator(rbc.getRules(), status)
  1008. {
  1009. }
  1010.  
  1011. My4146160Collator::~My4146160Collator()
  1012. {
  1013. }
  1014.  
  1015. CollationElementIterator *My4146160Collator::createCollationElementIterator(const UnicodeString &text) const
  1016. {
  1017.     count += 1;
  1018.     return RuleBasedCollator::createCollationElementIterator(text);
  1019. }
  1020.  
  1021. CollationElementIterator *My4146160Collator::createCollationElementIterator(const CharacterIterator &text) const
  1022. {
  1023.     count += 1;
  1024.     return RuleBasedCollator::createCollationElementIterator(text);
  1025. }
  1026.  
  1027. // @bug 4146160
  1028. //
  1029. // RuleBasedCollator doesn't use createCollationElementIterator internally
  1030. //
  1031. void CollationRegressionTest::Test4146160(char *par)
  1032. {
  1033.     //
  1034.     // Use a custom collator class whose createCollationElementIterator
  1035.     // methods increment a count....
  1036.     //
  1037.     UErrorCode status = U_ZERO_ERROR;
  1038.     CollationKey key;
  1039.  
  1040.     My4146160Collator::count = 0;
  1041.     My4146160Collator *mc = NULL;
  1042.     
  1043.     mc = new My4146160Collator(*en_us, status);
  1044.  
  1045.     if (mc == NULL || U_FAILURE(status))
  1046.     {
  1047.         errln("Failed to create a My4146160Collator.");
  1048.         delete mc;
  1049.         return;
  1050.     }
  1051.  
  1052.     mc->getCollationKey("1", key, status);
  1053.  
  1054.     if (key.isBogus() || U_FAILURE(status))
  1055.     {
  1056.         errln("Failure to get a CollationKey from a My4146160Collator.");
  1057.         delete mc;
  1058.         return;
  1059.     }
  1060.  
  1061.     if (My4146160Collator::count < 1)
  1062.     {
  1063.         errln("My4146160Collator::createCollationElementIterator not called for getCollationKey");
  1064.     }
  1065.  
  1066.     My4146160Collator::count = 0;
  1067.     mc->compare("1", "2");
  1068.  
  1069.     if (My4146160Collator::count < 1)
  1070.     {
  1071.         errln("My4146160Collator::createtCollationElementIterator not called for compare");
  1072.     }
  1073.  
  1074.     delete mc;
  1075. }
  1076.  
  1077. void CollationRegressionTest::compareArray(Collator &c,
  1078.                                            const UChar tests[][CollationRegressionTest::MAX_TOKEN_LEN],
  1079.                                            int32_t testCount)
  1080. {
  1081.     int32_t i;
  1082.     Collator::EComparisonResult expectedResult = Collator::EQUAL;
  1083.  
  1084.     for (i = 0; i < testCount; i += 3)
  1085.     {
  1086.         UnicodeString source(tests[i]);
  1087.         UnicodeString comparison(tests[i + 1]);
  1088.         UnicodeString target(tests[i + 2]);
  1089.  
  1090.         if (comparison == "<")
  1091.         {
  1092.             expectedResult = Collator::LESS;
  1093.         }
  1094.         else if (comparison == ">")
  1095.         {
  1096.             expectedResult = Collator::GREATER;
  1097.         }
  1098.         else if (comparison == "=")
  1099.         {
  1100.             expectedResult = Collator::EQUAL;
  1101.         }
  1102.         else
  1103.         {
  1104.             UnicodeString bogus1("Bogus comparison string \"");
  1105.             UnicodeString bogus2("\"");
  1106.             errln(bogus1 + comparison + bogus2);
  1107.         }
  1108.  
  1109.         Collator::EComparisonResult compareResult = c.compare(source, target);
  1110.  
  1111.         CollationKey sourceKey, targetKey;
  1112.         UErrorCode status = U_ZERO_ERROR;
  1113.  
  1114.         c.getCollationKey(source, sourceKey, status);
  1115.  
  1116.         if (U_FAILURE(status))
  1117.         {
  1118.             errln("Couldn't get collationKey for source");
  1119.             continue;
  1120.         }
  1121.  
  1122.         c.getCollationKey(target, targetKey, status);
  1123.  
  1124.         if (U_FAILURE(status))
  1125.         {
  1126.             errln("Couldn't get collationKey for target");
  1127.             continue;
  1128.         }
  1129.  
  1130.         Collator::EComparisonResult keyResult = sourceKey.compareTo(targetKey);
  1131.  
  1132.         reportCResult(source, target, sourceKey, targetKey,
  1133.                       compareResult, keyResult, expectedResult);
  1134.  
  1135.     }
  1136. }
  1137.  
  1138. void CollationRegressionTest::assertEqual(CollationElementIterator &i1, CollationElementIterator &i2)
  1139. {
  1140.     int32_t c1, c2, count = 0;
  1141.     UErrorCode status = U_ZERO_ERROR;
  1142.  
  1143.     do
  1144.     {
  1145.         c1 = i1.next(status);
  1146.         c2 = i2.next(status);
  1147.  
  1148.         if (c1 != c2)
  1149.         {
  1150.             UnicodeString msg, msg1("    ");
  1151.             
  1152.             msg += msg1 + count;
  1153.             msg += ": strength(0x";
  1154.             appendHex(c1, 8, msg);
  1155.             msg += ") != strength(0x";
  1156.             appendHex(c2, 8, msg);
  1157.             msg += ")";
  1158.  
  1159.             errln(msg);
  1160.             break;
  1161.         }
  1162.  
  1163.         count += 1;
  1164.     }
  1165.     while (c1 != CollationElementIterator::NULLORDER);
  1166. }
  1167.  
  1168. void CollationRegressionTest::runIndexedTest(int32_t index, bool_t exec, char* &name, char* par)
  1169. {
  1170.     if (exec)
  1171.     {
  1172.         logln("Collation Regression Tests: ");
  1173.     }
  1174.  
  1175.     switch (index)
  1176.     {
  1177.         case  0: name = "Test4048446"; if (exec) Test4048446(par); break;
  1178.         case  1: name = "Test4051866"; if (exec) Test4051866(par); break;
  1179.         case  2: name = "Test4053636"; if (exec) Test4053636(par); break;
  1180.         case  3: name = "Test4054238"; if (exec) Test4054238(par); break;
  1181.         case  4: name = "Test4054734"; if (exec) Test4054734(par); break;
  1182.         case  5: name = "Test4054736"; if (exec) Test4054736(par); break;
  1183.         case  6: name = "Test4058613"; if (exec) Test4058613(par); break;
  1184.         case  7: name = "Test4059820"; if (exec) Test4059820(par); break;
  1185.         case  8: name = "Test4060154"; if (exec) Test4060154(par); break;
  1186.         case  9: name = "Test4062418"; if (exec) Test4062418(par); break;
  1187.         case 10: name = "Test4065540"; if (exec) Test4065540(par); break;
  1188.         case 11: name = "Test4066189"; if (exec) Test4066189(par); break;
  1189.         case 12: name = "Test4066696"; if (exec) Test4066696(par); break;
  1190.         case 13: name = "Test4076676"; if (exec) Test4076676(par); break;
  1191.         case 14: name = "Test4078588"; if (exec) Test4078588(par); break;
  1192.         case 15: name = "Test4079231"; if (exec) Test4079231(par); break;
  1193.         case 16: name = "Test4081866"; if (exec) Test4081866(par); break;
  1194.         case 17: name = "Test4087241"; if (exec) Test4087241(par); break;
  1195.         case 18: name = "Test4087243"; if (exec) Test4087243(par); break;
  1196.         case 19: name = "Test4092260"; if (exec) Test4092260(par); break;
  1197.         case 20: name = "Test4095316"; if (exec) Test4095316(par); break;
  1198.         case 21: name = "Test4101940"; if (exec) Test4101940(par); break;
  1199.         case 22: name = "Test4103436"; if (exec) Test4103436(par); break;
  1200.         case 23: name = "Test4114076"; if (exec) Test4114076(par); break;
  1201.         case 24: name = "Test4114077"; if (exec) Test4114077(par); break;
  1202.         case 25: name = "Test4124632"; if (exec) Test4124632(par); break;
  1203.         case 26: name = "Test4132736"; if (exec) Test4132736(par); break;
  1204.         case 27: name = "Test4133509"; if (exec) Test4133509(par); break;
  1205.         case 28: name = "Test4139572"; if (exec) Test4139572(par); break;
  1206.         case 29: name = "Test4141640"; if (exec) Test4141640(par); break;
  1207.         case 30: name = "Test4146160"; if (exec) Test4146160(par); break;
  1208.         default: name = ""; break;
  1209.     }
  1210. }
  1211.  
  1212.