1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/********************************************************************
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * COPYRIGHT:
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius * Copyright (c) 2002-2012, International Business Machines Corporation and
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ********************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @author Mark E. Davis
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @author Vladimir Weinstein
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_NORMALIZATION
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "intltest.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "canittst.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/caniter.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/normlzr.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uchar.h"
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "hash.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ARRAY_LENGTH(array) ((int32_t)(sizeof (array) / sizeof (*array)))
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CASE(id,test) case id:                          \
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          name = #test;                 \
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          if (exec) {                   \
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              logln(#test "---");       \
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              logln((UnicodeString)""); \
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              test();                   \
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          }                             \
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          break
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CanonicalIteratorTest::runIndexedTest(int32_t index, UBool exec,
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                         const char* &name, char* /*par*/) {
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (index) {
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CASE(0, TestBasic);
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CASE(1, TestExhaustive);
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CASE(2, TestAPI);
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      default: name = ""; break;
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UnicodeString str(const char *input)
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString str(input, ""); // Invariant conversion
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return str.unescape();
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCanonicalIteratorTest::CanonicalIteratorTest() :
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerunameTrans(NULL), hexTrans(NULL)
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCanonicalIteratorTest::~CanonicalIteratorTest()
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_TRANSLITERATION
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(nameTrans != NULL) {
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete(nameTrans);
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(hexTrans != NULL) {
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete(hexTrans);
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CanonicalIteratorTest::TestExhaustive() {
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CanonicalIterator it("", status);
7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (U_FAILURE(status)) {
7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        dataerrln("Error creating CanonicalIterator: %s", u_errorName(status));
7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar32 i = 0;
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString s;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Test static and dynamic class IDs
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(it.getDynamicClassID() != CanonicalIterator::getStaticClassID()){
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("CanonicalIterator::getStaticClassId ! = CanonicalIterator.getDynamicClassID");
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i = 0; i < 0x10FFFF; quick?i+=0x10:++i) {
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //for (i = 0xae00; i < 0xaf00; ++i) {
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((i % 0x100) == 0) {
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logln("Testing U+%06X", i);
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // skip characters we know don't have decomps
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int8_t type = u_charType(i);
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (type == U_UNASSIGNED || type == U_PRIVATE_USE_CHAR
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            || type == U_SURROGATE) continue;
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        s = i;
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        characterTest(s, i, it);
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        s += (UChar32)0x0345; //"\\u0345";
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        characterTest(s, i, it);
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CanonicalIteratorTest::TestBasic() {
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const char * const testArray[][2] = {
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {"\\u00C5d\\u0307\\u0327", "A\\u030Ad\\u0307\\u0327, A\\u030Ad\\u0327\\u0307, A\\u030A\\u1E0B\\u0327, "
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "A\\u030A\\u1E11\\u0307, \\u00C5d\\u0307\\u0327, \\u00C5d\\u0327\\u0307, "
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\\u00C5\\u1E0B\\u0327, \\u00C5\\u1E11\\u0307, \\u212Bd\\u0307\\u0327, "
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            "\\u212Bd\\u0327\\u0307, \\u212B\\u1E0B\\u0327, \\u212B\\u1E11\\u0307"},
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {"\\u010d\\u017E", "c\\u030Cz\\u030C, c\\u030C\\u017E, \\u010Dz\\u030C, \\u010D\\u017E"},
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {"x\\u0307\\u0327", "x\\u0307\\u0327, x\\u0327\\u0307, \\u1E8B\\u0327"},
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This is not interesting for C/C++ as the data is already built beforehand
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check build
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeSet ss = CanonicalIterator.getSafeStart();
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("Safe Start: " + ss.toPattern(true));
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ss = CanonicalIterator.getStarts('a');
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    expectEqual("Characters with 'a' at the start of their decomposition: ", "", CanonicalIterator.getStarts('a'),
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        new UnicodeSet("[\u00E0-\u00E5\u0101\u0103\u0105\u01CE\u01DF\u01E1\u01FB"
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        + "\u0201\u0203\u0227\u1E01\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7]")
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            );
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check permute
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NOTE: we use a TreeSet below to sort the output, which is not guaranteed to be sorted!
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Hashtable *permutations = new Hashtable(FALSE, status);
133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    permutations->setValueDeleter(uprv_deleteUObject);
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString toPermute("ABC");
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CanonicalIterator::permute(toPermute, FALSE, permutations, status);
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("testing permutation");
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    expectEqual("Simple permutation ", "", collectionToString(permutations), "ABC, ACB, BAC, BCA, CAB, CBA");
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete permutations;
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // try samples
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("testing samples");
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Hashtable *set = new Hashtable(FALSE, status);
147103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    set->setValueDeleter(uprv_deleteUObject);
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i = 0;
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CanonicalIterator it("", status);
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_SUCCESS(status)) {
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      for (i = 0; i < ARRAY_LENGTH(testArray); ++i) {
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          //logln("Results for: " + name.transliterate(testArray[i]));
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          UnicodeString testStr = CharsToUnicodeString(testArray[i][0]);
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          it.setSource(testStr, status);
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          set->removeAll();
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          for (;;) {
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              //UnicodeString *result = new UnicodeString(it.next());
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UnicodeString result(it.next());
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              if (result.isBogus()) {
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  break;
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              }
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              set->put(result, new UnicodeString(result), status); // Add result to the table
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              //logln(++counter + ": " + hex.transliterate(result));
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              //logln(" = " + name.transliterate(result));
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
1668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius          expectEqual(i + UnicodeString(": "), testStr, collectionToString(set), CharsToUnicodeString(testArray[i][1]));
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      dataerrln("Couldn't instantiate canonical iterator. Error: %s", u_errorName(status));
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete set;
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CanonicalIteratorTest::characterTest(UnicodeString &s, UChar32 ch, CanonicalIterator &it)
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString decomp, comp;
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool gotDecomp = FALSE;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool gotComp = FALSE;
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool gotSource = FALSE;
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Normalizer::decompose(s, FALSE, 0, decomp, status);
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Normalizer::compose(s, FALSE, 0, comp, status);
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // skip characters that don't have either decomp.
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // need quick test for this!
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (s == decomp && s == comp) {
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    it.setSource(s, status);
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;) {
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString item = it.next();
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item.isBogus()) break;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item == s) gotSource = TRUE;
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item == decomp) gotDecomp = TRUE;
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item == comp) gotComp = TRUE;
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!gotSource || !gotDecomp || !gotComp) {
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("FAIL CanonicalIterator: " + s + (int)ch);
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CanonicalIteratorTest::expectEqual(const UnicodeString &message, const UnicodeString &item, const UnicodeString &a, const UnicodeString &b) {
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!(a==b)) {
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("FAIL: " + message + getReadable(item));
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("\t" + getReadable(a));
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("\t" + getReadable(b));
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("Checked: " + message + getReadable(item));
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("\t" + getReadable(a));
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("\t" + getReadable(b));
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString CanonicalIteratorTest::getReadable(const UnicodeString &s) {
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString result = "[";
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (s.length() == 0) return "";
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // set up for readable display
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_TRANSLITERATION
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(verbose) {
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (nameTrans == NULL)
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          nameTrans = Transliterator::createInstance("[^\\ -\\u007F] name", UTRANS_FORWARD, status);
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      UnicodeString sName = s;
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      nameTrans->transliterate(sName);
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result += sName;
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result += ";";
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (hexTrans == NULL)
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hexTrans = Transliterator::createInstance("[^\\ -\\u007F] hex", UTRANS_FORWARD, status);
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString sHex = s;
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_TRANSLITERATION
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(hexTrans) { // maybe there is no data and transliterator cannot be instantiated
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      hexTrans->transliterate(sHex);
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    result += sHex;
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    result += "]";
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //return "[" + (verbose ? name->transliterate(s) + "; " : "") + hex->transliterate(s) + "]";
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC int U_CALLCONV
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucompareUnicodeStrings(const void *s1, const void *s2) {
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString **st1 = (UnicodeString **)s1;
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString **st2 = (UnicodeString **)s2;
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return (*st1)->compare(**st2);
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString CanonicalIteratorTest::collectionToString(Hashtable *col) {
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Iterate over the Hashtable, then qsort.
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString **resArray = new UnicodeString*[col->count()];
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i = 0;
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UHashElement *ne = NULL;
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t el = -1;
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //Iterator it = basic.iterator();
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ne = col->nextElement(el);
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //while (it.hasNext())
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (ne != NULL) {
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      //String item = (String) it.next();
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      UnicodeString *item = (UnicodeString *)(ne->value.pointer);
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      resArray[i++] = item;
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ne = col->nextElement(el);
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i = 0; i<col->count(); ++i) {
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      logln(*resArray[i]);
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    qsort(resArray, col->count(), sizeof(UnicodeString *), compareUnicodeStrings);
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    result = *resArray[0];
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i = 1; i<col->count(); ++i) {
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result += ", ";
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result += *resArray[i];
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Iterator it = col.iterator();
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (it.hasNext()) {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (result.length() != 0) result.append(", ");
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.append(it.next().toString());
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete [] resArray;
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CanonicalIteratorTest::TestAPI() {
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Test reset and getSource
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString start("ljubav");
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("Testing CanonicalIterator::getSource");
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("Instantiating canonical iterator with string "+start);
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  CanonicalIterator can(start, status);
31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if (U_FAILURE(status)) {
31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      dataerrln("Error creating CanonicalIterator: %s", u_errorName(status));
31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      return;
31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString source = can.getSource();
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("CanonicalIterator::getSource returned "+source);
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(start != source) {
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    errln("CanonicalIterator.getSource() didn't return the starting string. Expected "+start+", got "+source);
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("Testing CanonicalIterator::reset");
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString next = can.next();
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("CanonicalIterator::next returned "+next);
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  can.reset();
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UnicodeString afterReset = can.next();
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("After reset, CanonicalIterator::next returned "+afterReset);
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(next != afterReset) {
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    errln("Next after instantiation ("+next+") is different from next after reset ("+afterReset+").");
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  logln("Testing getStaticClassID and getDynamicClassID");
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(can.getDynamicClassID() != CanonicalIterator::getStaticClassID()){
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      errln("RTTI failed for CanonicalIterator getDynamicClassID != getStaticClassID");
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_NORMALIZATION */
339