home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / itercoll.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  13.9 KB  |  558 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 _ITERCOLL
  30. #include "itercoll.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 CollationIteratorTest::test1 = "What subset of all possible test cases?";
  38. const UnicodeString CollationIteratorTest::test2 = "has the highest probability of detecting";
  39.  
  40. CollationIteratorTest::CollationIteratorTest()
  41. {
  42.     en_us = (RuleBasedCollator *)Collator::createInstance(Locale::US, status);
  43. }
  44.  
  45. CollationIteratorTest::~CollationIteratorTest()
  46. {
  47.     delete en_us;
  48. }
  49.  
  50. /**
  51.  * Test for CollationElementIterator.previous()
  52.  *
  53.  * @bug 4108758 - Make sure it works with contracting characters
  54.  * 
  55.  */
  56. void CollationIteratorTest::TestPrevious(char *par)
  57. {
  58.     UErrorCode status = U_ZERO_ERROR;
  59.     CollationElementIterator *iter = en_us->createCollationElementIterator(test1);
  60.  
  61.     // A basic test to see if it's working at all
  62.     backAndForth(*iter);
  63.     delete iter;
  64.  
  65.     // Test with a contracting character sequence
  66.     UnicodeString source;
  67.     RuleBasedCollator *c1 = NULL;
  68.     c1 = new RuleBasedCollator(
  69.         "< a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH", status);
  70.  
  71.     if (c1 == NULL || U_FAILURE(status))
  72.     {
  73.         errln("Couldn't create a RuleBasedCollator with a contracting sequence.");
  74.         delete c1;
  75.         return;
  76.     }
  77.  
  78.     source = "abchdcba";
  79.     iter = c1->createCollationElementIterator(source);
  80.     backAndForth(*iter);
  81.     delete iter;
  82.     delete c1;
  83.  
  84.     // Test with an expanding character sequence
  85.     RuleBasedCollator *c2 = NULL;
  86.     c2 = new RuleBasedCollator("< a < b < c/abd < d", status);
  87.  
  88.     if (c2 == NULL || U_FAILURE(status))
  89.     {
  90.         errln("Couldn't create a RuleBasedCollator with an expanding sequence.");
  91.         delete c2;
  92.         return;
  93.     }
  94.  
  95.     source = "abcd";
  96.     iter = c2->createCollationElementIterator(source);
  97.     backAndForth(*iter);
  98.     delete iter;
  99.     delete c2;
  100.  
  101.     // Now try both
  102.     RuleBasedCollator *c3 = NULL;
  103.     c3 = new RuleBasedCollator("< a < b < c/aba < d < z < ch", status);
  104.  
  105.     if (c3 == NULL || U_FAILURE(status))
  106.     {
  107.         errln("Couldn't create a RuleBasedCollator with both an expanding and a contracting sequence.");
  108.         delete c3;
  109.         return;
  110.     }
  111.  
  112.     source = "abcdbchdc";
  113.     iter = c3->createCollationElementIterator(source);
  114.     backAndForth(*iter);
  115.     delete iter;
  116.     delete c3;
  117. }
  118.  
  119. /**
  120.  * Test for getOffset() and setOffset()
  121.  */
  122. void CollationIteratorTest::TestOffset(char *par)
  123. {
  124.     CollationElementIterator *iter = en_us->createCollationElementIterator(test1);
  125.  
  126.     // Run all the way through the iterator, then get the offset
  127.     int32_t orderLength = 0;
  128.     int32_t *orders = getOrders(*iter, orderLength);
  129.  
  130.     int32_t offset = iter->getOffset();
  131.  
  132.     if (offset != test1.size())
  133.     {
  134.         UnicodeString msg1("offset at end != length: ");
  135.         UnicodeString msg2(" vs ");
  136.  
  137.         errln(msg1 + offset + msg2 + test1.size());
  138.     }
  139.  
  140.     // Now set the offset back to the beginning and see if it works
  141.     CollationElementIterator *pristine = en_us->createCollationElementIterator(test1);
  142.     UErrorCode status = U_ZERO_ERROR;
  143.  
  144.     iter->setOffset(0, status);
  145.  
  146.     if (U_FAILURE(status))
  147.     {
  148.         errln("setOffset failed.");
  149.     }
  150.     else
  151.     {
  152.         assertEqual(*iter, *pristine);
  153.     }
  154.  
  155.     // TODO: try iterating halfway through a messy string.
  156.  
  157.     delete pristine;
  158.     delete[] orders;
  159.     delete iter;
  160. }
  161.  
  162. /**
  163.  * Test for setText()
  164.  */
  165. void CollationIteratorTest::TestSetText(char *par)
  166. {
  167.     CollationElementIterator *iter1 = en_us->createCollationElementIterator(test1);
  168.     CollationElementIterator *iter2 = en_us->createCollationElementIterator(test2);
  169.     UErrorCode status = U_ZERO_ERROR;
  170.  
  171.     // Run through the second iterator just to exercise it
  172.     int32_t c = iter2->next(status);
  173.     int32_t i = 0;
  174.  
  175.     while ( ++i < 10 && c != CollationElementIterator::NULLORDER)
  176.     {
  177.         if (U_FAILURE(status))
  178.         {
  179.             errln("iter2->next() returned an error.");
  180.             delete iter2;
  181.             delete iter1;
  182.         }
  183.  
  184.         c = iter2->next(status);
  185.     }
  186.  
  187.     // Now set it to point to the same string as the first iterator
  188.     iter2->setText(test1, status);
  189.  
  190.     if (U_FAILURE(status))
  191.     {
  192.         errln("call to inter2->setText(test1) failed.");
  193.     }
  194.     else
  195.     {
  196.         assertEqual(*iter1, *iter2);
  197.     }
  198.  
  199.     delete iter2;
  200.     delete iter1;
  201. }
  202.  
  203. /** @bug 4108762
  204.  * Test for getMaxExpansion()
  205.  */
  206. void CollationIteratorTest::TestMaxExpansion(char *par)
  207. {
  208.     // Try a simple one first:
  209.     // The only expansion ends with 'e' and has length 2
  210.     UnicodeString rule1("< a & ae = ");
  211.     rule1 += (UChar)0x00e4;
  212.     rule1 += " < b < e";
  213.     ExpansionRecord test1[] =
  214.     {
  215.         {'a', 1},
  216.         {'b', 1},
  217.         {'e', 2}
  218.     };
  219.     verifyExpansion(rule1, test1, ARRAY_LENGTH(test1));
  220.     
  221.     // Now a more complicated one:
  222.     //   "a1" --> "ae"
  223.     //   "z" --> "aeef"
  224.     //
  225.     UnicodeString rule2("< a & ae = a1 & aeef = z < b < e < f");
  226.     ExpansionRecord test2[] =
  227.     {
  228.         {'a', 1},
  229.         {'b', 1},
  230.         {'e', 2},
  231.         {'f', 4}
  232.     };
  233.     verifyExpansion(rule2, test2, ARRAY_LENGTH(test2));
  234. }
  235.  
  236. /*
  237.  * @bug 4157299
  238.  */
  239. void CollationIteratorTest::TestClearBuffers(char *par)
  240. {
  241.     UErrorCode status = U_ZERO_ERROR;
  242.     RuleBasedCollator *c = NULL;
  243.     c = new RuleBasedCollator("< a < b < c & ab = d", status);
  244.  
  245.     if (c == NULL || U_FAILURE(status))
  246.     {
  247.         errln("Couldn't create a RuleBasedCollator.");
  248.         delete c;
  249.         return;
  250.     }
  251.  
  252.     UnicodeString source("abcd");
  253.     CollationElementIterator *i = c->createCollationElementIterator(source);
  254.     int32_t e0 = i->next(status);    // save the first collation element
  255.  
  256.     if (U_FAILURE(status))
  257.     {
  258.         errln("call to i->next() failed");
  259.         goto bail;
  260.     }
  261.  
  262.     i->setOffset(3, status);        // go to the expanding character
  263.  
  264.     if (U_FAILURE(status))
  265.     {
  266.         errln("call to i->setOffset(3) failed");
  267.         goto bail;
  268.     }
  269.  
  270.     i->next(status);                // but only use up half of it
  271.  
  272.     if (U_FAILURE(status))
  273.     {
  274.         errln("call to i->next() failed");
  275.         goto bail;
  276.     }
  277.  
  278.     i->setOffset(0, status);        // go back to the beginning
  279.  
  280.     if (U_FAILURE(status))
  281.     {
  282.         errln("call to i->setOffset(0) failed");
  283.         goto bail;
  284.     }
  285.  
  286.     {
  287.         // This is in it's own block to stop a stupid compiler
  288.         // error about the goto's skipping the initialization
  289.         // of e...
  290.         int32_t e = i->next(status);    // and get this one again
  291.  
  292.         if (U_FAILURE(status))
  293.         {
  294.             errln("call to i->next() failed.");
  295.             goto bail;
  296.         }
  297.  
  298.         if (e != e0)
  299.         {
  300.             UnicodeString msg;
  301.             
  302.             msg += "got 0x";
  303.             appendHex(e, 8, msg);
  304.             msg += ", expected 0x";
  305.             appendHex(e0, 8, msg);
  306.  
  307.             errln(msg);
  308.         }
  309.     }
  310.  
  311. bail:
  312.     delete i;
  313.     delete c;
  314. }
  315.  
  316. void CollationIteratorTest::backAndForth(CollationElementIterator &iter)
  317. {
  318.     // Run through the iterator forwards and stick it into an array
  319.     int32_t orderLength = 0;
  320.     int32_t *orders = getOrders(iter, orderLength);
  321.     UErrorCode status = U_ZERO_ERROR;
  322.  
  323.     // Now go through it backwards and make sure we get the same values
  324.     int32_t index = orderLength;
  325.     int32_t o;
  326.  
  327.     while ((o = iter.previous(status)) != CollationElementIterator::NULLORDER)
  328.     {
  329.         if (o != orders[--index])
  330.         {
  331.             UnicodeString msg1("Mismatch at index ");
  332.             UnicodeString msg2(": 0x");
  333.             appendHex(orders[index], 8, msg2);
  334.             msg2 += " vs 0x";
  335.             appendHex(o, 8, msg2);
  336.  
  337.             errln(msg1 + index + msg2);
  338.             break;
  339.         }
  340.     }
  341.  
  342.     if (index != 0)
  343.     {
  344.         UnicodeString msg("Didn't get back to beginning - index is ");
  345.         errln(msg + index);
  346.  
  347.         iter.reset();
  348.         err("next: ");
  349.         while ((o = iter.next(status)) != CollationElementIterator::NULLORDER)
  350.         {
  351.             UnicodeString hexString("0x");
  352.  
  353.             appendHex(0, 8, hexString);
  354.             hexString += " ";
  355.             err(hexString);
  356.         }
  357.         errln("");
  358.  
  359.         err("prev: ");
  360.         while ((o = iter.previous(status)) != CollationElementIterator::NULLORDER)
  361.         {
  362.             UnicodeString hexString("0x");
  363.  
  364.             appendHex(o, 8, hexString);
  365.             hexString += " ";
  366.              err(hexString);
  367.         }
  368.         errln("");
  369.     }
  370.  
  371.     delete[] orders;
  372. }
  373.  
  374. /**
  375.  * Verify that getMaxExpansion works on a given set of collation rules
  376.  *
  377.  * The first row of the "tests" array contains the collation rules
  378.  * at index 0, and the string at index 1 is ignored.
  379.  *
  380.  * Subsequent rows of the array contain a character and a number, both
  381.  * represented as strings.  The character's collation order is determined,
  382.  * and getMaxExpansion is called for that character.  If its value is
  383.  * not equal to the specified number, an error results.
  384.  */
  385. void CollationIteratorTest::verifyExpansion(UnicodeString rules, ExpansionRecord tests[], int32_t testCount)
  386. {
  387.     UErrorCode status = U_ZERO_ERROR;
  388.     RuleBasedCollator *coll = NULL;
  389.     coll = new RuleBasedCollator(rules, status);
  390.  
  391.     if (coll == NULL || U_FAILURE(status))
  392.     {
  393.         errln("Couldn't create a RuleBasedCollator.");
  394.         delete coll;
  395.         return;
  396.     }
  397.  
  398.     UnicodeString source("");
  399.     CollationElementIterator *iter = coll->createCollationElementIterator(source);
  400.  
  401.     int32_t i;
  402.     for (i = 1; i < testCount; i += 1)
  403.     {
  404.         // First get the collation key that the test string expands to
  405.         UnicodeString test(&tests[i].character, 1);
  406.         iter->setText(test, status);
  407.  
  408.         if (U_FAILURE(status))
  409.         {
  410.             errln("call to iter->setText() failed.");
  411.             return;
  412.         }
  413.         
  414.         int32_t order = iter->next(status);
  415.  
  416.         if (U_FAILURE(status))
  417.         {
  418.             errln("call to iter->next() failed.");
  419.             return;
  420.         }
  421.         
  422.         if (order == CollationElementIterator::NULLORDER || iter->next(status) != CollationElementIterator::NULLORDER)
  423.         {
  424.             UnicodeString msg("verifyExpansion: '");
  425.             
  426.             msg += test;
  427.             msg += "' has multiple orders:";
  428.             orderString(*iter, msg);
  429.  
  430.             iter->reset();
  431.             errln(msg);
  432.         }
  433.         
  434.         int32_t expansion = iter->getMaxExpansion(order);
  435.         int32_t expect = tests[i].count;
  436.         
  437.         if (expansion != expect)
  438.         {
  439.             UnicodeString msg1("expansion for '");
  440.             
  441.             msg1 += test;
  442.             msg1 += "' is wrong: expected ";
  443.  
  444.             UnicodeString msg2(", got ");
  445.  
  446.             errln(msg1 + expect + msg2 + expansion);
  447.         }
  448.     }
  449. }
  450.  
  451. /**
  452.  * Return an integer array containing all of the collation orders
  453.  * returned by calls to next on the specified iterator
  454.  */
  455. int32_t *CollationIteratorTest::getOrders(CollationElementIterator &iter, int32_t &orderLength)
  456. {
  457.     int32_t maxSize = 100;
  458.     int32_t size = 0;
  459.     int32_t *orders = new int32_t[maxSize];
  460.     UErrorCode status = U_ZERO_ERROR;
  461.  
  462.     int32_t order;
  463.     while ((order = iter.next(status)) != CollationElementIterator::NULLORDER)
  464.     {
  465.         if (size == maxSize)
  466.         {
  467.             maxSize *= 2;
  468.             int32_t *temp = new int32_t[maxSize];
  469.  
  470.             memcpy(temp, orders, size * sizeof(int32_t));
  471.             delete[] orders;
  472.             orders = temp;
  473.         }
  474.  
  475.         orders[size++] = order;
  476.     }
  477.  
  478.     if (maxSize > size)
  479.     {
  480.         int32_t *temp = new int32_t[size];
  481.  
  482.         memcpy(temp, orders, size * sizeof(int32_t));
  483.         delete[] orders;
  484.         orders = temp;
  485.     }
  486.  
  487.     orderLength = size;
  488.     return orders;
  489. }
  490.  
  491. /**
  492.  * Return a string containing all of the collation orders
  493.  * returned by calls to next on the specified iterator
  494.  */
  495. UnicodeString &CollationIteratorTest::orderString(CollationElementIterator &iter, UnicodeString &target)
  496. {
  497.     int32_t order;
  498.     UErrorCode status = U_ZERO_ERROR;
  499.  
  500.     while ((order = iter.next(status)) != CollationElementIterator::NULLORDER)
  501.     {
  502.         target += "0x";
  503.         appendHex(order, 8, target);
  504.         target += " ";
  505.     }
  506.  
  507.     return target;
  508. }
  509.  
  510. void CollationIteratorTest::assertEqual(CollationElementIterator &i1, CollationElementIterator &i2)
  511. {
  512.     int32_t c1, c2, count = 0;
  513.     UErrorCode status = U_ZERO_ERROR;
  514.  
  515.     do
  516.     {
  517.         c1 = i1.next(status);
  518.         c2 = i2.next(status);
  519.  
  520.         if (c1 != c2)
  521.         {
  522.             UnicodeString msg, msg1("    ");
  523.             
  524.             msg += msg1 + count;
  525.             msg += ": strength(0x";
  526.             appendHex(c1, 8, msg);
  527.             msg += ") != strength(0x";
  528.             appendHex(c2, 8, msg);
  529.             msg += ")";
  530.  
  531.             errln(msg);
  532.             break;
  533.         }
  534.  
  535.         count += 1;
  536.     }
  537.     while (c1 != CollationElementIterator::NULLORDER);
  538. }
  539.  
  540. void CollationIteratorTest::runIndexedTest(int32_t index, bool_t exec, char* &name, char* par)
  541. {
  542.     if (exec)
  543.     {
  544.         logln("Collation Iteration Tests: ");
  545.     }
  546.  
  547.     switch (index)
  548.     {
  549.         case  0: name = "TestPrevious";        if (exec) TestPrevious(par);     break;
  550.         case  1: name = "TestOffset";        if (exec) TestOffset(par);         break;
  551.         case  2: name = "TestSetText";        if (exec) TestSetText(par);         break;
  552.         case  3: name = "TestMaxExpansion";    if (exec) TestMaxExpansion(par); break;
  553.         case  4: name = "TestClearBuffers"; if (exec) TestClearBuffers(par); break;
  554.         default: name = ""; break;
  555.     }
  556. }
  557.  
  558.